From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1943339C006 for ; Fri, 17 Apr 2026 09:06:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776416793; cv=none; b=omcfmIaweVsVR4ErpIzkU/sdL0uyDEw5hDbku7ztW38uzngnqiijNRaZjLfZV/WUbROfalI0rfdY+QxV5asWSthS4r2jOaXCIzuTbXSvNn66hwONNyycktZwopNpCO4cvF3ZSAt1j+w61pq/xDsygXmZ2k95UJsII5YtlNj0HnE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776416793; c=relaxed/simple; bh=yHSlV7wbuZhkB6l/6Jm38uxkzUQXwj83gXsmbtwjB90=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=c3b/tq/Tyh0gTVryxg+RVYVB54oFRlOnKRFKxWwtNyBTs5pkOkLsMy9t3jQ1aBf1YAPeDGNx6FFTaqlKtlfVvcL+rHSOQFkgTY7TaD1eu+5JKbeQiS2cRgEcTJiNlcMGB7gH7WyO6mgUSI5oLEeFy2s3T0zfjueT1TUQMxY75Bw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=i1fxL07N; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=mlv8HsOg; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="i1fxL07N"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="mlv8HsOg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776416782; 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=EU/7popoIlHXPKNk7AvAbCyKDJyYEaUVqKntEl5TLiQ=; b=i1fxL07N4s1+qXjZmIM4hOiRpORK8zH2RO+ZIagg8ZTJN9C1Q7NMMoXI7rX7hQa1P/XI1a 0Po/3x1ujP83i4umlV6FUZXNlsZlMAI3uaCq2cE8hpXCnRLFeR4iAxPU9FYNlUjZF/0kmr GFeIENjJUgOUbgKOzbfkgRJFTSRIl/I= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-631-YJNgoTQFN3Cx_e3NE_sxIQ-1; Fri, 17 Apr 2026 05:06:20 -0400 X-MC-Unique: YJNgoTQFN3Cx_e3NE_sxIQ-1 X-Mimecast-MFC-AGG-ID: YJNgoTQFN3Cx_e3NE_sxIQ_1776416779 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-4836abfc742so3964985e9.0 for ; Fri, 17 Apr 2026 02:06:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1776416779; x=1777021579; darn=vger.kernel.org; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=EU/7popoIlHXPKNk7AvAbCyKDJyYEaUVqKntEl5TLiQ=; b=mlv8HsOgwIIQkY83qPHZtkfOBRqtjSh8GpytDbUlESt9hmUH4R2imwDOLOEFx9O7H0 ZO/UANA4nPlXQcpn/9puCoLBuu2tmGCUDPXqEBxtlgO/2vy1OmPwluHNNyWnghH81sKT SbYQLkxyRqJFvsJ909gkBErLMk3g1WgX2gsgodLSPVXSd9KVSxYqaP2uktpXRDmZ2iCV gJMlEo9o0RRzbF5NGA1RNIYwR/UtbCp4oqmDOq/hYrZVp1in+FpAOlBikJyWnTgoa0Ko UuHus4rLC6X+UxyjtqpGIWT+1qctDS+8QsnUej+f5Vi6NyxARpR8wSJ9g46eR2ZORMJ8 iKsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776416779; x=1777021579; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=EU/7popoIlHXPKNk7AvAbCyKDJyYEaUVqKntEl5TLiQ=; b=fjFE07huvSko1XgI6Eu+i6q+shItsO/kxTStjLWnl2FL2whfDXDVPnR7D6+jSZf/Qt +HSR56eVVUcL2LQzkWBXn1ogoPL9FYIkUSULflrElkLLMlPWJSDISwZ3yMFpIpgyxSjc ITYYGsgTR7gcOZexsRKzGlkKKlygH+oKPfYlVlqDVGrIdI7mNjjf/IY2gLXDBESUyzI5 IpTxN/OXIJBQDu2T0Gw3utKhG2UC5MieVv6/84Ideqdn7obN9bm3TtTGpbCuClUtOTmU 0t7DLnRrsUp7gBb+6ni9kzX11dnrCLnMKx8KPT7NoHt/YAt/+IAUdD6cTwAN8CaDvNcB MDwQ== X-Forwarded-Encrypted: i=1; AFNElJ+4F9gv/SG5UAlll0KVWQZ1TlR/qlj3lygPu3e8YPUFGNydWuFaAxKUER8g9xNCgyfrhgu8XaE=@vger.kernel.org X-Gm-Message-State: AOJu0YxMsJbhudr97xN8m0SjCg32RbNi/zy3keWG5v7drSoFETcLKpZ7 I05hNED/O87JKwsqdfxLOqWUOLK78aGmTJQF765jW79cEfYc6noHRE86XIGonndEFHBdo7w5bQ5 ToBB/4z43R0iGMQ5CqwCzqIlbpQQjX8RBsxELIaIZN0zNQbTCqhOhQ9dmQg== X-Gm-Gg: AeBDieve+DRs9JbAqP5Ip5Vuz/If9beYI+IkKnWDgyycCeshmrbpw3ATWdw9mRRwLeF T0ZGE7tNFrLHGeIxNIyD7/s1zA904Ak7osDr0Z9DIs2oeSDgSLrPzIs6ainizxIlANfoGz6qi68 ixatrjklGIbF1SXjbkFYO0U0Ou9+oT51/iUXEQ8ZjLw/ToSS4gHLvIo5dBtjbDQDlHE4MZxsT/1 gqKqL36j/VRITXJc3Bd/D+Q+ic4e+FMu9CEP7t6DpW7gwvAsujiBaSlcJrmPWCcglkEaaOCk7St VzdJ6wDOuKOWmldr2ur4b+bL5MAdXY6wPmJzn+a16MZacWOPs7+vEQqNabOmpL4pbryO9xjQNMT MMqGyVajbXSDQIV2B8cJgM2HvOj0RTt40/y21HgdG/KtLt8ygiE6y9A== X-Received: by 2002:a05:600c:c114:b0:488:cc72:5497 with SMTP id 5b1f17b1804b1-488fb78dd55mr21061915e9.31.1776416777731; Fri, 17 Apr 2026 02:06:17 -0700 (PDT) X-Received: by 2002:a05:600c:c114:b0:488:cc72:5497 with SMTP id 5b1f17b1804b1-488fb78dd55mr21060755e9.31.1776416776455; Fri, 17 Apr 2026 02:06:16 -0700 (PDT) Received: from redhat.com (IGLD-80-230-25-21.inter.net.il. [80.230.25.21]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488fc1001bdsm49736405e9.6.2026.04.17.02.06.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 02:06:15 -0700 (PDT) Date: Fri, 17 Apr 2026 05:06:11 -0400 From: "Michael S. Tsirkin" To: Jakub Kicinski Cc: davem@davemloft.net, netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org, alexs@kernel.org, si.yanteng@linux.dev, dzm91@hust.edu.cn, linux@armlinux.org.uk, jasowang@redhat.com, xuanzhuo@linux.alibaba.com, eperezma@redhat.com, xu.xin16@zte.com.cn, wang.yaxin@zte.com.cn, jiang.kun2@zte.com.cn, linusw@kernel.org, jihed.chaibi.dev@gmail.com, arnd@arndb.de, tytso@mit.edu, jiayuan.chen@shopee.com, gregkh@linuxfoundation.org Subject: Re: [PATCH net-deletions] caif: remove CAIF NETWORK LAYER Message-ID: <20260417050558-mutt-send-email-mst@kernel.org> References: <20260416182829.1440262-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20260416182829.1440262-1-kuba@kernel.org> On Thu, Apr 16, 2026 at 11:28:28AM -0700, Jakub Kicinski wrote: > Remove CAIF (Communication CPU to Application CPU Interface), the > ST-Ericsson modem protocol. The subsystem has been orphaned since 2013. > The last meaningful changes from the maintainers were in March 2013: > a8c7687bf216 ("caif_virtio: Check that vringh_config is not null") > b2273be8d2df ("caif_virtio: Use vringh_notify_enable correctly") > 0d2e1a2926b1 ("caif_virtio: Introduce caif over virtio") > > Not-so-coincidentally, according to "the Internet" ST-Ericsson officially > shut down its modem joint venture in Aug 2013. > > If anyone is using this code please yell! > > In the 13 years since, the code has accumulated 200 non-merge commits, > of which 71 were cross-tree API changes, 21 carried Fixes: tags, and > the remaining ~110 were cleanups, doc conversions, treewide refactors, > and one partial removal (caif_hsi, ca75bcf0a83b). > > We are still getting fixes to this code, in the last 10 days there were > 3 reports on security@ about CAIF that I have been CCed on. > > UAPI constants (AF_CAIF, ARPHRD_CAIF, N_CAIF, VIRTIO_ID_CAIF) and the > SELinux classmap entry are intentionally kept for ABI stability. > > Signed-off-by: Jakub Kicinski The device was never specced out. Acked-by: Michael S. Tsirkin > --- > I think we should accumulate such patches over the coming days on a separate > branch. CAIF is a no-brainer IMO but other removals may be more controversial. > > CC: corbet@lwn.net > CC: skhan@linuxfoundation.org > CC: alexs@kernel.org > CC: si.yanteng@linux.dev > CC: dzm91@hust.edu.cn > CC: linux@armlinux.org.uk > CC: mst@redhat.com > CC: jasowang@redhat.com > CC: xuanzhuo@linux.alibaba.com > CC: eperezma@redhat.com > CC: xu.xin16@zte.com.cn > CC: wang.yaxin@zte.com.cn > CC: jiang.kun2@zte.com.cn > CC: linusw@kernel.org > CC: jihed.chaibi.dev@gmail.com > CC: arnd@arndb.de > CC: tytso@mit.edu > CC: jiayuan.chen@shopee.com > CC: gregkh@linuxfoundation.org > --- > MAINTAINERS | 9 - > Documentation/networking/caif/caif.rst | 138 -- > Documentation/networking/caif/index.rst | 12 - > Documentation/networking/caif/linux_caif.rst | 195 --- > Documentation/networking/index.rst | 1 - > .../translations/zh_CN/networking/index.rst | 1 - > drivers/net/Kconfig | 2 - > drivers/net/caif/Kconfig | 33 - > net/Kconfig | 1 - > net/caif/Kconfig | 54 - > drivers/net/Makefile | 1 - > drivers/net/caif/Makefile | 8 - > net/Makefile | 1 - > net/caif/Makefile | 16 - > include/linux/virtio_caif.h | 24 - > include/net/caif/caif_dev.h | 128 -- > include/net/caif/caif_device.h | 55 - > include/net/caif/caif_layer.h | 277 ---- > include/net/caif/cfcnfg.h | 90 -- > include/net/caif/cfctrl.h | 130 -- > include/net/caif/cffrml.h | 21 - > include/net/caif/cfmuxl.h | 20 - > include/net/caif/cfpkt.h | 232 ---- > include/net/caif/cfserl.h | 13 - > include/net/caif/cfsrvl.h | 61 - > include/uapi/linux/caif/caif_socket.h | 195 --- > include/uapi/linux/caif/if_caif.h | 35 - > drivers/net/caif/caif_serial.c | 443 ------- > drivers/net/caif/caif_virtio.c | 791 ------------ > net/caif/caif_dev.c | 586 --------- > net/caif/caif_socket.c | 1114 ----------------- > net/caif/caif_usb.c | 216 ---- > net/caif/cfcnfg.c | 612 --------- > net/caif/cfctrl.c | 631 ---------- > net/caif/cfdbgl.c | 55 - > net/caif/cfdgml.c | 113 -- > net/caif/cffrml.c | 204 --- > net/caif/cfmuxl.c | 267 ---- > net/caif/cfpkt_skbuff.c | 373 ------ > net/caif/cfrfml.c | 299 ----- > net/caif/cfserl.c | 192 --- > net/caif/cfsrvl.c | 224 ---- > net/caif/cfutill.c | 104 -- > net/caif/cfveil.c | 101 -- > net/caif/cfvidl.c | 65 - > net/caif/chnl_net.c | 531 -------- > arch/arm/configs/u8500_defconfig | 1 - > 47 files changed, 8675 deletions(-) > delete mode 100644 Documentation/networking/caif/caif.rst > delete mode 100644 Documentation/networking/caif/index.rst > delete mode 100644 Documentation/networking/caif/linux_caif.rst > delete mode 100644 drivers/net/caif/Kconfig > delete mode 100644 net/caif/Kconfig > delete mode 100644 drivers/net/caif/Makefile > delete mode 100644 net/caif/Makefile > delete mode 100644 include/linux/virtio_caif.h > delete mode 100644 include/net/caif/caif_dev.h > delete mode 100644 include/net/caif/caif_device.h > delete mode 100644 include/net/caif/caif_layer.h > delete mode 100644 include/net/caif/cfcnfg.h > delete mode 100644 include/net/caif/cfctrl.h > delete mode 100644 include/net/caif/cffrml.h > delete mode 100644 include/net/caif/cfmuxl.h > delete mode 100644 include/net/caif/cfpkt.h > delete mode 100644 include/net/caif/cfserl.h > delete mode 100644 include/net/caif/cfsrvl.h > delete mode 100644 include/uapi/linux/caif/caif_socket.h > delete mode 100644 include/uapi/linux/caif/if_caif.h > delete mode 100644 drivers/net/caif/caif_serial.c > delete mode 100644 drivers/net/caif/caif_virtio.c > delete mode 100644 net/caif/caif_dev.c > delete mode 100644 net/caif/caif_socket.c > delete mode 100644 net/caif/caif_usb.c > delete mode 100644 net/caif/cfcnfg.c > delete mode 100644 net/caif/cfctrl.c > delete mode 100644 net/caif/cfdbgl.c > delete mode 100644 net/caif/cfdgml.c > delete mode 100644 net/caif/cffrml.c > delete mode 100644 net/caif/cfmuxl.c > delete mode 100644 net/caif/cfpkt_skbuff.c > delete mode 100644 net/caif/cfrfml.c > delete mode 100644 net/caif/cfserl.c > delete mode 100644 net/caif/cfsrvl.c > delete mode 100644 net/caif/cfutill.c > delete mode 100644 net/caif/cfveil.c > delete mode 100644 net/caif/cfvidl.c > delete mode 100644 net/caif/chnl_net.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index e7dc9e6fad2e..2b1b5e93c272 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -5674,15 +5674,6 @@ T: git git://linuxtv.org/media.git > F: Documentation/admin-guide/media/cafe_ccic* > F: drivers/media/platform/marvell/ > > -CAIF NETWORK LAYER > -L: netdev@vger.kernel.org > -S: Orphan > -F: Documentation/networking/caif/ > -F: drivers/net/caif/ > -F: include/net/caif/ > -F: include/uapi/linux/caif/ > -F: net/caif/ > - > CAKE QDISC > M: Toke Høiland-Jørgensen > L: cake@lists.bufferbloat.net (moderated for non-subscribers) > diff --git a/Documentation/networking/caif/caif.rst b/Documentation/networking/caif/caif.rst > deleted file mode 100644 > index d922d419c513..000000000000 > --- a/Documentation/networking/caif/caif.rst > +++ /dev/null > @@ -1,138 +0,0 @@ > -.. SPDX-License-Identifier: GPL-2.0 > -.. include:: > - > - > -================ > -Using Linux CAIF > -================ > - > - > -:Copyright: |copy| ST-Ericsson AB 2010 > - > -:Author: Sjur Brendeland/ sjur.brandeland@stericsson.com > - > -Start > -===== > - > -If you have compiled CAIF for modules do:: > - > - $modprobe crc_ccitt > - $modprobe caif > - $modprobe caif_socket > - $modprobe chnl_net > - > - > -Preparing the setup with a STE modem > -==================================== > - > -If you are working on integration of CAIF you should make sure > -that the kernel is built with module support. > - > -There are some things that need to be tweaked to get the host TTY correctly > -set up to talk to the modem. > -Since the CAIF stack is running in the kernel and we want to use the existing > -TTY, we are installing our physical serial driver as a line discipline above > -the TTY device. > - > -To achieve this we need to install the N_CAIF ldisc from user space. > -The benefit is that we can hook up to any TTY. > - > -The use of Start-of-frame-extension (STX) must also be set as > -module parameter "ser_use_stx". > - > -Normally Frame Checksum is always used on UART, but this is also provided as a > -module parameter "ser_use_fcs". > - > -:: > - > - $ modprobe caif_serial ser_ttyname=/dev/ttyS0 ser_use_stx=yes > - $ ifconfig caif_ttyS0 up > - > -PLEASE NOTE: > - There is a limitation in Android shell. > - It only accepts one argument to insmod/modprobe! > - > -Trouble shooting > -================ > - > -There are debugfs parameters provided for serial communication. > -/sys/kernel/debug/caif_serial// > - > -* ser_state: Prints the bit-mask status where > - > - - 0x02 means SENDING, this is a transient state. > - - 0x10 means FLOW_OFF_SENT, i.e. the previous frame has not been sent > - and is blocking further send operation. Flow OFF has been propagated > - to all CAIF Channels using this TTY. > - > -* tty_status: Prints the bit-mask tty status information > - > - - 0x01 - tty->warned is on. > - - 0x04 - tty->packed is on. > - - 0x08 - tty->flow.tco_stopped is on. > - - 0x10 - tty->hw_stopped is on. > - - 0x20 - tty->flow.stopped is on. > - > -* last_tx_msg: Binary blob Prints the last transmitted frame. > - > - This can be printed with:: > - > - $od --format=x1 /sys/kernel/debug/caif_serial//last_rx_msg. > - > - The first two tx messages sent look like this. Note: The initial > - byte 02 is start of frame extension (STX) used for re-syncing > - upon errors. > - > - - Enumeration:: > - > - 0000000 02 05 00 00 03 01 d2 02 > - | | | | | | > - STX(1) | | | | > - Length(2)| | | > - Control Channel(1) > - Command:Enumeration(1) > - Link-ID(1) > - Checksum(2) > - > - - Channel Setup:: > - > - 0000000 02 07 00 00 00 21 a1 00 48 df > - | | | | | | | | > - STX(1) | | | | | | > - Length(2)| | | | | > - Control Channel(1) > - Command:Channel Setup(1) > - Channel Type(1) > - Priority and Link-ID(1) > - Endpoint(1) > - Checksum(2) > - > -* last_rx_msg: Prints the last transmitted frame. > - > - The RX messages for LinkSetup look almost identical but they have the > - bit 0x20 set in the command bit, and Channel Setup has added one byte > - before Checksum containing Channel ID. > - > - NOTE: > - Several CAIF Messages might be concatenated. The maximum debug > - buffer size is 128 bytes. > - > -Error Scenarios > -=============== > - > -- last_tx_msg contains channel setup message and last_rx_msg is empty -> > - The host seems to be able to send over the UART, at least the CAIF ldisc get > - notified that sending is completed. > - > -- last_tx_msg contains enumeration message and last_rx_msg is empty -> > - The host is not able to send the message from UART, the tty has not been > - able to complete the transmit operation. > - > -- if /sys/kernel/debug/caif_serial//tty_status is non-zero there > - might be problems transmitting over UART. > - > - E.g. host and modem wiring is not correct you will typically see > - tty_status = 0x10 (hw_stopped) and ser_state = 0x10 (FLOW_OFF_SENT). > - > - You will probably see the enumeration message in last_tx_message > - and empty last_rx_message. > diff --git a/Documentation/networking/caif/index.rst b/Documentation/networking/caif/index.rst > deleted file mode 100644 > index ec29b6f4bdb4..000000000000 > --- a/Documentation/networking/caif/index.rst > +++ /dev/null > @@ -1,12 +0,0 @@ > -.. SPDX-License-Identifier: GPL-2.0 > - > -CAIF > -==== > - > -Contents: > - > -.. toctree:: > - :maxdepth: 2 > - > - linux_caif > - caif > diff --git a/Documentation/networking/caif/linux_caif.rst b/Documentation/networking/caif/linux_caif.rst > deleted file mode 100644 > index a0480862ab8c..000000000000 > --- a/Documentation/networking/caif/linux_caif.rst > +++ /dev/null > @@ -1,195 +0,0 @@ > -.. SPDX-License-Identifier: GPL-2.0 > -.. include:: > - > -========== > -Linux CAIF > -========== > - > -Copyright |copy| ST-Ericsson AB 2010 > - > -:Author: Sjur Brendeland/ sjur.brandeland@stericsson.com > -:License terms: GNU General Public License (GPL) version 2 > - > - > -Introduction > -============ > - > -CAIF is a MUX protocol used by ST-Ericsson cellular modems for > -communication between Modem and host. The host processes can open virtual AT > -channels, initiate GPRS Data connections, Video channels and Utility Channels. > -The Utility Channels are general purpose pipes between modem and host. > - > -ST-Ericsson modems support a number of transports between modem > -and host. Currently, UART and Loopback are available for Linux. > - > - > -Architecture > -============ > - > -The implementation of CAIF is divided into: > - > -* CAIF Socket Layer and GPRS IP Interface. > -* CAIF Core Protocol Implementation > -* CAIF Link Layer, implemented as NET devices. > - > -:: > - > - RTNL > - ! > - ! +------+ +------+ > - ! +------+! +------+! > - ! ! IP !! !Socket!! > - +-------> !interf!+ ! API !+ <- CAIF Client APIs > - ! +------+ +------! > - ! ! ! > - ! +-----------+ > - ! ! > - ! +------+ <- CAIF Core Protocol > - ! ! CAIF ! > - ! ! Core ! > - ! +------+ > - ! +----------!---------+ > - ! ! ! ! > - ! +------+ +-----+ +------+ > - +--> ! HSI ! ! TTY ! ! USB ! <- Link Layer (Net Devices) > - +------+ +-----+ +------+ > - > - > - > -Implementation > -============== > - > - > -CAIF Core Protocol Layer > ------------------------- > - > -CAIF Core layer implements the CAIF protocol as defined by ST-Ericsson. > -It implements the CAIF protocol stack in a layered approach, where > -each layer described in the specification is implemented as a separate layer. > -The architecture is inspired by the design patterns "Protocol Layer" and > -"Protocol Packet". > - > -CAIF structure > -^^^^^^^^^^^^^^ > - > -The Core CAIF implementation contains: > - > - - Simple implementation of CAIF. > - - Layered architecture (a la Streams), each layer in the CAIF > - specification is implemented in a separate c-file. > - - Clients must call configuration function to add PHY layer. > - - Clients must implement CAIF layer to consume/produce > - CAIF payload with receive and transmit functions. > - - Clients must call configuration function to add and connect the > - Client layer. > - - When receiving / transmitting CAIF Packets (cfpkt), ownership is passed > - to the called function (except for framing layers' receive function) > - > -Layered Architecture > -==================== > - > -The CAIF protocol can be divided into two parts: Support functions and Protocol > -Implementation. The support functions include: > - > - - CFPKT CAIF Packet. Implementation of CAIF Protocol Packet. The > - CAIF Packet has functions for creating, destroying and adding content > - and for adding/extracting header and trailers to protocol packets. > - > -The CAIF Protocol implementation contains: > - > - - CFCNFG CAIF Configuration layer. Configures the CAIF Protocol > - Stack and provides a Client interface for adding Link-Layer and > - Driver interfaces on top of the CAIF Stack. > - > - - CFCTRL CAIF Control layer. Encodes and Decodes control messages > - such as enumeration and channel setup. Also matches request and > - response messages. > - > - - CFSERVL General CAIF Service Layer functionality; handles flow > - control and remote shutdown requests. > - > - - CFVEI CAIF VEI layer. Handles CAIF AT Channels on VEI (Virtual > - External Interface). This layer encodes/decodes VEI frames. > - > - - CFDGML CAIF Datagram layer. Handles CAIF Datagram layer (IP > - traffic), encodes/decodes Datagram frames. > - > - - CFMUX CAIF Mux layer. Handles multiplexing between multiple > - physical bearers and multiple channels such as VEI, Datagram, etc. > - The MUX keeps track of the existing CAIF Channels and > - Physical Instances and selects the appropriate instance based > - on Channel-Id and Physical-ID. > - > - - CFFRML CAIF Framing layer. Handles Framing i.e. Frame length > - and frame checksum. > - > - - CFSERL CAIF Serial layer. Handles concatenation/split of frames > - into CAIF Frames with correct length. > - > -:: > - > - +---------+ > - | Config | > - | CFCNFG | > - +---------+ > - ! > - +---------+ +---------+ +---------+ > - | AT | | Control | | Datagram| > - | CFVEIL | | CFCTRL | | CFDGML | > - +---------+ +---------+ +---------+ > - \_____________!______________/ > - ! > - +---------+ > - | MUX | > - | | > - +---------+ > - _____!_____ > - / \ > - +---------+ +---------+ > - | CFFRML | | CFFRML | > - | Framing | | Framing | > - +---------+ +---------+ > - ! ! > - +---------+ +---------+ > - | | | Serial | > - | | | CFSERL | > - +---------+ +---------+ > - > - > -In this layered approach the following "rules" apply. > - > - - All layers embed the same structure "struct cflayer" > - - A layer does not depend on any other layer's private data. > - - Layers are stacked by setting the pointers:: > - > - layer->up , layer->dn > - > - - In order to send data upwards, each layer should do:: > - > - layer->up->receive(layer->up, packet); > - > - - In order to send data downwards, each layer should do:: > - > - layer->dn->transmit(layer->dn, packet); > - > - > -CAIF Socket and IP interface > -============================ > - > -The IP interface and CAIF socket API are implemented on top of the > -CAIF Core protocol. The IP Interface and CAIF socket have an instance of > -'struct cflayer', just like the CAIF Core protocol stack. > -Net device and Socket implement the 'receive()' function defined by > -'struct cflayer', just like the rest of the CAIF stack. In this way, transmit and > -receive of packets is handled as by the rest of the layers: the 'dn->transmit()' > -function is called in order to transmit data. > - > -Configuration of Link Layer > ---------------------------- > -The Link Layer is implemented as Linux network devices (struct net_device). > -Payload handling and registration is done using standard Linux mechanisms. > - > -The CAIF Protocol relies on a loss-less link layer without implementing > -retransmission. This implies that packet drops must not happen. > -Therefore a flow-control mechanism is implemented where the physical > -interface can initiate flow stop for all CAIF Channels. > diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst > index c2406bd8ae0b..2e946924ad3f 100644 > --- a/Documentation/networking/index.rst > +++ b/Documentation/networking/index.rst > @@ -17,7 +17,6 @@ Refer to :ref:`netdev-FAQ` for a guide on netdev development process specifics. > diagnostic/index > dsa/index > devlink/index > - caif/index > ethtool-netlink > ieee802154 > iso15765-2 > diff --git a/Documentation/translations/zh_CN/networking/index.rst b/Documentation/translations/zh_CN/networking/index.rst > index c276c0993c51..333e9f6cafff 100644 > --- a/Documentation/translations/zh_CN/networking/index.rst > +++ b/Documentation/translations/zh_CN/networking/index.rst > @@ -42,7 +42,6 @@ 目录: > * diagnostic/index > * dsa/index > * devlink/index > -* caif/index > * ethtool-netlink > * ieee802154 > * iso15765-2 > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig > index edaab759dc50..8ec98f6dfef9 100644 > --- a/drivers/net/Kconfig > +++ b/drivers/net/Kconfig > @@ -503,8 +503,6 @@ source "drivers/net/arcnet/Kconfig" > > source "drivers/atm/Kconfig" > > -source "drivers/net/caif/Kconfig" > - > source "drivers/net/dsa/Kconfig" > > source "drivers/net/ethernet/Kconfig" > diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig > deleted file mode 100644 > index 709660cb38f8..000000000000 > --- a/drivers/net/caif/Kconfig > +++ /dev/null > @@ -1,33 +0,0 @@ > -# SPDX-License-Identifier: GPL-2.0-only > -# > -# CAIF physical drivers > -# > - > -menuconfig CAIF_DRIVERS > - bool "CAIF transport drivers" > - depends on CAIF > - help > - Enable this to see CAIF physical drivers. > - > -if CAIF_DRIVERS > - > -config CAIF_TTY > - tristate "CAIF TTY transport driver" > - depends on CAIF && TTY > - default n > - help > - The CAIF TTY transport driver is a Line Discipline (ldisc) > - identified as N_CAIF. When this ldisc is opened from user space > - it will redirect the TTY's traffic into the CAIF stack. > - > -config CAIF_VIRTIO > - tristate "CAIF virtio transport driver" > - depends on CAIF && HAS_DMA > - select VHOST_RING > - select VIRTIO > - select GENERIC_ALLOCATOR > - default n > - help > - The CAIF driver for CAIF over Virtio. > - > -endif # CAIF_DRIVERS > diff --git a/net/Kconfig b/net/Kconfig > index 62266eaf0e95..5c588dbcbdbd 100644 > --- a/net/Kconfig > +++ b/net/Kconfig > @@ -439,7 +439,6 @@ endif # WIRELESS > > source "net/rfkill/Kconfig" > source "net/9p/Kconfig" > -source "net/caif/Kconfig" > source "net/ceph/Kconfig" > source "net/nfc/Kconfig" > source "net/psample/Kconfig" > diff --git a/net/caif/Kconfig b/net/caif/Kconfig > deleted file mode 100644 > index 87205251cc25..000000000000 > --- a/net/caif/Kconfig > +++ /dev/null > @@ -1,54 +0,0 @@ > -# SPDX-License-Identifier: GPL-2.0-only > -# > -# CAIF net configurations > -# > - > -menuconfig CAIF > - tristate "CAIF support" > - select CRC_CCITT > - default n > - help > - The "Communication CPU to Application CPU Interface" (CAIF) is a packet > - based connection-oriented MUX protocol developed by ST-Ericsson for use > - with its modems. It is accessed from user space as sockets (PF_CAIF). > - > - Say Y (or M) here if you build for a phone product (e.g. Android or > - MeeGo) that uses CAIF as transport. If unsure say N. > - > - If you select to build it as module then CAIF_NETDEV also needs to be > - built as a module. You will also need to say Y (or M) to any CAIF > - physical devices that your platform requires. > - > - See Documentation/networking/caif for a further explanation on how to > - use and configure CAIF. > - > -config CAIF_DEBUG > - bool "Enable Debug" > - depends on CAIF > - default n > - help > - Enable the inclusion of debug code in the CAIF stack. > - Be aware that doing this will impact performance. > - If unsure say N. > - > -config CAIF_NETDEV > - tristate "CAIF GPRS Network device" > - depends on CAIF > - default CAIF > - help > - Say Y if you will be using a CAIF based GPRS network device. > - This can be either built-in or a loadable module. > - If you select to build it as a built-in then the main CAIF device must > - also be a built-in. > - If unsure say Y. > - > -config CAIF_USB > - tristate "CAIF USB support" > - depends on CAIF > - default n > - help > - Say Y if you are using CAIF over USB CDC NCM. > - This can be either built-in or a loadable module. > - If you select to build it as a built-in then the main CAIF device must > - also be a built-in. > - If unsure say N. > diff --git a/drivers/net/Makefile b/drivers/net/Makefile > index 5b01215f6829..3b2d28127634 100644 > --- a/drivers/net/Makefile > +++ b/drivers/net/Makefile > @@ -48,7 +48,6 @@ obj-$(CONFIG_MHI_NET) += mhi_net.o > # Networking Drivers > # > obj-$(CONFIG_ARCNET) += arcnet/ > -obj-$(CONFIG_CAIF) += caif/ > obj-$(CONFIG_CAN) += can/ > ifdef CONFIG_NET_DSA > obj-y += dsa/ > diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile > deleted file mode 100644 > index 97f664f8016c..000000000000 > --- a/drivers/net/caif/Makefile > +++ /dev/null > @@ -1,8 +0,0 @@ > -# SPDX-License-Identifier: GPL-2.0 > -ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG > - > -# Serial interface > -obj-$(CONFIG_CAIF_TTY) += caif_serial.o > - > -# Virtio interface > -obj-$(CONFIG_CAIF_VIRTIO) += caif_virtio.o > diff --git a/net/Makefile b/net/Makefile > index 90e3d72bf58b..98e182829eff 100644 > --- a/net/Makefile > +++ b/net/Makefile > @@ -53,7 +53,6 @@ obj-$(CONFIG_IUCV) += iucv/ > obj-$(CONFIG_SMC) += smc/ > obj-$(CONFIG_RFKILL) += rfkill/ > obj-$(CONFIG_NET_9P) += 9p/ > -obj-$(CONFIG_CAIF) += caif/ > obj-$(CONFIG_DCB) += dcb/ > obj-$(CONFIG_6LOWPAN) += 6lowpan/ > obj-$(CONFIG_IEEE802154) += ieee802154/ > diff --git a/net/caif/Makefile b/net/caif/Makefile > deleted file mode 100644 > index 4f6c0517cdfb..000000000000 > --- a/net/caif/Makefile > +++ /dev/null > @@ -1,16 +0,0 @@ > -# SPDX-License-Identifier: GPL-2.0 > -ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG > - > -caif-y := caif_dev.o \ > - cfcnfg.o cfmuxl.o cfctrl.o \ > - cffrml.o cfveil.o cfdbgl.o\ > - cfserl.o cfdgml.o \ > - cfrfml.o cfvidl.o cfutill.o \ > - cfsrvl.o cfpkt_skbuff.o > - > -obj-$(CONFIG_CAIF) += caif.o > -obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o > -obj-$(CONFIG_CAIF) += caif_socket.o > -obj-$(CONFIG_CAIF_USB) += caif_usb.o > - > -export-y := caif.o > diff --git a/include/linux/virtio_caif.h b/include/linux/virtio_caif.h > deleted file mode 100644 > index ea722479510c..000000000000 > --- a/include/linux/virtio_caif.h > +++ /dev/null > @@ -1,24 +0,0 @@ > -/* > - * Copyright (C) ST-Ericsson AB 2012 > - * Author: Sjur Brændeland > - * > - * This header is BSD licensed so > - * anyone can use the definitions to implement compatible remote processors > - */ > - > -#ifndef VIRTIO_CAIF_H > -#define VIRTIO_CAIF_H > - > -#include > -struct virtio_caif_transf_config { > - __virtio16 headroom; > - __virtio16 tailroom; > - __virtio32 mtu; > - u8 reserved[4]; > -}; > - > -struct virtio_caif_config { > - struct virtio_caif_transf_config uplink, downlink; > - u8 reserved[8]; > -}; > -#endif > diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h > deleted file mode 100644 > index b655d8666f55..000000000000 > --- a/include/net/caif/caif_dev.h > +++ /dev/null > @@ -1,128 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CAIF_DEV_H_ > -#define CAIF_DEV_H_ > - > -#include > -#include > -#include > -#include > -#include > -#include > - > -/** > - * struct caif_param - CAIF parameters. > - * @size: Length of data > - * @data: Binary Data Blob > - */ > -struct caif_param { > - u16 size; > - u8 data[256]; > -}; > - > -/** > - * struct caif_connect_request - Request data for CAIF channel setup. > - * @protocol: Type of CAIF protocol to use (at, datagram etc) > - * @sockaddr: Socket address to connect. > - * @priority: Priority of the connection. > - * @link_selector: Link selector (high bandwidth or low latency) > - * @ifindex: kernel index of the interface. > - * @param: Connect Request parameters (CAIF_SO_REQ_PARAM). > - * > - * This struct is used when connecting a CAIF channel. > - * It contains all CAIF channel configuration options. > - */ > -struct caif_connect_request { > - enum caif_protocol_type protocol; > - struct sockaddr_caif sockaddr; > - enum caif_channel_priority priority; > - enum caif_link_selector link_selector; > - int ifindex; > - struct caif_param param; > -}; > - > -/** > - * caif_connect_client - Connect a client to CAIF Core Stack. > - * @config: Channel setup parameters, specifying what address > - * to connect on the Modem. > - * @client_layer: User implementation of client layer. This layer > - * MUST have receive and control callback functions > - * implemented. > - * @ifindex: Link layer interface index used for this connection. > - * @headroom: Head room needed by CAIF protocol. > - * @tailroom: Tail room needed by CAIF protocol. > - * > - * This function connects a CAIF channel. The Client must implement > - * the struct cflayer. This layer represents the Client layer and holds > - * receive functions and control callback functions. Control callback > - * function will receive information about connect/disconnect responses, > - * flow control etc (see enum caif_control). > - * E.g. CAIF Socket will call this function for each socket it connects > - * and have one client_layer instance for each socket. > - */ > -int caif_connect_client(struct net *net, > - struct caif_connect_request *conn_req, > - struct cflayer *client_layer, int *ifindex, > - int *headroom, int *tailroom); > - > -/** > - * caif_disconnect_client - Disconnects a client from the CAIF stack. > - * > - * @client_layer: Client layer to be disconnected. > - */ > -int caif_disconnect_client(struct net *net, struct cflayer *client_layer); > - > - > -/** > - * caif_client_register_refcnt - register ref-count functions provided by client. > - * > - * @adapt_layer: Client layer using CAIF Stack. > - * @hold: Function provided by client layer increasing ref-count > - * @put: Function provided by client layer decreasing ref-count > - * > - * Client of the CAIF Stack must register functions for reference counting. > - * These functions are called by the CAIF Stack for every upstream packet, > - * and must therefore be implemented efficiently. > - * > - * Client should call caif_free_client when reference count degrease to zero. > - */ > - > -void caif_client_register_refcnt(struct cflayer *adapt_layer, > - void (*hold)(struct cflayer *lyr), > - void (*put)(struct cflayer *lyr)); > -/** > - * caif_free_client - Free memory used to manage the client in the CAIF Stack. > - * > - * @client_layer: Client layer to be removed. > - * > - * This function must be called from client layer in order to free memory. > - * Caller must guarantee that no packets are in flight upstream when calling > - * this function. > - */ > -void caif_free_client(struct cflayer *adap_layer); > - > -/** > - * struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer > - * @dev: Network device to enroll. > - * @caifdev: Configuration information from CAIF Link Layer > - * @link_support: Link layer support layer > - * @head_room: Head room needed by link support layer > - * @layer: Lowest layer in CAIF stack > - * @rcv_fun: Receive function for CAIF stack. > - * > - * This function enroll a CAIF link layer into CAIF Stack and > - * expects the interface to be able to handle CAIF payload. > - * The link_support layer is used to add any Link Layer specific > - * framing. > - */ > -int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, > - struct cflayer *link_support, int head_room, > - struct cflayer **layer, int (**rcv_func)( > - struct sk_buff *, struct net_device *, > - struct packet_type *, struct net_device *)); > - > -#endif /* CAIF_DEV_H_ */ > diff --git a/include/net/caif/caif_device.h b/include/net/caif/caif_device.h > deleted file mode 100644 > index 91d1fd5b44a4..000000000000 > --- a/include/net/caif/caif_device.h > +++ /dev/null > @@ -1,55 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CAIF_DEVICE_H_ > -#define CAIF_DEVICE_H_ > -#include > -#include > -#include > -#include > -#include > - > -/** > - * struct caif_dev_common - data shared between CAIF drivers and stack. > - * @flowctrl: Flow Control callback function. This function is > - * supplied by CAIF Core Stack and is used by CAIF > - * Link Layer to send flow-stop to CAIF Core. > - * The flow information will be distributed to all > - * clients of CAIF. > - * > - * @link_select: Profile of device, either high-bandwidth or > - * low-latency. This member is set by CAIF Link > - * Layer Device in order to indicate if this device > - * is a high bandwidth or low latency device. > - * > - * @use_frag: CAIF Frames may be fragmented. > - * Is set by CAIF Link Layer in order to indicate if the > - * interface receives fragmented frames that must be > - * assembled by CAIF Core Layer. > - * > - * @use_fcs: Indicate if Frame CheckSum (fcs) is used. > - * Is set if the physical interface is > - * using Frame Checksum on the CAIF Frames. > - * > - * @use_stx: Indicate STart of frame eXtension (stx) in use. > - * Is set if the CAIF Link Layer expects > - * CAIF Frames to start with the STX byte. > - * > - * This structure is shared between the CAIF drivers and the CAIF stack. > - * It is used by the device to register its behavior. > - * CAIF Core layer must set the member flowctrl in order to supply > - * CAIF Link Layer with the flow control function. > - * > - */ > - struct caif_dev_common { > - void (*flowctrl)(struct net_device *net, int on); > - enum caif_link_selector link_select; > - int use_frag; > - int use_fcs; > - int use_stx; > -}; > - > -#endif /* CAIF_DEVICE_H_ */ > diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h > deleted file mode 100644 > index 053e7c6a6a66..000000000000 > --- a/include/net/caif/caif_layer.h > +++ /dev/null > @@ -1,277 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CAIF_LAYER_H_ > -#define CAIF_LAYER_H_ > - > -#include > - > -struct cflayer; > -struct cfpkt; > -struct caif_payload_info; > - > -#define CAIF_LAYER_NAME_SZ 16 > - > -/** > - * caif_assert() - Assert function for CAIF. > - * @assert: expression to evaluate. > - * > - * This function will print a error message and a do WARN_ON if the > - * assertion fails. Normally this will do a stack up at the current location. > - */ > -#define caif_assert(assert) \ > -do { \ > - if (!(assert)) { \ > - pr_err("caif:Assert detected:'%s'\n", #assert); \ > - WARN_ON(!(assert)); \ > - } \ > -} while (0) > - > -/** > - * enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd(). > - * > - * @CAIF_CTRLCMD_FLOW_OFF_IND: Flow Control is OFF, transmit function > - * should stop sending data > - * > - * @CAIF_CTRLCMD_FLOW_ON_IND: Flow Control is ON, transmit function > - * can start sending data > - * > - * @CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: Remote end modem has decided to close > - * down channel > - * > - * @CAIF_CTRLCMD_INIT_RSP: Called initially when the layer below > - * has finished initialization > - * > - * @CAIF_CTRLCMD_DEINIT_RSP: Called when de-initialization is > - * complete > - * > - * @CAIF_CTRLCMD_INIT_FAIL_RSP: Called if initialization fails > - * > - * @_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: CAIF Link layer temporarily cannot > - * send more packets. > - * @_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: Called if CAIF Link layer is able > - * to send packets again. > - * @_CAIF_CTRLCMD_PHYIF_DOWN_IND: Called if CAIF Link layer is going > - * down. > - * > - * These commands are sent upwards in the CAIF stack to the CAIF Client. > - * They are used for signaling originating from the modem or CAIF Link Layer. > - * These are either responses (*_RSP) or events (*_IND). > - */ > -enum caif_ctrlcmd { > - CAIF_CTRLCMD_FLOW_OFF_IND, > - CAIF_CTRLCMD_FLOW_ON_IND, > - CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, > - CAIF_CTRLCMD_INIT_RSP, > - CAIF_CTRLCMD_DEINIT_RSP, > - CAIF_CTRLCMD_INIT_FAIL_RSP, > - _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, > - _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND, > - _CAIF_CTRLCMD_PHYIF_DOWN_IND, > -}; > - > -/** > - * enum caif_modemcmd - Modem Control Signaling, sent from CAIF Client > - * to the CAIF Link Layer or modem. > - * > - * @CAIF_MODEMCMD_FLOW_ON_REQ: Flow Control is ON, transmit function > - * can start sending data. > - * > - * @CAIF_MODEMCMD_FLOW_OFF_REQ: Flow Control is OFF, transmit function > - * should stop sending data. > - * > - * @_CAIF_MODEMCMD_PHYIF_USEFULL: Notify physical layer that it is in use > - * > - * @_CAIF_MODEMCMD_PHYIF_USELESS: Notify physical layer that it is > - * no longer in use. > - * > - * These are requests sent 'downwards' in the stack. > - * Flow ON, OFF can be indicated to the modem. > - */ > -enum caif_modemcmd { > - CAIF_MODEMCMD_FLOW_ON_REQ = 0, > - CAIF_MODEMCMD_FLOW_OFF_REQ = 1, > - _CAIF_MODEMCMD_PHYIF_USEFULL = 3, > - _CAIF_MODEMCMD_PHYIF_USELESS = 4 > -}; > - > -/** > - * enum caif_direction - CAIF Packet Direction. > - * Indicate if a packet is to be sent out or to be received in. > - * @CAIF_DIR_IN: Incoming packet received. > - * @CAIF_DIR_OUT: Outgoing packet to be transmitted. > - */ > -enum caif_direction { > - CAIF_DIR_IN = 0, > - CAIF_DIR_OUT = 1 > -}; > - > -/** > - * struct cflayer - CAIF Stack layer. > - * Defines the framework for the CAIF Core Stack. > - * @up: Pointer up to the layer above. > - * @dn: Pointer down to the layer below. > - * @node: List node used when layer participate in a list. > - * @receive: Packet receive function. > - * @transmit: Packet transmit function. > - * @ctrlcmd: Used for control signalling upwards in the stack. > - * @modemcmd: Used for control signaling downwards in the stack. > - * @id: The identity of this layer > - * @name: Name of the layer. > - * > - * This structure defines the layered structure in CAIF. > - * > - * It defines CAIF layering structure, used by all CAIF Layers and the > - * layers interfacing CAIF. > - * > - * In order to integrate with CAIF an adaptation layer on top of the CAIF stack > - * and PHY layer below the CAIF stack > - * must be implemented. These layer must follow the design principles below. > - * > - * Principles for layering of protocol layers: > - * - All layers must use this structure. If embedding it, then place this > - * structure first in the layer specific structure. > - * > - * - Each layer should not depend on any others layer's private data. > - * > - * - In order to send data upwards do > - * layer->up->receive(layer->up, packet); > - * > - * - In order to send data downwards do > - * layer->dn->transmit(layer->dn, info, packet); > - */ > -struct cflayer { > - struct cflayer *up; > - struct cflayer *dn; > - struct list_head node; > - > - /* > - * receive() - Receive Function (non-blocking). > - * Contract: Each layer must implement a receive function passing the > - * CAIF packets upwards in the stack. > - * Packet handling rules: > - * - The CAIF packet (cfpkt) ownership is passed to the > - * called receive function. This means that the > - * packet cannot be accessed after passing it to the > - * above layer using up->receive(). > - * > - * - If parsing of the packet fails, the packet must be > - * destroyed and negative error code returned > - * from the function. > - * EXCEPTION: If the framing layer (cffrml) returns > - * -EILSEQ, the packet is not freed. > - * > - * - If parsing succeeds (and above layers return OK) then > - * the function must return a value >= 0. > - * > - * Returns result < 0 indicates an error, 0 or positive value > - * indicates success. > - * > - * @layr: Pointer to the current layer the receive function is > - * implemented for (this pointer). > - * @cfpkt: Pointer to CaifPacket to be handled. > - */ > - int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt); > - > - /* > - * transmit() - Transmit Function (non-blocking). > - * Contract: Each layer must implement a transmit function passing the > - * CAIF packet downwards in the stack. > - * Packet handling rules: > - * - The CAIF packet (cfpkt) ownership is passed to the > - * transmit function. This means that the packet > - * cannot be accessed after passing it to the below > - * layer using dn->transmit(). > - * > - * - Upon error the packet ownership is still passed on, > - * so the packet shall be freed where error is detected. > - * Callers of the transmit function shall not free packets, > - * but errors shall be returned. > - * > - * - Return value less than zero means error, zero or > - * greater than zero means OK. > - * > - * Returns result < 0 indicates an error, 0 or positive value > - * indicates success. > - * > - * @layr: Pointer to the current layer the receive function > - * isimplemented for (this pointer). > - * @cfpkt: Pointer to CaifPacket to be handled. > - */ > - int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt); > - > - /* > - * cttrlcmd() - Control Function upwards in CAIF Stack (non-blocking). > - * Used for signaling responses (CAIF_CTRLCMD_*_RSP) > - * and asynchronous events from the modem (CAIF_CTRLCMD_*_IND) > - * > - * @layr: Pointer to the current layer the receive function > - * is implemented for (this pointer). > - * @ctrl: Control Command. > - */ > - void (*ctrlcmd) (struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid); > - > - /* > - * modemctrl() - Control Function used for controlling the modem. > - * Used to signal down-wards in the CAIF stack. > - * Returns 0 on success, < 0 upon failure. > - * > - * @layr: Pointer to the current layer the receive function > - * is implemented for (this pointer). > - * @ctrl: Control Command. > - */ > - int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl); > - > - unsigned int id; > - char name[CAIF_LAYER_NAME_SZ]; > -}; > - > -/** > - * layer_set_up() - Set the up pointer for a specified layer. > - * @layr: Layer where up pointer shall be set. > - * @above: Layer above. > - */ > -#define layer_set_up(layr, above) ((layr)->up = (struct cflayer *)(above)) > - > -/** > - * layer_set_dn() - Set the down pointer for a specified layer. > - * @layr: Layer where down pointer shall be set. > - * @below: Layer below. > - */ > -#define layer_set_dn(layr, below) ((layr)->dn = (struct cflayer *)(below)) > - > -/** > - * struct dev_info - Physical Device info information about physical layer. > - * @dev: Pointer to native physical device. > - * @id: Physical ID of the physical connection used by the > - * logical CAIF connection. Used by service layers to > - * identify their physical id to Caif MUX (CFMUXL)so > - * that the MUX can add the correct physical ID to the > - * packet. > - */ > -struct dev_info { > - void *dev; > - unsigned int id; > -}; > - > -/** > - * struct caif_payload_info - Payload information embedded in packet (sk_buff). > - * > - * @dev_info: Information about the receiving device. > - * > - * @hdr_len: Header length, used to align pay load on 32bit boundary. > - * > - * @channel_id: Channel ID of the logical CAIF connection. > - * Used by mux to insert channel id into the caif packet. > - */ > -struct caif_payload_info { > - struct dev_info *dev_info; > - unsigned short hdr_len; > - unsigned short channel_id; > -}; > - > -#endif /* CAIF_LAYER_H_ */ > diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h > deleted file mode 100644 > index 8819ff4db35a..000000000000 > --- a/include/net/caif/cfcnfg.h > +++ /dev/null > @@ -1,90 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFCNFG_H_ > -#define CFCNFG_H_ > -#include > -#include > -#include > -#include > - > -struct cfcnfg; > - > -/** > - * enum cfcnfg_phy_preference - Physical preference HW Abstraction > - * > - * @CFPHYPREF_UNSPECIFIED: Default physical interface > - * > - * @CFPHYPREF_LOW_LAT: Default physical interface for low-latency > - * traffic > - * @CFPHYPREF_HIGH_BW: Default physical interface for high-bandwidth > - * traffic > - * @CFPHYPREF_LOOP: TEST only Loopback interface simulating modem > - * responses. > - * > - */ > -enum cfcnfg_phy_preference { > - CFPHYPREF_UNSPECIFIED, > - CFPHYPREF_LOW_LAT, > - CFPHYPREF_HIGH_BW, > - CFPHYPREF_LOOP > -}; > - > -/** > - * cfcnfg_create() - Get the CAIF configuration object given network. > - * @net: Network for the CAIF configuration object. > - */ > -struct cfcnfg *get_cfcnfg(struct net *net); > - > -/** > - * cfcnfg_create() - Create the CAIF configuration object. > - */ > -struct cfcnfg *cfcnfg_create(void); > - > -/** > - * cfcnfg_remove() - Remove the CFCNFG object > - * @cfg: config object > - */ > -void cfcnfg_remove(struct cfcnfg *cfg); > - > -/** > - * cfcnfg_add_phy_layer() - Adds a physical layer to the CAIF stack. > - * @cnfg: Pointer to a CAIF configuration object, created by > - * cfcnfg_create(). > - * @dev: Pointer to link layer device > - * @phy_layer: Specify the physical layer. The transmit function > - * MUST be set in the structure. > - * @pref: The phy (link layer) preference. > - * @link_support: Protocol implementation for link layer specific protocol. > - * @fcs: Specify if checksum is used in CAIF Framing Layer. > - * @head_room: Head space needed by link specific protocol. > - */ > -int > -cfcnfg_add_phy_layer(struct cfcnfg *cnfg, > - struct net_device *dev, struct cflayer *phy_layer, > - enum cfcnfg_phy_preference pref, > - struct cflayer *link_support, > - bool fcs, int head_room); > - > -/** > - * cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack. > - * > - * @cnfg: Pointer to a CAIF configuration object, created by > - * cfcnfg_create(). > - * @phy_layer: Adaptation layer to be removed. > - */ > -int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer); > - > -/** > - * cfcnfg_set_phy_state() - Set the state of the physical interface device. > - * @cnfg: Configuration object > - * @phy_layer: Physical Layer representation > - * @up: State of device > - */ > -int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, > - bool up); > - > -#endif /* CFCNFG_H_ */ > diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h > deleted file mode 100644 > index 86d17315c8a1..000000000000 > --- a/include/net/caif/cfctrl.h > +++ /dev/null > @@ -1,130 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFCTRL_H_ > -#define CFCTRL_H_ > -#include > -#include > - > -/* CAIF Control packet commands */ > -enum cfctrl_cmd { > - CFCTRL_CMD_LINK_SETUP = 0, > - CFCTRL_CMD_LINK_DESTROY = 1, > - CFCTRL_CMD_LINK_ERR = 2, > - CFCTRL_CMD_ENUM = 3, > - CFCTRL_CMD_SLEEP = 4, > - CFCTRL_CMD_WAKE = 5, > - CFCTRL_CMD_LINK_RECONF = 6, > - CFCTRL_CMD_START_REASON = 7, > - CFCTRL_CMD_RADIO_SET = 8, > - CFCTRL_CMD_MODEM_SET = 9, > - CFCTRL_CMD_MASK = 0xf > -}; > - > -/* Channel types */ > -enum cfctrl_srv { > - CFCTRL_SRV_DECM = 0, > - CFCTRL_SRV_VEI = 1, > - CFCTRL_SRV_VIDEO = 2, > - CFCTRL_SRV_DBG = 3, > - CFCTRL_SRV_DATAGRAM = 4, > - CFCTRL_SRV_RFM = 5, > - CFCTRL_SRV_UTIL = 6, > - CFCTRL_SRV_MASK = 0xf > -}; > - > -#define CFCTRL_RSP_BIT 0x20 > -#define CFCTRL_ERR_BIT 0x10 > - > -struct cfctrl_rsp { > - void (*linksetup_rsp)(struct cflayer *layer, u8 linkid, > - enum cfctrl_srv serv, u8 phyid, > - struct cflayer *adapt_layer); > - void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid); > - void (*linkerror_ind)(void); > - void (*enum_rsp)(void); > - void (*sleep_rsp)(void); > - void (*wake_rsp)(void); > - void (*restart_rsp)(void); > - void (*radioset_rsp)(void); > - void (*reject_rsp)(struct cflayer *layer, u8 linkid, > - struct cflayer *client_layer); > -}; > - > -/* Link Setup Parameters for CAIF-Links. */ > -struct cfctrl_link_param { > - enum cfctrl_srv linktype;/* (T3,T0) Type of Channel */ > - u8 priority; /* (P4,P0) Priority of the channel */ > - u8 phyid; /* (U2-U0) Physical interface to connect */ > - u8 endpoint; /* (E1,E0) Endpoint for data channels */ > - u8 chtype; /* (H1,H0) Channel-Type, applies to > - * VEI, DEBUG */ > - union { > - struct { > - u8 connid; /* (D7,D0) Video LinkId */ > - } video; > - > - struct { > - u32 connid; /* (N31,Ngit0) Connection ID used > - * for Datagram */ > - } datagram; > - > - struct { > - u32 connid; /* Connection ID used for RFM */ > - char volume[20]; /* Volume to mount for RFM */ > - } rfm; /* Configuration for RFM */ > - > - struct { > - u16 fifosize_kb; /* Psock FIFO size in KB */ > - u16 fifosize_bufs; /* Psock # signal buffers */ > - char name[16]; /* Name of the PSOCK service */ > - u8 params[255]; /* Link setup Parameters> */ > - u16 paramlen; /* Length of Link Setup > - * Parameters */ > - } utility; /* Configuration for Utility Links (Psock) */ > - } u; > -}; > - > -/* This structure is used internally in CFCTRL */ > -struct cfctrl_request_info { > - int sequence_no; > - enum cfctrl_cmd cmd; > - u8 channel_id; > - struct cfctrl_link_param param; > - struct cflayer *client_layer; > - struct list_head list; > -}; > - > -struct cfctrl { > - struct cfsrvl serv; > - struct cfctrl_rsp res; > - atomic_t req_seq_no; > - atomic_t rsp_seq_no; > - struct list_head list; > - /* Protects from simultaneous access to first_req list */ > - spinlock_t info_list_lock; > -#ifndef CAIF_NO_LOOP > - u8 loop_linkid; > - int loop_linkused[256]; > - /* Protects simultaneous access to loop_linkid and loop_linkused */ > - spinlock_t loop_linkid_lock; > -#endif > - > -}; > - > -void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid); > -int cfctrl_linkup_request(struct cflayer *cfctrl, > - struct cfctrl_link_param *param, > - struct cflayer *user_layer); > -int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid, > - struct cflayer *client); > - > -struct cflayer *cfctrl_create(void); > -struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer); > -int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer); > -void cfctrl_remove(struct cflayer *layr); > - > -#endif /* CFCTRL_H_ */ > diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h > deleted file mode 100644 > index 1ab8a80ede4d..000000000000 > --- a/include/net/caif/cffrml.h > +++ /dev/null > @@ -1,21 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFFRML_H_ > -#define CFFRML_H_ > -#include > -#include > - > -struct cffrml; > -struct cflayer *cffrml_create(u16 phyid, bool use_fcs); > -void cffrml_free(struct cflayer *layr); > -void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up); > -void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn); > -void cffrml_put(struct cflayer *layr); > -void cffrml_hold(struct cflayer *layr); > -int cffrml_refcnt_read(struct cflayer *layr); > - > -#endif /* CFFRML_H_ */ > diff --git a/include/net/caif/cfmuxl.h b/include/net/caif/cfmuxl.h > deleted file mode 100644 > index 92ccb2648309..000000000000 > --- a/include/net/caif/cfmuxl.h > +++ /dev/null > @@ -1,20 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFMUXL_H_ > -#define CFMUXL_H_ > -#include > - > -struct cfsrvl; > -struct cffrml; > - > -struct cflayer *cfmuxl_create(void); > -int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid); > -struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid); > -int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid); > -struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid); > - > -#endif /* CFMUXL_H_ */ > diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h > deleted file mode 100644 > index acf664227d96..000000000000 > --- a/include/net/caif/cfpkt.h > +++ /dev/null > @@ -1,232 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFPKT_H_ > -#define CFPKT_H_ > -#include > -#include > -struct cfpkt; > - > -/* Create a CAIF packet. > - * len: Length of packet to be created > - * @return New packet. > - */ > -struct cfpkt *cfpkt_create(u16 len); > - > -/* > - * Destroy a CAIF Packet. > - * pkt Packet to be destroyed. > - */ > -void cfpkt_destroy(struct cfpkt *pkt); > - > -/* > - * Extract header from packet. > - * > - * pkt Packet to extract header data from. > - * data Pointer to copy the header data into. > - * len Length of head data to copy. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len); > - > -static inline u8 cfpkt_extr_head_u8(struct cfpkt *pkt) > -{ > - u8 tmp; > - > - cfpkt_extr_head(pkt, &tmp, 1); > - > - return tmp; > -} > - > -static inline u16 cfpkt_extr_head_u16(struct cfpkt *pkt) > -{ > - __le16 tmp; > - > - cfpkt_extr_head(pkt, &tmp, 2); > - > - return le16_to_cpu(tmp); > -} > - > -static inline u32 cfpkt_extr_head_u32(struct cfpkt *pkt) > -{ > - __le32 tmp; > - > - cfpkt_extr_head(pkt, &tmp, 4); > - > - return le32_to_cpu(tmp); > -} > - > -/* > - * Peek header from packet. > - * Reads data from packet without changing packet. > - * > - * pkt Packet to extract header data from. > - * data Pointer to copy the header data into. > - * len Length of head data to copy. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len); > - > -/* > - * Extract header from trailer (end of packet). > - * > - * pkt Packet to extract header data from. > - * data Pointer to copy the trailer data into. > - * len Length of header data to copy. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_extr_trail(struct cfpkt *pkt, void *data, u16 len); > - > -/* > - * Add header to packet. > - * > - * > - * pkt Packet to add header data to. > - * data Pointer to data to copy into the header. > - * len Length of header data to copy. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_add_head(struct cfpkt *pkt, const void *data, u16 len); > - > -/* > - * Add trailer to packet. > - * > - * > - * pkt Packet to add trailer data to. > - * data Pointer to data to copy into the trailer. > - * len Length of trailer data to copy. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len); > - > -/* > - * Pad trailer on packet. > - * Moves data pointer in packet, no content copied. > - * > - * pkt Packet in which to pad trailer. > - * len Length of padding to add. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_pad_trail(struct cfpkt *pkt, u16 len); > - > -/* > - * Add a single byte to packet body (tail). > - * > - * pkt Packet in which to add byte. > - * data Byte to add. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_addbdy(struct cfpkt *pkt, const u8 data); > - > -/* > - * Add a data to packet body (tail). > - * > - * pkt Packet in which to add data. > - * data Pointer to data to copy into the packet body. > - * len Length of data to add. > - * @return zero on success and error code upon failure > - */ > -int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len); > - > -/* > - * Checks whether there are more data to process in packet. > - * pkt Packet to check. > - * @return true if more data are available in packet false otherwise > - */ > -bool cfpkt_more(struct cfpkt *pkt); > - > -/* > - * Checks whether the packet is erroneous, > - * i.e. if it has been attempted to extract more data than available in packet > - * or writing more data than has been allocated in cfpkt_create(). > - * pkt Packet to check. > - * @return true on error false otherwise > - */ > -bool cfpkt_erroneous(struct cfpkt *pkt); > - > -/* > - * Get the packet length. > - * pkt Packet to get length from. > - * @return Number of bytes in packet. > - */ > -u16 cfpkt_getlen(struct cfpkt *pkt); > - > -/* > - * Set the packet length, by adjusting the trailer pointer according to length. > - * pkt Packet to set length. > - * len Packet length. > - * @return Number of bytes in packet. > - */ > -int cfpkt_setlen(struct cfpkt *pkt, u16 len); > - > -/* > - * cfpkt_append - Appends a packet's data to another packet. > - * dstpkt: Packet to append data into, WILL BE FREED BY THIS FUNCTION > - * addpkt: Packet to be appended and automatically released, > - * WILL BE FREED BY THIS FUNCTION. > - * expectlen: Packet's expected total length. This should be considered > - * as a hint. > - * NB: Input packets will be destroyed after appending and cannot be used > - * after calling this function. > - * @return The new appended packet. > - */ > -struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt, > - u16 expectlen); > - > -/* > - * cfpkt_split - Split a packet into two packets at the specified split point. > - * pkt: Packet to be split (will contain the first part of the data on exit) > - * pos: Position to split packet in two parts. > - * @return The new packet, containing the second part of the data. > - */ > -struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos); > - > -/* > - * Iteration function, iterates the packet buffers from start to end. > - * > - * Checksum iteration function used to iterate buffers > - * (we may have packets consisting of a chain of buffers) > - * pkt: Packet to calculate checksum for > - * iter_func: Function pointer to iteration function > - * chks: Checksum calculated so far. > - * buf: Pointer to the buffer to checksum > - * len: Length of buf. > - * data: Initial checksum value. > - * @return Checksum of buffer. > - */ > - > -int cfpkt_iterate(struct cfpkt *pkt, > - u16 (*iter_func)(u16 chks, void *buf, u16 len), > - u16 data); > - > -/* Map from a "native" packet (e.g. Linux Socket Buffer) to a CAIF packet. > - * dir - Direction indicating whether this packet is to be sent or received. > - * nativepkt - The native packet to be transformed to a CAIF packet > - * @return The mapped CAIF Packet CFPKT. > - */ > -struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt); > - > -/* Map from a CAIF packet to a "native" packet (e.g. Linux Socket Buffer). > - * pkt - The CAIF packet to be transformed into a "native" packet. > - * @return The native packet transformed from a CAIF packet. > - */ > -void *cfpkt_tonative(struct cfpkt *pkt); > - > -/* > - * Returns packet information for a packet. > - * pkt Packet to get info from; > - * @return Packet information > - */ > -struct caif_payload_info *cfpkt_info(struct cfpkt *pkt); > - > -/** cfpkt_set_prio - set priority for a CAIF packet. > - * > - * @pkt: The CAIF packet to be adjusted. > - * @prio: one of TC_PRIO_ constants. > - */ > -void cfpkt_set_prio(struct cfpkt *pkt, int prio); > - > -#endif /* CFPKT_H_ */ > diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h > deleted file mode 100644 > index 67cce8757175..000000000000 > --- a/include/net/caif/cfserl.h > +++ /dev/null > @@ -1,13 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFSERL_H_ > -#define CFSERL_H_ > -#include > - > -struct cflayer *cfserl_create(int instance, bool use_stx); > -void cfserl_release(struct cflayer *layer); > -#endif > diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h > deleted file mode 100644 > index a000dc45f966..000000000000 > --- a/include/net/caif/cfsrvl.h > +++ /dev/null > @@ -1,61 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0-only */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#ifndef CFSRVL_H_ > -#define CFSRVL_H_ > -#include > -#include > -#include > -#include > -#include > - > -struct cfsrvl { > - struct cflayer layer; > - bool open; > - bool phy_flow_on; > - bool modem_flow_on; > - bool supports_flowctrl; > - void (*release)(struct cflayer *layer); > - struct dev_info dev_info; > - void (*hold)(struct cflayer *lyr); > - void (*put)(struct cflayer *lyr); > - struct rcu_head rcu; > -}; > - > -struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); > -struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info); > -struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info); > -struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info); > -struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, > - int mtu_size); > -struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); > - > -bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); > - > -void cfsrvl_init(struct cfsrvl *service, > - u8 channel_id, > - struct dev_info *dev_info, > - bool supports_flowctrl); > -bool cfsrvl_ready(struct cfsrvl *service, int *err); > - > -static inline void cfsrvl_get(struct cflayer *layr) > -{ > - struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); > - if (layr == NULL || layr->up == NULL || s->hold == NULL) > - return; > - > - s->hold(layr->up); > -} > - > -static inline void cfsrvl_put(struct cflayer *layr) > -{ > - struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); > - if (layr == NULL || layr->up == NULL || s->hold == NULL) > - return; > - > - s->put(layr->up); > -} > -#endif /* CFSRVL_H_ */ > diff --git a/include/uapi/linux/caif/caif_socket.h b/include/uapi/linux/caif/caif_socket.h > deleted file mode 100644 > index d9970bbaa156..000000000000 > --- a/include/uapi/linux/caif/caif_socket.h > +++ /dev/null > @@ -1,195 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > -/* linux/caif_socket.h > - * CAIF Definitions for CAIF socket and network layer > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - * License terms: GNU General Public License (GPL) version 2 > - */ > - > -#ifndef _LINUX_CAIF_SOCKET_H > -#define _LINUX_CAIF_SOCKET_H > - > -#include > -#include > - > -/** > - * enum caif_link_selector - Physical Link Selection. > - * @CAIF_LINK_HIGH_BANDW: Physical interface for high-bandwidth > - * traffic. > - * @CAIF_LINK_LOW_LATENCY: Physical interface for low-latency > - * traffic. > - * > - * CAIF Link Layers can register their link properties. > - * This enum is used for choosing between CAIF Link Layers when > - * setting up CAIF Channels when multiple CAIF Link Layers exists. > - */ > -enum caif_link_selector { > - CAIF_LINK_HIGH_BANDW, > - CAIF_LINK_LOW_LATENCY > -}; > - > -/** > - * enum caif_channel_priority - CAIF channel priorities. > - * > - * @CAIF_PRIO_MIN: Min priority for a channel. > - * @CAIF_PRIO_LOW: Low-priority channel. > - * @CAIF_PRIO_NORMAL: Normal/default priority level. > - * @CAIF_PRIO_HIGH: High priority level > - * @CAIF_PRIO_MAX: Max priority for channel > - * > - * Priority can be set on CAIF Channels in order to > - * prioritize between traffic on different CAIF Channels. > - * These priority levels are recommended, but the priority value > - * is not restricted to the values defined in this enum, any value > - * between CAIF_PRIO_MIN and CAIF_PRIO_MAX could be used. > - */ > -enum caif_channel_priority { > - CAIF_PRIO_MIN = 0x01, > - CAIF_PRIO_LOW = 0x04, > - CAIF_PRIO_NORMAL = 0x0f, > - CAIF_PRIO_HIGH = 0x14, > - CAIF_PRIO_MAX = 0x1F > -}; > - > -/** > - * enum caif_protocol_type - CAIF Channel type. > - * @CAIFPROTO_AT: Classic AT channel. > - * @CAIFPROTO_DATAGRAM: Datagram channel. > - * @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing. > - * @CAIFPROTO_UTIL: Utility (Psock) channel. > - * @CAIFPROTO_RFM: Remote File Manager > - * @CAIFPROTO_DEBUG: Debug link > - * > - * This enum defines the CAIF Channel type to be used. This defines > - * the service to connect to on the modem. > - */ > -enum caif_protocol_type { > - CAIFPROTO_AT, > - CAIFPROTO_DATAGRAM, > - CAIFPROTO_DATAGRAM_LOOP, > - CAIFPROTO_UTIL, > - CAIFPROTO_RFM, > - CAIFPROTO_DEBUG, > - _CAIFPROTO_MAX > -}; > -#define CAIFPROTO_MAX _CAIFPROTO_MAX > - > -/** > - * enum caif_at_type - AT Service Endpoint > - * @CAIF_ATTYPE_PLAIN: Connects to a plain vanilla AT channel. > - */ > -enum caif_at_type { > - CAIF_ATTYPE_PLAIN = 2 > -}; > - /** > - * enum caif_debug_type - Content selection for debug connection > - * @CAIF_DEBUG_TRACE_INTERACTIVE: Connection will contain > - * both trace and interactive debug. > - * @CAIF_DEBUG_TRACE: Connection contains trace only. > - * @CAIF_DEBUG_INTERACTIVE: Connection to interactive debug. > - */ > -enum caif_debug_type { > - CAIF_DEBUG_TRACE_INTERACTIVE = 0, > - CAIF_DEBUG_TRACE, > - CAIF_DEBUG_INTERACTIVE, > -}; > - > -/** > - * enum caif_debug_service - Debug Service Endpoint > - * @CAIF_RADIO_DEBUG_SERVICE: Debug service on the Radio sub-system > - * @CAIF_APP_DEBUG_SERVICE: Debug for the applications sub-system > - */ > -enum caif_debug_service { > - CAIF_RADIO_DEBUG_SERVICE = 1, > - CAIF_APP_DEBUG_SERVICE > -}; > - > -/** > - * struct sockaddr_caif - the sockaddr structure for CAIF sockets. > - * @family: Address family number, must be AF_CAIF. > - * @u: Union of address data 'switched' by family. > - * : > - * @u.at: Applies when family = CAIFPROTO_AT. > - * > - * @u.at.type: Type of AT link to set up (enum caif_at_type). > - * > - * @u.util: Applies when family = CAIFPROTO_UTIL > - * > - * @u.util.service: Utility service name. > - * > - * @u.dgm: Applies when family = CAIFPROTO_DATAGRAM > - * > - * @u.dgm.connection_id: Datagram connection id. > - * > - * @u.dgm.nsapi: NSAPI of the PDP-Context. > - * > - * @u.rfm: Applies when family = CAIFPROTO_RFM > - * > - * @u.rfm.connection_id: Connection ID for RFM. > - * > - * @u.rfm.volume: Volume to mount. > - * > - * @u.dbg: Applies when family = CAIFPROTO_DEBUG. > - * > - * @u.dbg.type: Type of debug connection to set up > - * (caif_debug_type). > - * > - * @u.dbg.service: Service sub-system to connect (caif_debug_service > - * Description: > - * This structure holds the connect parameters used for setting up a > - * CAIF Channel. It defines the service to connect to on the modem. > - */ > -struct sockaddr_caif { > - __kernel_sa_family_t family; > - union { > - struct { > - __u8 type; /* type: enum caif_at_type */ > - } at; /* CAIFPROTO_AT */ > - struct { > - char service[16]; > - } util; /* CAIFPROTO_UTIL */ > - union { > - __u32 connection_id; > - __u8 nsapi; > - } dgm; /* CAIFPROTO_DATAGRAM(_LOOP)*/ > - struct { > - __u32 connection_id; > - char volume[16]; > - } rfm; /* CAIFPROTO_RFM */ > - struct { > - __u8 type; /* type:enum caif_debug_type */ > - __u8 service; /* service:caif_debug_service */ > - } dbg; /* CAIFPROTO_DEBUG */ > - } u; > -}; > - > -/** > - * enum caif_socket_opts - CAIF option values for getsockopt and setsockopt. > - * > - * @CAIFSO_LINK_SELECT: Selector used if multiple CAIF Link layers are > - * available. Either a high bandwidth > - * link can be selected (CAIF_LINK_HIGH_BANDW) or > - * a low latency link (CAIF_LINK_LOW_LATENCY). > - * This option is of type __u32. > - * Alternatively SO_BINDTODEVICE can be used. > - * > - * @CAIFSO_REQ_PARAM: Used to set the request parameters for a > - * utility channel. (maximum 256 bytes). This > - * option must be set before connecting. > - * > - * @CAIFSO_RSP_PARAM: Gets the response parameters for a utility > - * channel. (maximum 256 bytes). This option > - * is valid after a successful connect. > - * > - * > - * This enum defines the CAIF Socket options to be used on a socket > - * of type PF_CAIF. > - * > - */ > -enum caif_socket_opts { > - CAIFSO_LINK_SELECT = 127, > - CAIFSO_REQ_PARAM = 128, > - CAIFSO_RSP_PARAM = 129, > -}; > - > -#endif /* _LINUX_CAIF_SOCKET_H */ > diff --git a/include/uapi/linux/caif/if_caif.h b/include/uapi/linux/caif/if_caif.h > deleted file mode 100644 > index 74bca19403fa..000000000000 > --- a/include/uapi/linux/caif/if_caif.h > +++ /dev/null > @@ -1,35 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - * License terms: GNU General Public License (GPL) version 2 > - */ > - > -#ifndef IF_CAIF_H_ > -#define IF_CAIF_H_ > -#include > -#include > -#include > - > -/** > - * enum ifla_caif - CAIF NetlinkRT parameters. > - * @IFLA_CAIF_IPV4_CONNID: Connection ID for IPv4 PDP Context. > - * The type of attribute is NLA_U32. > - * @IFLA_CAIF_IPV6_CONNID: Connection ID for IPv6 PDP Context. > - * The type of attribute is NLA_U32. > - * @IFLA_CAIF_LOOPBACK: If different from zero, device is doing loopback > - * The type of attribute is NLA_U8. > - * > - * When using RT Netlink to create, destroy or configure a CAIF IP interface, > - * enum ifla_caif is used to specify the configuration attributes. > - */ > -enum ifla_caif { > - __IFLA_CAIF_UNSPEC, > - IFLA_CAIF_IPV4_CONNID, > - IFLA_CAIF_IPV6_CONNID, > - IFLA_CAIF_LOOPBACK, > - __IFLA_CAIF_MAX > -}; > -#define IFLA_CAIF_MAX (__IFLA_CAIF_MAX-1) > - > -#endif /*IF_CAIF_H_*/ > diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c > deleted file mode 100644 > index 1873d8287bb9..000000000000 > --- a/drivers/net/caif/caif_serial.c > +++ /dev/null > @@ -1,443 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -MODULE_LICENSE("GPL"); > -MODULE_AUTHOR("Sjur Brendeland"); > -MODULE_DESCRIPTION("CAIF serial device TTY line discipline"); > -MODULE_LICENSE("GPL"); > -MODULE_ALIAS_LDISC(N_CAIF); > - > -#define SEND_QUEUE_LOW 10 > -#define SEND_QUEUE_HIGH 100 > -#define CAIF_SENDING 1 /* Bit 1 = 0x02*/ > -#define CAIF_FLOW_OFF_SENT 4 /* Bit 4 = 0x10 */ > -#define MAX_WRITE_CHUNK 4096 > -#define ON 1 > -#define OFF 0 > -#define CAIF_MAX_MTU 4096 > - > -static DEFINE_SPINLOCK(ser_lock); > -static LIST_HEAD(ser_list); > -static LIST_HEAD(ser_release_list); > - > -static bool ser_loop; > -module_param(ser_loop, bool, 0444); > -MODULE_PARM_DESC(ser_loop, "Run in simulated loopback mode."); > - > -static bool ser_use_stx = true; > -module_param(ser_use_stx, bool, 0444); > -MODULE_PARM_DESC(ser_use_stx, "STX enabled or not."); > - > -static bool ser_use_fcs = true; > - > -module_param(ser_use_fcs, bool, 0444); > -MODULE_PARM_DESC(ser_use_fcs, "FCS enabled or not."); > - > -static int ser_write_chunk = MAX_WRITE_CHUNK; > -module_param(ser_write_chunk, int, 0444); > - > -MODULE_PARM_DESC(ser_write_chunk, "Maximum size of data written to UART."); > - > -static struct dentry *debugfsdir; > - > -static int caif_net_open(struct net_device *dev); > -static int caif_net_close(struct net_device *dev); > - > -struct ser_device { > - struct caif_dev_common common; > - struct list_head node; > - struct net_device *dev; > - struct sk_buff_head head; > - struct tty_struct *tty; > - bool tx_started; > - unsigned long state; > -#ifdef CONFIG_DEBUG_FS > - struct dentry *debugfs_tty_dir; > - struct debugfs_blob_wrapper tx_blob; > - struct debugfs_blob_wrapper rx_blob; > - u8 rx_data[128]; > - u8 tx_data[128]; > - u8 tty_status; > - > -#endif > -}; > - > -static void caifdev_setup(struct net_device *dev); > -static void ldisc_tx_wakeup(struct tty_struct *tty); > -#ifdef CONFIG_DEBUG_FS > -static inline void update_tty_status(struct ser_device *ser) > -{ > - ser->tty_status = > - ser->tty->flow.stopped << 5 | > - ser->tty->flow.tco_stopped << 3 | > - ser->tty->ctrl.packet << 2; > -} > -static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) > -{ > - ser->debugfs_tty_dir = debugfs_create_dir(tty->name, debugfsdir); > - > - debugfs_create_blob("last_tx_msg", 0400, ser->debugfs_tty_dir, > - &ser->tx_blob); > - > - debugfs_create_blob("last_rx_msg", 0400, ser->debugfs_tty_dir, > - &ser->rx_blob); > - > - debugfs_create_xul("ser_state", 0400, ser->debugfs_tty_dir, > - &ser->state); > - > - debugfs_create_x8("tty_status", 0400, ser->debugfs_tty_dir, > - &ser->tty_status); > - > - ser->tx_blob.data = ser->tx_data; > - ser->tx_blob.size = 0; > - ser->rx_blob.data = ser->rx_data; > - ser->rx_blob.size = 0; > -} > - > -static inline void debugfs_deinit(struct ser_device *ser) > -{ > - debugfs_remove_recursive(ser->debugfs_tty_dir); > -} > - > -static inline void debugfs_rx(struct ser_device *ser, const u8 *data, int size) > -{ > - if (size > sizeof(ser->rx_data)) > - size = sizeof(ser->rx_data); > - memcpy(ser->rx_data, data, size); > - ser->rx_blob.data = ser->rx_data; > - ser->rx_blob.size = size; > -} > -#else > -static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) > -{ > -} > - > -static inline void debugfs_deinit(struct ser_device *ser) > -{ > -} > - > -static inline void update_tty_status(struct ser_device *ser) > -{ > -} > - > -static inline void debugfs_rx(struct ser_device *ser, const u8 *data, int size) > -{ > -} > -#endif > - > -static void ldisc_receive(struct tty_struct *tty, const u8 *data, > - const u8 *flags, size_t count) > -{ > - struct sk_buff *skb = NULL; > - struct ser_device *ser; > - int ret; > - > - ser = tty->disc_data; > - > - /* > - * NOTE: flags may contain information about break or overrun. > - * This is not yet handled. > - */ > - > - > - /* > - * Workaround for garbage at start of transmission, > - * only enable if STX handling is not enabled. > - */ > - if (!ser->common.use_stx && !ser->tx_started) { > - dev_info(&ser->dev->dev, > - "Bytes received before initial transmission -" > - "bytes discarded.\n"); > - return; > - } > - > - BUG_ON(ser->dev == NULL); > - > - /* Get a suitable caif packet and copy in data. */ > - skb = netdev_alloc_skb(ser->dev, count+1); > - if (skb == NULL) > - return; > - skb_put_data(skb, data, count); > - > - skb->protocol = htons(ETH_P_CAIF); > - skb_reset_mac_header(skb); > - debugfs_rx(ser, data, count); > - /* Push received packet up the stack. */ > - ret = netif_rx(skb); > - if (!ret) { > - ser->dev->stats.rx_packets++; > - ser->dev->stats.rx_bytes += count; > - } else > - ++ser->dev->stats.rx_dropped; > - update_tty_status(ser); > -} > - > -static int handle_tx(struct ser_device *ser) > -{ > - struct tty_struct *tty; > - struct sk_buff *skb; > - int tty_wr, len, room; > - > - tty = ser->tty; > - ser->tx_started = true; > - > - /* Enter critical section */ > - if (test_and_set_bit(CAIF_SENDING, &ser->state)) > - return 0; > - > - /* skb_peek is safe because handle_tx is called after skb_queue_tail */ > - while ((skb = skb_peek(&ser->head)) != NULL) { > - > - /* Make sure you don't write too much */ > - len = skb->len; > - room = tty_write_room(tty); > - if (!room) > - break; > - if (room > ser_write_chunk) > - room = ser_write_chunk; > - if (len > room) > - len = room; > - > - /* Write to tty or loopback */ > - if (!ser_loop) { > - tty_wr = tty->ops->write(tty, skb->data, len); > - update_tty_status(ser); > - } else { > - tty_wr = len; > - ldisc_receive(tty, skb->data, NULL, len); > - } > - ser->dev->stats.tx_packets++; > - ser->dev->stats.tx_bytes += tty_wr; > - > - /* Error on TTY ?! */ > - if (tty_wr < 0) > - goto error; > - /* Reduce buffer written, and discard if empty */ > - skb_pull(skb, tty_wr); > - if (skb->len == 0) { > - struct sk_buff *tmp = skb_dequeue(&ser->head); > - WARN_ON(tmp != skb); > - dev_consume_skb_any(skb); > - } > - } > - /* Send flow off if queue is empty */ > - if (ser->head.qlen <= SEND_QUEUE_LOW && > - test_and_clear_bit(CAIF_FLOW_OFF_SENT, &ser->state) && > - ser->common.flowctrl != NULL) > - ser->common.flowctrl(ser->dev, ON); > - clear_bit(CAIF_SENDING, &ser->state); > - return 0; > -error: > - clear_bit(CAIF_SENDING, &ser->state); > - return tty_wr; > -} > - > -static netdev_tx_t caif_xmit(struct sk_buff *skb, struct net_device *dev) > -{ > - struct ser_device *ser; > - > - ser = netdev_priv(dev); > - > - /* Send flow off once, on high water mark */ > - if (ser->head.qlen > SEND_QUEUE_HIGH && > - !test_and_set_bit(CAIF_FLOW_OFF_SENT, &ser->state) && > - ser->common.flowctrl != NULL) > - > - ser->common.flowctrl(ser->dev, OFF); > - > - skb_queue_tail(&ser->head, skb); > - return handle_tx(ser); > -} > - > - > -static void ldisc_tx_wakeup(struct tty_struct *tty) > -{ > - struct ser_device *ser; > - > - ser = tty->disc_data; > - BUG_ON(ser == NULL); > - WARN_ON(ser->tty != tty); > - handle_tx(ser); > -} > - > - > -static void ser_release(struct work_struct *work) > -{ > - struct list_head list; > - struct ser_device *ser, *tmp; > - struct tty_struct *tty; > - > - spin_lock(&ser_lock); > - list_replace_init(&ser_release_list, &list); > - spin_unlock(&ser_lock); > - > - if (!list_empty(&list)) { > - rtnl_lock(); > - list_for_each_entry_safe(ser, tmp, &list, node) { > - tty = ser->tty; > - dev_close(ser->dev); > - unregister_netdevice(ser->dev); > - debugfs_deinit(ser); > - tty_kref_put(tty->link); > - tty_kref_put(tty); > - } > - rtnl_unlock(); > - } > -} > - > -static DECLARE_WORK(ser_release_work, ser_release); > - > -static int ldisc_open(struct tty_struct *tty) > -{ > - struct ser_device *ser; > - struct net_device *dev; > - char name[64]; > - int result; > - > - /* No write no play */ > - if (tty->ops->write == NULL) > - return -EOPNOTSUPP; > - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_TTY_CONFIG)) > - return -EPERM; > - > - /* release devices to avoid name collision */ > - ser_release(NULL); > - > - result = snprintf(name, sizeof(name), "cf%s", tty->name); > - if (result >= IFNAMSIZ) > - return -EINVAL; > - dev = alloc_netdev(sizeof(*ser), name, NET_NAME_UNKNOWN, > - caifdev_setup); > - if (!dev) > - return -ENOMEM; > - > - ser = netdev_priv(dev); > - ser->tty = tty_kref_get(tty); > - tty_kref_get(tty->link); > - ser->dev = dev; > - debugfs_init(ser, tty); > - tty->receive_room = 4096; > - tty->disc_data = ser; > - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); > - rtnl_lock(); > - result = register_netdevice(dev); > - if (result) { > - tty_kref_put(tty->link); > - tty_kref_put(tty); > - rtnl_unlock(); > - free_netdev(dev); > - return -ENODEV; > - } > - > - spin_lock(&ser_lock); > - list_add(&ser->node, &ser_list); > - spin_unlock(&ser_lock); > - rtnl_unlock(); > - netif_stop_queue(dev); > - update_tty_status(ser); > - return 0; > -} > - > -static void ldisc_close(struct tty_struct *tty) > -{ > - struct ser_device *ser = tty->disc_data; > - > - spin_lock(&ser_lock); > - list_move(&ser->node, &ser_release_list); > - spin_unlock(&ser_lock); > - schedule_work(&ser_release_work); > -} > - > -/* The line discipline structure. */ > -static struct tty_ldisc_ops caif_ldisc = { > - .owner = THIS_MODULE, > - .num = N_CAIF, > - .name = "n_caif", > - .open = ldisc_open, > - .close = ldisc_close, > - .receive_buf = ldisc_receive, > - .write_wakeup = ldisc_tx_wakeup > -}; > - > -static const struct net_device_ops netdev_ops = { > - .ndo_open = caif_net_open, > - .ndo_stop = caif_net_close, > - .ndo_start_xmit = caif_xmit > -}; > - > -static void caifdev_setup(struct net_device *dev) > -{ > - struct ser_device *serdev = netdev_priv(dev); > - > - dev->features = 0; > - dev->netdev_ops = &netdev_ops; > - dev->type = ARPHRD_CAIF; > - dev->flags = IFF_POINTOPOINT | IFF_NOARP; > - dev->mtu = CAIF_MAX_MTU; > - dev->priv_flags |= IFF_NO_QUEUE; > - dev->needs_free_netdev = true; > - skb_queue_head_init(&serdev->head); > - serdev->common.link_select = CAIF_LINK_LOW_LATENCY; > - serdev->common.use_frag = true; > - serdev->common.use_stx = ser_use_stx; > - serdev->common.use_fcs = ser_use_fcs; > - serdev->dev = dev; > -} > - > - > -static int caif_net_open(struct net_device *dev) > -{ > - netif_wake_queue(dev); > - return 0; > -} > - > -static int caif_net_close(struct net_device *dev) > -{ > - netif_stop_queue(dev); > - return 0; > -} > - > -static int __init caif_ser_init(void) > -{ > - int ret; > - > - ret = tty_register_ldisc(&caif_ldisc); > - if (ret < 0) > - pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF, ret); > - > - debugfsdir = debugfs_create_dir("caif_serial", NULL); > - return ret; > -} > - > -static void __exit caif_ser_exit(void) > -{ > - spin_lock(&ser_lock); > - list_splice(&ser_list, &ser_release_list); > - spin_unlock(&ser_lock); > - ser_release(NULL); > - cancel_work_sync(&ser_release_work); > - tty_unregister_ldisc(&caif_ldisc); > - debugfs_remove_recursive(debugfsdir); > -} > - > -module_init(caif_ser_init); > -module_exit(caif_ser_exit); > diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c > deleted file mode 100644 > index 8ac1a4b8e055..000000000000 > --- a/drivers/net/caif/caif_virtio.c > +++ /dev/null > @@ -1,791 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2013 > - * Authors: Vicram Arv > - * Dmitry Tarnyagin > - * Sjur Brendeland > - */ > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -MODULE_LICENSE("GPL v2"); > -MODULE_AUTHOR("Vicram Arv"); > -MODULE_AUTHOR("Sjur Brendeland"); > -MODULE_DESCRIPTION("Virtio CAIF Driver"); > - > -/* NAPI schedule quota */ > -#define CFV_DEFAULT_QUOTA 32 > - > -/* Defaults used if virtio config space is unavailable */ > -#define CFV_DEF_MTU_SIZE 4096 > -#define CFV_DEF_HEADROOM 32 > -#define CFV_DEF_TAILROOM 32 > - > -/* Required IP header alignment */ > -#define IP_HDR_ALIGN 4 > - > -/* struct cfv_napi_contxt - NAPI context info > - * @riov: IOV holding data read from the ring. Note that riov may > - * still hold data when cfv_rx_poll() returns. > - * @head: Last descriptor ID we received from vringh_getdesc_kern. > - * We use this to put descriptor back on the used ring. USHRT_MAX is > - * used to indicate invalid head-id. > - */ > -struct cfv_napi_context { > - struct vringh_kiov riov; > - unsigned short head; > -}; > - > -/* struct cfv_stats - statistics for debugfs > - * @rx_napi_complete: Number of NAPI completions (RX) > - * @rx_napi_resched: Number of calls where the full quota was used (RX) > - * @rx_nomem: Number of SKB alloc failures (RX) > - * @rx_kicks: Number of RX kicks > - * @tx_full_ring: Number times TX ring was full > - * @tx_no_mem: Number of times TX went out of memory > - * @tx_flow_on: Number of flow on (TX) > - * @tx_kicks: Number of TX kicks > - */ > -struct cfv_stats { > - u32 rx_napi_complete; > - u32 rx_napi_resched; > - u32 rx_nomem; > - u32 rx_kicks; > - u32 tx_full_ring; > - u32 tx_no_mem; > - u32 tx_flow_on; > - u32 tx_kicks; > -}; > - > -/* struct cfv_info - Caif Virtio control structure > - * @cfdev: caif common header > - * @vdev: Associated virtio device > - * @vr_rx: rx/downlink host vring > - * @vq_tx: tx/uplink virtqueue > - * @ndev: CAIF link layer device > - * @watermark_tx: indicates number of free descriptors we need > - * to reopen the tx-queues after overload. > - * @tx_lock: protects vq_tx from concurrent use > - * @tx_release_tasklet: Tasklet for freeing consumed TX buffers > - * @napi: Napi context used in cfv_rx_poll() > - * @ctx: Context data used in cfv_rx_poll() > - * @tx_hr: transmit headroom > - * @rx_hr: receive headroom > - * @tx_tr: transmit tail room > - * @rx_tr: receive tail room > - * @mtu: transmit max size > - * @mru: receive max size > - * @allocsz: size of dma memory reserved for TX buffers > - * @alloc_addr: virtual address to dma memory for TX buffers > - * @alloc_dma: dma address to dma memory for TX buffers > - * @genpool: Gen Pool used for allocating TX buffers > - * @reserved_mem: Pointer to memory reserve allocated from genpool > - * @reserved_size: Size of memory reserve allocated from genpool > - * @stats: Statistics exposed in sysfs > - * @debugfs: Debugfs dentry for statistic counters > - */ > -struct cfv_info { > - struct caif_dev_common cfdev; > - struct virtio_device *vdev; > - struct vringh *vr_rx; > - struct virtqueue *vq_tx; > - struct net_device *ndev; > - unsigned int watermark_tx; > - /* Protect access to vq_tx */ > - spinlock_t tx_lock; > - struct tasklet_struct tx_release_tasklet; > - struct napi_struct napi; > - struct cfv_napi_context ctx; > - u16 tx_hr; > - u16 rx_hr; > - u16 tx_tr; > - u16 rx_tr; > - u32 mtu; > - u32 mru; > - size_t allocsz; > - void *alloc_addr; > - dma_addr_t alloc_dma; > - struct gen_pool *genpool; > - unsigned long reserved_mem; > - size_t reserved_size; > - struct cfv_stats stats; > - struct dentry *debugfs; > -}; > - > -/* struct buf_info - maintains transmit buffer data handle > - * @size: size of transmit buffer > - * @dma_handle: handle to allocated dma device memory area > - * @vaddr: virtual address mapping to allocated memory area > - */ > -struct buf_info { > - size_t size; > - u8 *vaddr; > -}; > - > -/* Called from virtio device, in IRQ context */ > -static void cfv_release_cb(struct virtqueue *vq_tx) > -{ > - struct cfv_info *cfv = vq_tx->vdev->priv; > - > - ++cfv->stats.tx_kicks; > - tasklet_schedule(&cfv->tx_release_tasklet); > -} > - > -static void free_buf_info(struct cfv_info *cfv, struct buf_info *buf_info) > -{ > - if (!buf_info) > - return; > - gen_pool_free(cfv->genpool, (unsigned long) buf_info->vaddr, > - buf_info->size); > - kfree(buf_info); > -} > - > -/* This is invoked whenever the remote processor completed processing > - * a TX msg we just sent, and the buffer is put back to the used ring. > - */ > -static void cfv_release_used_buf(struct virtqueue *vq_tx) > -{ > - struct cfv_info *cfv = vq_tx->vdev->priv; > - unsigned long flags; > - > - BUG_ON(vq_tx != cfv->vq_tx); > - > - for (;;) { > - unsigned int len; > - struct buf_info *buf_info; > - > - /* Get used buffer from used ring to recycle used descriptors */ > - spin_lock_irqsave(&cfv->tx_lock, flags); > - buf_info = virtqueue_get_buf(vq_tx, &len); > - spin_unlock_irqrestore(&cfv->tx_lock, flags); > - > - /* Stop looping if there are no more buffers to free */ > - if (!buf_info) > - break; > - > - free_buf_info(cfv, buf_info); > - > - /* watermark_tx indicates if we previously stopped the tx > - * queues. If we have enough free stots in the virtio ring, > - * re-establish memory reserved and open up tx queues. > - */ > - if (cfv->vq_tx->num_free <= cfv->watermark_tx) > - continue; > - > - /* Re-establish memory reserve */ > - if (cfv->reserved_mem == 0 && cfv->genpool) > - cfv->reserved_mem = > - gen_pool_alloc(cfv->genpool, > - cfv->reserved_size); > - > - /* Open up the tx queues */ > - if (cfv->reserved_mem) { > - cfv->watermark_tx = > - virtqueue_get_vring_size(cfv->vq_tx); > - netif_tx_wake_all_queues(cfv->ndev); > - /* Buffers are recycled in cfv_netdev_tx, so > - * disable notifications when queues are opened. > - */ > - virtqueue_disable_cb(cfv->vq_tx); > - ++cfv->stats.tx_flow_on; > - } else { > - /* if no memory reserve, wait for more free slots */ > - WARN_ON(cfv->watermark_tx > > - virtqueue_get_vring_size(cfv->vq_tx)); > - cfv->watermark_tx += > - virtqueue_get_vring_size(cfv->vq_tx) / 4; > - } > - } > -} > - > -/* Allocate a SKB and copy packet data to it */ > -static struct sk_buff *cfv_alloc_and_copy_skb(int *err, > - struct cfv_info *cfv, > - u8 *frm, u32 frm_len) > -{ > - struct sk_buff *skb; > - u32 cfpkt_len, pad_len; > - > - *err = 0; > - /* Verify that packet size with down-link header and mtu size */ > - if (frm_len > cfv->mru || frm_len <= cfv->rx_hr + cfv->rx_tr) { > - netdev_err(cfv->ndev, > - "Invalid frmlen:%u mtu:%u hr:%d tr:%d\n", > - frm_len, cfv->mru, cfv->rx_hr, > - cfv->rx_tr); > - *err = -EPROTO; > - return NULL; > - } > - > - cfpkt_len = frm_len - (cfv->rx_hr + cfv->rx_tr); > - pad_len = (unsigned long)(frm + cfv->rx_hr) & (IP_HDR_ALIGN - 1); > - > - skb = netdev_alloc_skb(cfv->ndev, frm_len + pad_len); > - if (!skb) { > - *err = -ENOMEM; > - return NULL; > - } > - > - skb_reserve(skb, cfv->rx_hr + pad_len); > - > - skb_put_data(skb, frm + cfv->rx_hr, cfpkt_len); > - return skb; > -} > - > -/* Get packets from the host vring */ > -static int cfv_rx_poll(struct napi_struct *napi, int quota) > -{ > - struct cfv_info *cfv = container_of(napi, struct cfv_info, napi); > - int rxcnt = 0; > - int err = 0; > - void *buf; > - struct sk_buff *skb; > - struct vringh_kiov *riov = &cfv->ctx.riov; > - unsigned int skb_len; > - > - do { > - skb = NULL; > - > - /* Put the previous iovec back on the used ring and > - * fetch a new iovec if we have processed all elements. > - */ > - if (riov->i == riov->used) { > - if (cfv->ctx.head != USHRT_MAX) { > - vringh_complete_kern(cfv->vr_rx, > - cfv->ctx.head, > - 0); > - cfv->ctx.head = USHRT_MAX; > - } > - > - err = vringh_getdesc_kern( > - cfv->vr_rx, > - riov, > - NULL, > - &cfv->ctx.head, > - GFP_ATOMIC); > - > - if (err <= 0) > - goto exit; > - } > - > - buf = phys_to_virt((unsigned long) riov->iov[riov->i].iov_base); > - /* TODO: Add check on valid buffer address */ > - > - skb = cfv_alloc_and_copy_skb(&err, cfv, buf, > - riov->iov[riov->i].iov_len); > - if (unlikely(err)) > - goto exit; > - > - /* Push received packet up the stack. */ > - skb_len = skb->len; > - skb->protocol = htons(ETH_P_CAIF); > - skb_reset_mac_header(skb); > - skb->dev = cfv->ndev; > - err = netif_receive_skb(skb); > - if (unlikely(err)) { > - ++cfv->ndev->stats.rx_dropped; > - } else { > - ++cfv->ndev->stats.rx_packets; > - cfv->ndev->stats.rx_bytes += skb_len; > - } > - > - ++riov->i; > - ++rxcnt; > - } while (rxcnt < quota); > - > - ++cfv->stats.rx_napi_resched; > - goto out; > - > -exit: > - switch (err) { > - case 0: > - ++cfv->stats.rx_napi_complete; > - > - /* Really out of packets? (stolen from virtio_net)*/ > - napi_complete(napi); > - if (unlikely(!vringh_notify_enable_kern(cfv->vr_rx)) && > - napi_schedule_prep(napi)) { > - vringh_notify_disable_kern(cfv->vr_rx); > - __napi_schedule(napi); > - } > - break; > - > - case -ENOMEM: > - ++cfv->stats.rx_nomem; > - dev_kfree_skb(skb); > - /* Stop NAPI poll on OOM, we hope to be polled later */ > - napi_complete(napi); > - vringh_notify_enable_kern(cfv->vr_rx); > - break; > - > - default: > - /* We're doomed, any modem fault is fatal */ > - netdev_warn(cfv->ndev, "Bad ring, disable device\n"); > - cfv->ndev->stats.rx_dropped = riov->used - riov->i; > - napi_complete(napi); > - vringh_notify_disable_kern(cfv->vr_rx); > - netif_carrier_off(cfv->ndev); > - break; > - } > -out: > - if (rxcnt && vringh_need_notify_kern(cfv->vr_rx) > 0) > - vringh_notify(cfv->vr_rx); > - return rxcnt; > -} > - > -static void cfv_recv(struct virtio_device *vdev, struct vringh *vr_rx) > -{ > - struct cfv_info *cfv = vdev->priv; > - > - ++cfv->stats.rx_kicks; > - vringh_notify_disable_kern(cfv->vr_rx); > - napi_schedule(&cfv->napi); > -} > - > -static void cfv_destroy_genpool(struct cfv_info *cfv) > -{ > - if (cfv->alloc_addr) > - dma_free_coherent(cfv->vdev->dev.parent->parent, > - cfv->allocsz, cfv->alloc_addr, > - cfv->alloc_dma); > - > - if (!cfv->genpool) > - return; > - gen_pool_free(cfv->genpool, cfv->reserved_mem, > - cfv->reserved_size); > - gen_pool_destroy(cfv->genpool); > - cfv->genpool = NULL; > -} > - > -static int cfv_create_genpool(struct cfv_info *cfv) > -{ > - int err; > - > - /* dma_alloc can only allocate whole pages, and we need a more > - * fine graned allocation so we use genpool. We ask for space needed > - * by IP and a full ring. If the dma allcoation fails we retry with a > - * smaller allocation size. > - */ > - err = -ENOMEM; > - cfv->allocsz = (virtqueue_get_vring_size(cfv->vq_tx) * > - (ETH_DATA_LEN + cfv->tx_hr + cfv->tx_tr) * 11)/10; > - if (cfv->allocsz <= (num_possible_cpus() + 1) * cfv->ndev->mtu) > - return -EINVAL; > - > - for (;;) { > - if (cfv->allocsz <= num_possible_cpus() * cfv->ndev->mtu) { > - netdev_info(cfv->ndev, "Not enough device memory\n"); > - return -ENOMEM; > - } > - > - cfv->alloc_addr = dma_alloc_coherent( > - cfv->vdev->dev.parent->parent, > - cfv->allocsz, &cfv->alloc_dma, > - GFP_ATOMIC); > - if (cfv->alloc_addr) > - break; > - > - cfv->allocsz = (cfv->allocsz * 3) >> 2; > - } > - > - netdev_dbg(cfv->ndev, "Allocated %zd bytes from dma-memory\n", > - cfv->allocsz); > - > - /* Allocate on 128 bytes boundaries (1 << 7)*/ > - cfv->genpool = gen_pool_create(7, -1); > - if (!cfv->genpool) > - goto err; > - > - err = gen_pool_add_virt(cfv->genpool, (unsigned long)cfv->alloc_addr, > - (phys_addr_t)virt_to_phys(cfv->alloc_addr), > - cfv->allocsz, -1); > - if (err) > - goto err; > - > - /* Reserve some memory for low memory situations. If we hit the roof > - * in the memory pool, we stop TX flow and release the reserve. > - */ > - cfv->reserved_size = num_possible_cpus() * cfv->ndev->mtu; > - cfv->reserved_mem = gen_pool_alloc(cfv->genpool, > - cfv->reserved_size); > - if (!cfv->reserved_mem) { > - err = -ENOMEM; > - goto err; > - } > - > - cfv->watermark_tx = virtqueue_get_vring_size(cfv->vq_tx); > - return 0; > -err: > - cfv_destroy_genpool(cfv); > - return err; > -} > - > -/* Enable the CAIF interface and allocate the memory-pool */ > -static int cfv_netdev_open(struct net_device *netdev) > -{ > - struct cfv_info *cfv = netdev_priv(netdev); > - > - if (cfv_create_genpool(cfv)) > - return -ENOMEM; > - > - netif_carrier_on(netdev); > - napi_enable(&cfv->napi); > - > - /* Schedule NAPI to read any pending packets */ > - napi_schedule(&cfv->napi); > - return 0; > -} > - > -/* Disable the CAIF interface and free the memory-pool */ > -static int cfv_netdev_close(struct net_device *netdev) > -{ > - struct cfv_info *cfv = netdev_priv(netdev); > - unsigned long flags; > - struct buf_info *buf_info; > - > - /* Disable interrupts, queues and NAPI polling */ > - netif_carrier_off(netdev); > - virtqueue_disable_cb(cfv->vq_tx); > - vringh_notify_disable_kern(cfv->vr_rx); > - napi_disable(&cfv->napi); > - > - /* Release any TX buffers on both used and available rings */ > - cfv_release_used_buf(cfv->vq_tx); > - spin_lock_irqsave(&cfv->tx_lock, flags); > - while ((buf_info = virtqueue_detach_unused_buf(cfv->vq_tx))) > - free_buf_info(cfv, buf_info); > - spin_unlock_irqrestore(&cfv->tx_lock, flags); > - > - /* Release all dma allocated memory and destroy the pool */ > - cfv_destroy_genpool(cfv); > - return 0; > -} > - > -/* Allocate a buffer in dma-memory and copy skb to it */ > -static struct buf_info *cfv_alloc_and_copy_to_shm(struct cfv_info *cfv, > - struct sk_buff *skb, > - struct scatterlist *sg) > -{ > - struct caif_payload_info *info = (void *)&skb->cb; > - struct buf_info *buf_info = NULL; > - u8 pad_len, hdr_ofs; > - > - if (!cfv->genpool) > - goto err; > - > - if (unlikely(cfv->tx_hr + skb->len + cfv->tx_tr > cfv->mtu)) { > - netdev_warn(cfv->ndev, "Invalid packet len (%d > %d)\n", > - cfv->tx_hr + skb->len + cfv->tx_tr, cfv->mtu); > - goto err; > - } > - > - buf_info = kmalloc_obj(struct buf_info, GFP_ATOMIC); > - if (unlikely(!buf_info)) > - goto err; > - > - /* Make the IP header aligned in the buffer */ > - hdr_ofs = cfv->tx_hr + info->hdr_len; > - pad_len = hdr_ofs & (IP_HDR_ALIGN - 1); > - buf_info->size = cfv->tx_hr + skb->len + cfv->tx_tr + pad_len; > - > - /* allocate dma memory buffer */ > - buf_info->vaddr = (void *)gen_pool_alloc(cfv->genpool, buf_info->size); > - if (unlikely(!buf_info->vaddr)) > - goto err; > - > - /* copy skbuf contents to send buffer */ > - skb_copy_bits(skb, 0, buf_info->vaddr + cfv->tx_hr + pad_len, skb->len); > - sg_init_one(sg, buf_info->vaddr + pad_len, > - skb->len + cfv->tx_hr + cfv->rx_hr); > - > - return buf_info; > -err: > - kfree(buf_info); > - return NULL; > -} > - > -/* Put the CAIF packet on the virtio ring and kick the receiver */ > -static netdev_tx_t cfv_netdev_tx(struct sk_buff *skb, struct net_device *netdev) > -{ > - struct cfv_info *cfv = netdev_priv(netdev); > - struct buf_info *buf_info; > - struct scatterlist sg; > - unsigned long flags; > - bool flow_off = false; > - int ret; > - > - /* garbage collect released buffers */ > - cfv_release_used_buf(cfv->vq_tx); > - spin_lock_irqsave(&cfv->tx_lock, flags); > - > - /* Flow-off check takes into account number of cpus to make sure > - * virtqueue will not be overfilled in any possible smp conditions. > - * > - * Flow-on is triggered when sufficient buffers are freed > - */ > - if (unlikely(cfv->vq_tx->num_free <= num_present_cpus())) { > - flow_off = true; > - cfv->stats.tx_full_ring++; > - } > - > - /* If we run out of memory, we release the memory reserve and retry > - * allocation. > - */ > - buf_info = cfv_alloc_and_copy_to_shm(cfv, skb, &sg); > - if (unlikely(!buf_info)) { > - cfv->stats.tx_no_mem++; > - flow_off = true; > - > - if (cfv->reserved_mem && cfv->genpool) { > - gen_pool_free(cfv->genpool, cfv->reserved_mem, > - cfv->reserved_size); > - cfv->reserved_mem = 0; > - buf_info = cfv_alloc_and_copy_to_shm(cfv, skb, &sg); > - } > - } > - > - if (unlikely(flow_off)) { > - /* Turn flow on when a 1/4 of the descriptors are released */ > - cfv->watermark_tx = virtqueue_get_vring_size(cfv->vq_tx) / 4; > - /* Enable notifications of recycled TX buffers */ > - virtqueue_enable_cb(cfv->vq_tx); > - netif_tx_stop_all_queues(netdev); > - } > - > - if (unlikely(!buf_info)) { > - /* If the memory reserve does it's job, this shouldn't happen */ > - netdev_warn(cfv->ndev, "Out of gen_pool memory\n"); > - goto err; > - } > - > - ret = virtqueue_add_outbuf(cfv->vq_tx, &sg, 1, buf_info, GFP_ATOMIC); > - if (unlikely((ret < 0))) { > - /* If flow control works, this shouldn't happen */ > - netdev_warn(cfv->ndev, "Failed adding buffer to TX vring:%d\n", > - ret); > - goto err; > - } > - > - /* update netdev statistics */ > - cfv->ndev->stats.tx_packets++; > - cfv->ndev->stats.tx_bytes += skb->len; > - spin_unlock_irqrestore(&cfv->tx_lock, flags); > - > - /* tell the remote processor it has a pending message to read */ > - virtqueue_kick(cfv->vq_tx); > - > - dev_kfree_skb(skb); > - return NETDEV_TX_OK; > -err: > - spin_unlock_irqrestore(&cfv->tx_lock, flags); > - cfv->ndev->stats.tx_dropped++; > - free_buf_info(cfv, buf_info); > - dev_kfree_skb(skb); > - return NETDEV_TX_OK; > -} > - > -static void cfv_tx_release_tasklet(struct tasklet_struct *t) > -{ > - struct cfv_info *cfv = from_tasklet(cfv, t, tx_release_tasklet); > - cfv_release_used_buf(cfv->vq_tx); > -} > - > -static const struct net_device_ops cfv_netdev_ops = { > - .ndo_open = cfv_netdev_open, > - .ndo_stop = cfv_netdev_close, > - .ndo_start_xmit = cfv_netdev_tx, > -}; > - > -static void cfv_netdev_setup(struct net_device *netdev) > -{ > - netdev->netdev_ops = &cfv_netdev_ops; > - netdev->type = ARPHRD_CAIF; > - netdev->tx_queue_len = 100; > - netdev->flags = IFF_POINTOPOINT | IFF_NOARP; > - netdev->mtu = CFV_DEF_MTU_SIZE; > - netdev->needs_free_netdev = true; > -} > - > -/* Create debugfs counters for the device */ > -static inline void debugfs_init(struct cfv_info *cfv) > -{ > - cfv->debugfs = debugfs_create_dir(netdev_name(cfv->ndev), NULL); > - > - debugfs_create_u32("rx-napi-complete", 0400, cfv->debugfs, > - &cfv->stats.rx_napi_complete); > - debugfs_create_u32("rx-napi-resched", 0400, cfv->debugfs, > - &cfv->stats.rx_napi_resched); > - debugfs_create_u32("rx-nomem", 0400, cfv->debugfs, > - &cfv->stats.rx_nomem); > - debugfs_create_u32("rx-kicks", 0400, cfv->debugfs, > - &cfv->stats.rx_kicks); > - debugfs_create_u32("tx-full-ring", 0400, cfv->debugfs, > - &cfv->stats.tx_full_ring); > - debugfs_create_u32("tx-no-mem", 0400, cfv->debugfs, > - &cfv->stats.tx_no_mem); > - debugfs_create_u32("tx-kicks", 0400, cfv->debugfs, > - &cfv->stats.tx_kicks); > - debugfs_create_u32("tx-flow-on", 0400, cfv->debugfs, > - &cfv->stats.tx_flow_on); > -} > - > -/* Setup CAIF for the a virtio device */ > -static int cfv_probe(struct virtio_device *vdev) > -{ > - vrh_callback_t *vrh_cbs = cfv_recv; > - const char *cfv_netdev_name = "cfvrt"; > - struct net_device *netdev; > - struct cfv_info *cfv; > - int err; > - > - netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name, > - NET_NAME_UNKNOWN, cfv_netdev_setup); > - if (!netdev) > - return -ENOMEM; > - > - cfv = netdev_priv(netdev); > - cfv->vdev = vdev; > - cfv->ndev = netdev; > - > - spin_lock_init(&cfv->tx_lock); > - > - /* Get the RX virtio ring. This is a "host side vring". */ > - err = -ENODEV; > - if (!vdev->vringh_config || !vdev->vringh_config->find_vrhs) > - goto err; > - > - err = vdev->vringh_config->find_vrhs(vdev, 1, &cfv->vr_rx, &vrh_cbs); > - if (err) > - goto err; > - > - /* Get the TX virtio ring. This is a "guest side vring". */ > - cfv->vq_tx = virtio_find_single_vq(vdev, cfv_release_cb, "output"); > - if (IS_ERR(cfv->vq_tx)) { > - err = PTR_ERR(cfv->vq_tx); > - goto err; > - } > - > - /* Get the CAIF configuration from virtio config space, if available */ > - if (vdev->config->get) { > - virtio_cread(vdev, struct virtio_caif_transf_config, headroom, > - &cfv->tx_hr); > - virtio_cread(vdev, struct virtio_caif_transf_config, headroom, > - &cfv->rx_hr); > - virtio_cread(vdev, struct virtio_caif_transf_config, tailroom, > - &cfv->tx_tr); > - virtio_cread(vdev, struct virtio_caif_transf_config, tailroom, > - &cfv->rx_tr); > - virtio_cread(vdev, struct virtio_caif_transf_config, mtu, > - &cfv->mtu); > - virtio_cread(vdev, struct virtio_caif_transf_config, mtu, > - &cfv->mru); > - } else { > - cfv->tx_hr = CFV_DEF_HEADROOM; > - cfv->rx_hr = CFV_DEF_HEADROOM; > - cfv->tx_tr = CFV_DEF_TAILROOM; > - cfv->rx_tr = CFV_DEF_TAILROOM; > - cfv->mtu = CFV_DEF_MTU_SIZE; > - cfv->mru = CFV_DEF_MTU_SIZE; > - } > - > - netdev->needed_headroom = cfv->tx_hr; > - netdev->needed_tailroom = cfv->tx_tr; > - > - /* Disable buffer release interrupts unless we have stopped TX queues */ > - virtqueue_disable_cb(cfv->vq_tx); > - > - netdev->mtu = cfv->mtu - cfv->tx_tr; > - vdev->priv = cfv; > - > - /* Initialize NAPI poll context data */ > - vringh_kiov_init(&cfv->ctx.riov, NULL, 0); > - cfv->ctx.head = USHRT_MAX; > - netif_napi_add_weight(netdev, &cfv->napi, cfv_rx_poll, > - CFV_DEFAULT_QUOTA); > - > - tasklet_setup(&cfv->tx_release_tasklet, cfv_tx_release_tasklet); > - > - /* Carrier is off until netdevice is opened */ > - netif_carrier_off(netdev); > - > - /* serialize netdev register + virtio_device_ready() with ndo_open() */ > - rtnl_lock(); > - > - /* register Netdev */ > - err = register_netdevice(netdev); > - if (err) { > - rtnl_unlock(); > - dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err); > - goto err; > - } > - > - virtio_device_ready(vdev); > - > - rtnl_unlock(); > - > - debugfs_init(cfv); > - > - return 0; > -err: > - netdev_warn(cfv->ndev, "CAIF Virtio probe failed:%d\n", err); > - > - if (cfv->vr_rx) > - vdev->vringh_config->del_vrhs(cfv->vdev); > - if (cfv->vq_tx) > - vdev->config->del_vqs(cfv->vdev); > - free_netdev(netdev); > - return err; > -} > - > -static void cfv_remove(struct virtio_device *vdev) > -{ > - struct cfv_info *cfv = vdev->priv; > - > - rtnl_lock(); > - dev_close(cfv->ndev); > - rtnl_unlock(); > - > - tasklet_kill(&cfv->tx_release_tasklet); > - debugfs_remove_recursive(cfv->debugfs); > - > - vringh_kiov_cleanup(&cfv->ctx.riov); > - virtio_reset_device(vdev); > - vdev->vringh_config->del_vrhs(cfv->vdev); > - cfv->vr_rx = NULL; > - vdev->config->del_vqs(cfv->vdev); > - unregister_netdev(cfv->ndev); > -} > - > -static struct virtio_device_id id_table[] = { > - { VIRTIO_ID_CAIF, VIRTIO_DEV_ANY_ID }, > - { 0 }, > -}; > - > -static unsigned int features[] = { > -}; > - > -static struct virtio_driver caif_virtio_driver = { > - .feature_table = features, > - .feature_table_size = ARRAY_SIZE(features), > - .driver.name = KBUILD_MODNAME, > - .id_table = id_table, > - .probe = cfv_probe, > - .remove = cfv_remove, > -}; > - > -module_virtio_driver(caif_virtio_driver); > -MODULE_DEVICE_TABLE(virtio, id_table); > diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c > deleted file mode 100644 > index 922de3d611c0..000000000000 > --- a/net/caif/caif_dev.c > +++ /dev/null > @@ -1,586 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * CAIF Interface registration. > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - * > - * Borrowed heavily from file: pn_dev.c. Thanks to Remi Denis-Courmont > - * and Sakari Ailus > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -MODULE_DESCRIPTION("ST-Ericsson CAIF modem protocol support"); > -MODULE_LICENSE("GPL"); > - > -/* Used for local tracking of the CAIF net devices */ > -struct caif_device_entry { > - struct cflayer layer; > - struct list_head list; > - struct net_device *netdev; > - int __percpu *pcpu_refcnt; > - spinlock_t flow_lock; > - struct sk_buff *xoff_skb; > - void (*xoff_skb_dtor)(struct sk_buff *skb); > - bool xoff; > -}; > - > -struct caif_device_entry_list { > - struct list_head list; > - /* Protects simulanous deletes in list */ > - struct mutex lock; > -}; > - > -struct caif_net { > - struct cfcnfg *cfg; > - struct caif_device_entry_list caifdevs; > -}; > - > -static unsigned int caif_net_id; > -static int q_high = 50; /* Percent */ > - > -struct cfcnfg *get_cfcnfg(struct net *net) > -{ > - struct caif_net *caifn; > - caifn = net_generic(net, caif_net_id); > - return caifn->cfg; > -} > -EXPORT_SYMBOL(get_cfcnfg); > - > -static struct caif_device_entry_list *caif_device_list(struct net *net) > -{ > - struct caif_net *caifn; > - caifn = net_generic(net, caif_net_id); > - return &caifn->caifdevs; > -} > - > -static void caifd_put(struct caif_device_entry *e) > -{ > - this_cpu_dec(*e->pcpu_refcnt); > -} > - > -static void caifd_hold(struct caif_device_entry *e) > -{ > - this_cpu_inc(*e->pcpu_refcnt); > -} > - > -static int caifd_refcnt_read(struct caif_device_entry *e) > -{ > - int i, refcnt = 0; > - for_each_possible_cpu(i) > - refcnt += *per_cpu_ptr(e->pcpu_refcnt, i); > - return refcnt; > -} > - > -/* Allocate new CAIF device. */ > -static struct caif_device_entry *caif_device_alloc(struct net_device *dev) > -{ > - struct caif_device_entry *caifd; > - > - caifd = kzalloc_obj(*caifd); > - if (!caifd) > - return NULL; > - caifd->pcpu_refcnt = alloc_percpu(int); > - if (!caifd->pcpu_refcnt) { > - kfree(caifd); > - return NULL; > - } > - caifd->netdev = dev; > - dev_hold(dev); > - return caifd; > -} > - > -static struct caif_device_entry *caif_get(struct net_device *dev) > -{ > - struct caif_device_entry_list *caifdevs = > - caif_device_list(dev_net(dev)); > - struct caif_device_entry *caifd; > - > - list_for_each_entry_rcu(caifd, &caifdevs->list, list, > - lockdep_rtnl_is_held()) { > - if (caifd->netdev == dev) > - return caifd; > - } > - return NULL; > -} > - > -static void caif_flow_cb(struct sk_buff *skb) > -{ > - struct caif_device_entry *caifd; > - void (*dtor)(struct sk_buff *skb) = NULL; > - bool send_xoff; > - > - WARN_ON(skb->dev == NULL); > - > - rcu_read_lock(); > - caifd = caif_get(skb->dev); > - > - WARN_ON(caifd == NULL); > - if (!caifd) { > - rcu_read_unlock(); > - return; > - } > - > - caifd_hold(caifd); > - rcu_read_unlock(); > - > - spin_lock_bh(&caifd->flow_lock); > - send_xoff = caifd->xoff; > - caifd->xoff = false; > - dtor = caifd->xoff_skb_dtor; > - > - if (WARN_ON(caifd->xoff_skb != skb)) > - skb = NULL; > - > - caifd->xoff_skb = NULL; > - caifd->xoff_skb_dtor = NULL; > - > - spin_unlock_bh(&caifd->flow_lock); > - > - if (dtor && skb) > - dtor(skb); > - > - if (send_xoff) > - caifd->layer.up-> > - ctrlcmd(caifd->layer.up, > - _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND, > - caifd->layer.id); > - caifd_put(caifd); > -} > - > -static int transmit(struct cflayer *layer, struct cfpkt *pkt) > -{ > - int err, high = 0, qlen = 0; > - struct caif_device_entry *caifd = > - container_of(layer, struct caif_device_entry, layer); > - struct sk_buff *skb; > - struct netdev_queue *txq; > - > - rcu_read_lock_bh(); > - > - skb = cfpkt_tonative(pkt); > - skb->dev = caifd->netdev; > - skb_reset_network_header(skb); > - skb->protocol = htons(ETH_P_CAIF); > - > - /* Check if we need to handle xoff */ > - if (likely(caifd->netdev->priv_flags & IFF_NO_QUEUE)) > - goto noxoff; > - > - if (unlikely(caifd->xoff)) > - goto noxoff; > - > - if (likely(!netif_queue_stopped(caifd->netdev))) { > - struct Qdisc *sch; > - > - /* If we run with a TX queue, check if the queue is too long*/ > - txq = netdev_get_tx_queue(skb->dev, 0); > - sch = rcu_dereference_bh(txq->qdisc); > - if (likely(qdisc_is_empty(sch))) > - goto noxoff; > - > - /* can check for explicit qdisc len value only !NOLOCK, > - * always set flow off otherwise > - */ > - high = (caifd->netdev->tx_queue_len * q_high) / 100; > - if (!(sch->flags & TCQ_F_NOLOCK) && likely(sch->q.qlen < high)) > - goto noxoff; > - } > - > - /* Hold lock while accessing xoff */ > - spin_lock_bh(&caifd->flow_lock); > - if (caifd->xoff) { > - spin_unlock_bh(&caifd->flow_lock); > - goto noxoff; > - } > - > - /* > - * Handle flow off, we do this by temporary hi-jacking this > - * skb's destructor function, and replace it with our own > - * flow-on callback. The callback will set flow-on and call > - * the original destructor. > - */ > - > - pr_debug("queue has stopped(%d) or is full (%d > %d)\n", > - netif_queue_stopped(caifd->netdev), > - qlen, high); > - caifd->xoff = true; > - caifd->xoff_skb = skb; > - caifd->xoff_skb_dtor = skb->destructor; > - skb->destructor = caif_flow_cb; > - spin_unlock_bh(&caifd->flow_lock); > - > - caifd->layer.up->ctrlcmd(caifd->layer.up, > - _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, > - caifd->layer.id); > -noxoff: > - rcu_read_unlock_bh(); > - > - err = dev_queue_xmit(skb); > - if (err > 0) > - err = -EIO; > - > - return err; > -} > - > -/* > - * Stuff received packets into the CAIF stack. > - * On error, returns non-zero and releases the skb. > - */ > -static int receive(struct sk_buff *skb, struct net_device *dev, > - struct packet_type *pkttype, struct net_device *orig_dev) > -{ > - struct cfpkt *pkt; > - struct caif_device_entry *caifd; > - int err; > - > - pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); > - > - rcu_read_lock(); > - caifd = caif_get(dev); > - > - if (!caifd || !caifd->layer.up || !caifd->layer.up->receive || > - !netif_oper_up(caifd->netdev)) { > - rcu_read_unlock(); > - kfree_skb(skb); > - return NET_RX_DROP; > - } > - > - /* Hold reference to netdevice while using CAIF stack */ > - caifd_hold(caifd); > - rcu_read_unlock(); > - > - err = caifd->layer.up->receive(caifd->layer.up, pkt); > - > - /* For -EILSEQ the packet is not freed so free it now */ > - if (err == -EILSEQ) > - cfpkt_destroy(pkt); > - > - /* Release reference to stack upwards */ > - caifd_put(caifd); > - > - if (err != 0) > - err = NET_RX_DROP; > - return err; > -} > - > -static struct packet_type caif_packet_type __read_mostly = { > - .type = cpu_to_be16(ETH_P_CAIF), > - .func = receive, > -}; > - > -static void dev_flowctrl(struct net_device *dev, int on) > -{ > - struct caif_device_entry *caifd; > - > - rcu_read_lock(); > - > - caifd = caif_get(dev); > - if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { > - rcu_read_unlock(); > - return; > - } > - > - caifd_hold(caifd); > - rcu_read_unlock(); > - > - caifd->layer.up->ctrlcmd(caifd->layer.up, > - on ? > - _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND : > - _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, > - caifd->layer.id); > - caifd_put(caifd); > -} > - > -int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, > - struct cflayer *link_support, int head_room, > - struct cflayer **layer, > - int (**rcv_func)(struct sk_buff *, struct net_device *, > - struct packet_type *, > - struct net_device *)) > -{ > - struct caif_device_entry *caifd; > - enum cfcnfg_phy_preference pref; > - struct cfcnfg *cfg = get_cfcnfg(dev_net(dev)); > - struct caif_device_entry_list *caifdevs; > - int res; > - > - caifdevs = caif_device_list(dev_net(dev)); > - caifd = caif_device_alloc(dev); > - if (!caifd) > - return -ENOMEM; > - *layer = &caifd->layer; > - spin_lock_init(&caifd->flow_lock); > - > - switch (caifdev->link_select) { > - case CAIF_LINK_HIGH_BANDW: > - pref = CFPHYPREF_HIGH_BW; > - break; > - case CAIF_LINK_LOW_LATENCY: > - pref = CFPHYPREF_LOW_LAT; > - break; > - default: > - pref = CFPHYPREF_HIGH_BW; > - break; > - } > - mutex_lock(&caifdevs->lock); > - list_add_rcu(&caifd->list, &caifdevs->list); > - > - strscpy(caifd->layer.name, dev->name, > - sizeof(caifd->layer.name)); > - caifd->layer.transmit = transmit; > - res = cfcnfg_add_phy_layer(cfg, > - dev, > - &caifd->layer, > - pref, > - link_support, > - caifdev->use_fcs, > - head_room); > - mutex_unlock(&caifdevs->lock); > - if (rcv_func) > - *rcv_func = receive; > - return res; > -} > -EXPORT_SYMBOL(caif_enroll_dev); > - > -/* notify Caif of device events */ > -static int caif_device_notify(struct notifier_block *me, unsigned long what, > - void *ptr) > -{ > - struct net_device *dev = netdev_notifier_info_to_dev(ptr); > - struct caif_device_entry *caifd = NULL; > - struct caif_dev_common *caifdev; > - struct cfcnfg *cfg; > - struct cflayer *layer, *link_support; > - int head_room = 0; > - struct caif_device_entry_list *caifdevs; > - int res; > - > - cfg = get_cfcnfg(dev_net(dev)); > - caifdevs = caif_device_list(dev_net(dev)); > - > - caifd = caif_get(dev); > - if (caifd == NULL && dev->type != ARPHRD_CAIF) > - return 0; > - > - switch (what) { > - case NETDEV_REGISTER: > - if (caifd != NULL) > - break; > - > - caifdev = netdev_priv(dev); > - > - link_support = NULL; > - if (caifdev->use_frag) { > - head_room = 1; > - link_support = cfserl_create(dev->ifindex, > - caifdev->use_stx); > - if (!link_support) { > - pr_warn("Out of memory\n"); > - break; > - } > - } > - res = caif_enroll_dev(dev, caifdev, link_support, head_room, > - &layer, NULL); > - if (res) > - cfserl_release(link_support); > - caifdev->flowctrl = dev_flowctrl; > - break; > - > - case NETDEV_UP: > - rcu_read_lock(); > - > - caifd = caif_get(dev); > - if (caifd == NULL) { > - rcu_read_unlock(); > - break; > - } > - > - caifd->xoff = false; > - cfcnfg_set_phy_state(cfg, &caifd->layer, true); > - rcu_read_unlock(); > - > - break; > - > - case NETDEV_DOWN: > - rcu_read_lock(); > - > - caifd = caif_get(dev); > - if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { > - rcu_read_unlock(); > - return -EINVAL; > - } > - > - cfcnfg_set_phy_state(cfg, &caifd->layer, false); > - caifd_hold(caifd); > - rcu_read_unlock(); > - > - caifd->layer.up->ctrlcmd(caifd->layer.up, > - _CAIF_CTRLCMD_PHYIF_DOWN_IND, > - caifd->layer.id); > - > - spin_lock_bh(&caifd->flow_lock); > - > - /* > - * Replace our xoff-destructor with original destructor. > - * We trust that skb->destructor *always* is called before > - * the skb reference is invalid. The hijacked SKB destructor > - * takes the flow_lock so manipulating the skb->destructor here > - * should be safe. > - */ > - if (caifd->xoff_skb_dtor != NULL && caifd->xoff_skb != NULL) > - caifd->xoff_skb->destructor = caifd->xoff_skb_dtor; > - > - caifd->xoff = false; > - caifd->xoff_skb_dtor = NULL; > - caifd->xoff_skb = NULL; > - > - spin_unlock_bh(&caifd->flow_lock); > - caifd_put(caifd); > - break; > - > - case NETDEV_UNREGISTER: > - mutex_lock(&caifdevs->lock); > - > - caifd = caif_get(dev); > - if (caifd == NULL) { > - mutex_unlock(&caifdevs->lock); > - break; > - } > - list_del_rcu(&caifd->list); > - > - /* > - * NETDEV_UNREGISTER is called repeatedly until all reference > - * counts for the net-device are released. If references to > - * caifd is taken, simply ignore NETDEV_UNREGISTER and wait for > - * the next call to NETDEV_UNREGISTER. > - * > - * If any packets are in flight down the CAIF Stack, > - * cfcnfg_del_phy_layer will return nonzero. > - * If no packets are in flight, the CAIF Stack associated > - * with the net-device un-registering is freed. > - */ > - > - if (caifd_refcnt_read(caifd) != 0 || > - cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0) { > - > - pr_info("Wait for device inuse\n"); > - /* Enrole device if CAIF Stack is still in use */ > - list_add_rcu(&caifd->list, &caifdevs->list); > - mutex_unlock(&caifdevs->lock); > - break; > - } > - > - synchronize_rcu(); > - dev_put(caifd->netdev); > - free_percpu(caifd->pcpu_refcnt); > - kfree(caifd); > - > - mutex_unlock(&caifdevs->lock); > - break; > - } > - return 0; > -} > - > -static struct notifier_block caif_device_notifier = { > - .notifier_call = caif_device_notify, > - .priority = 0, > -}; > - > -/* Per-namespace Caif devices handling */ > -static int caif_init_net(struct net *net) > -{ > - struct caif_net *caifn = net_generic(net, caif_net_id); > - INIT_LIST_HEAD(&caifn->caifdevs.list); > - mutex_init(&caifn->caifdevs.lock); > - > - caifn->cfg = cfcnfg_create(); > - if (!caifn->cfg) > - return -ENOMEM; > - > - return 0; > -} > - > -static void caif_exit_net(struct net *net) > -{ > - struct caif_device_entry *caifd, *tmp; > - struct caif_device_entry_list *caifdevs = > - caif_device_list(net); > - struct cfcnfg *cfg = get_cfcnfg(net); > - > - rtnl_lock(); > - mutex_lock(&caifdevs->lock); > - > - list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { > - int i = 0; > - list_del_rcu(&caifd->list); > - cfcnfg_set_phy_state(cfg, &caifd->layer, false); > - > - while (i < 10 && > - (caifd_refcnt_read(caifd) != 0 || > - cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0)) { > - > - pr_info("Wait for device inuse\n"); > - msleep(250); > - i++; > - } > - synchronize_rcu(); > - dev_put(caifd->netdev); > - free_percpu(caifd->pcpu_refcnt); > - kfree(caifd); > - } > - cfcnfg_remove(cfg); > - > - mutex_unlock(&caifdevs->lock); > - rtnl_unlock(); > -} > - > -static struct pernet_operations caif_net_ops = { > - .init = caif_init_net, > - .exit = caif_exit_net, > - .id = &caif_net_id, > - .size = sizeof(struct caif_net), > -}; > - > -/* Initialize Caif devices list */ > -static int __init caif_device_init(void) > -{ > - int result; > - > - result = register_pernet_subsys(&caif_net_ops); > - > - if (result) > - return result; > - > - register_netdevice_notifier(&caif_device_notifier); > - dev_add_pack(&caif_packet_type); > - > - return result; > -} > - > -static void __exit caif_device_exit(void) > -{ > - unregister_netdevice_notifier(&caif_device_notifier); > - dev_remove_pack(&caif_packet_type); > - unregister_pernet_subsys(&caif_net_ops); > -} > - > -module_init(caif_device_init); > -module_exit(caif_device_exit); > diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c > deleted file mode 100644 > index af218742af5a..000000000000 > --- a/net/caif/caif_socket.c > +++ /dev/null > @@ -1,1114 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -MODULE_DESCRIPTION("ST-Ericsson CAIF modem protocol socket support (AF_CAIF)"); > -MODULE_LICENSE("GPL"); > -MODULE_ALIAS_NETPROTO(AF_CAIF); > - > -/* > - * CAIF state is re-using the TCP socket states. > - * caif_states stored in sk_state reflect the state as reported by > - * the CAIF stack, while sk_socket->state is the state of the socket. > - */ > -enum caif_states { > - CAIF_CONNECTED = TCP_ESTABLISHED, > - CAIF_CONNECTING = TCP_SYN_SENT, > - CAIF_DISCONNECTED = TCP_CLOSE > -}; > - > -#define TX_FLOW_ON_BIT 1 > -#define RX_FLOW_ON_BIT 2 > - > -struct caifsock { > - struct sock sk; /* must be first member */ > - struct cflayer layer; > - unsigned long flow_state; > - struct caif_connect_request conn_req; > - struct mutex readlock; > - struct dentry *debugfs_socket_dir; > - int headroom, tailroom, maxframe; > -}; > - > -static int rx_flow_is_on(struct caifsock *cf_sk) > -{ > - return test_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static int tx_flow_is_on(struct caifsock *cf_sk) > -{ > - return test_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static void set_rx_flow_off(struct caifsock *cf_sk) > -{ > - clear_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static void set_rx_flow_on(struct caifsock *cf_sk) > -{ > - set_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static void set_tx_flow_off(struct caifsock *cf_sk) > -{ > - clear_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static void set_tx_flow_on(struct caifsock *cf_sk) > -{ > - set_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state); > -} > - > -static void caif_read_lock(struct sock *sk) > -{ > - struct caifsock *cf_sk; > - cf_sk = container_of(sk, struct caifsock, sk); > - mutex_lock(&cf_sk->readlock); > -} > - > -static void caif_read_unlock(struct sock *sk) > -{ > - struct caifsock *cf_sk; > - cf_sk = container_of(sk, struct caifsock, sk); > - mutex_unlock(&cf_sk->readlock); > -} > - > -static int sk_rcvbuf_lowwater(struct caifsock *cf_sk) > -{ > - /* A quarter of full buffer is used a low water mark */ > - return cf_sk->sk.sk_rcvbuf / 4; > -} > - > -static void caif_flow_ctrl(struct sock *sk, int mode) > -{ > - struct caifsock *cf_sk; > - cf_sk = container_of(sk, struct caifsock, sk); > - if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd) > - cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode); > -} > - > -/* > - * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are > - * not dropped, but CAIF is sending flow off instead. > - */ > -static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) > -{ > - int err; > - unsigned long flags; > - struct sk_buff_head *list = &sk->sk_receive_queue; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - bool queued = false; > - > - if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= > - (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { > - net_dbg_ratelimited("sending flow OFF (queue len = %d %d)\n", > - atomic_read(&cf_sk->sk.sk_rmem_alloc), > - sk_rcvbuf_lowwater(cf_sk)); > - set_rx_flow_off(cf_sk); > - caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); > - } > - > - err = sk_filter(sk, skb); > - if (err) > - goto out; > - > - if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { > - set_rx_flow_off(cf_sk); > - net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); > - caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); > - } > - skb->dev = NULL; > - skb_set_owner_r(skb, sk); > - spin_lock_irqsave(&list->lock, flags); > - queued = !sock_flag(sk, SOCK_DEAD); > - if (queued) > - __skb_queue_tail(list, skb); > - spin_unlock_irqrestore(&list->lock, flags); > -out: > - if (queued) > - sk->sk_data_ready(sk); > - else > - kfree_skb(skb); > -} > - > -/* Packet Receive Callback function called from CAIF Stack */ > -static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct caifsock *cf_sk; > - struct sk_buff *skb; > - > - cf_sk = container_of(layr, struct caifsock, layer); > - skb = cfpkt_tonative(pkt); > - > - if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { > - kfree_skb(skb); > - return 0; > - } > - caif_queue_rcv_skb(&cf_sk->sk, skb); > - return 0; > -} > - > -static void cfsk_hold(struct cflayer *layr) > -{ > - struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); > - sock_hold(&cf_sk->sk); > -} > - > -static void cfsk_put(struct cflayer *layr) > -{ > - struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); > - sock_put(&cf_sk->sk); > -} > - > -/* Packet Control Callback function called from CAIF */ > -static void caif_ctrl_cb(struct cflayer *layr, > - enum caif_ctrlcmd flow, > - int phyid) > -{ > - struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); > - switch (flow) { > - case CAIF_CTRLCMD_FLOW_ON_IND: > - /* OK from modem to start sending again */ > - set_tx_flow_on(cf_sk); > - cf_sk->sk.sk_state_change(&cf_sk->sk); > - break; > - > - case CAIF_CTRLCMD_FLOW_OFF_IND: > - /* Modem asks us to shut up */ > - set_tx_flow_off(cf_sk); > - cf_sk->sk.sk_state_change(&cf_sk->sk); > - break; > - > - case CAIF_CTRLCMD_INIT_RSP: > - /* We're now connected */ > - caif_client_register_refcnt(&cf_sk->layer, > - cfsk_hold, cfsk_put); > - cf_sk->sk.sk_state = CAIF_CONNECTED; > - set_tx_flow_on(cf_sk); > - cf_sk->sk.sk_shutdown = 0; > - cf_sk->sk.sk_state_change(&cf_sk->sk); > - break; > - > - case CAIF_CTRLCMD_DEINIT_RSP: > - /* We're now disconnected */ > - cf_sk->sk.sk_state = CAIF_DISCONNECTED; > - cf_sk->sk.sk_state_change(&cf_sk->sk); > - break; > - > - case CAIF_CTRLCMD_INIT_FAIL_RSP: > - /* Connect request failed */ > - cf_sk->sk.sk_err = ECONNREFUSED; > - cf_sk->sk.sk_state = CAIF_DISCONNECTED; > - cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; > - /* > - * Socket "standards" seems to require POLLOUT to > - * be set at connect failure. > - */ > - set_tx_flow_on(cf_sk); > - cf_sk->sk.sk_state_change(&cf_sk->sk); > - break; > - > - case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: > - /* Modem has closed this connection, or device is down. */ > - cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; > - cf_sk->sk.sk_err = ECONNRESET; > - set_rx_flow_on(cf_sk); > - sk_error_report(&cf_sk->sk); > - break; > - > - default: > - pr_debug("Unexpected flow command %d\n", flow); > - } > -} > - > -static void caif_check_flow_release(struct sock *sk) > -{ > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - > - if (rx_flow_is_on(cf_sk)) > - return; > - > - if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) { > - set_rx_flow_on(cf_sk); > - caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ); > - } > -} > - > -/* > - * Copied from unix_dgram_recvmsg, but removed credit checks, > - * changed locking, address handling and added MSG_TRUNC. > - */ > -static int caif_seqpkt_recvmsg(struct socket *sock, struct msghdr *m, > - size_t len, int flags) > - > -{ > - struct sock *sk = sock->sk; > - struct sk_buff *skb; > - int ret; > - int copylen; > - > - ret = -EOPNOTSUPP; > - if (flags & MSG_OOB) > - goto read_error; > - > - skb = skb_recv_datagram(sk, flags, &ret); > - if (!skb) > - goto read_error; > - copylen = skb->len; > - if (len < copylen) { > - m->msg_flags |= MSG_TRUNC; > - copylen = len; > - } > - > - ret = skb_copy_datagram_msg(skb, 0, m, copylen); > - if (ret) > - goto out_free; > - > - ret = (flags & MSG_TRUNC) ? skb->len : copylen; > -out_free: > - skb_free_datagram(sk, skb); > - caif_check_flow_release(sk); > - return ret; > - > -read_error: > - return ret; > -} > - > - > -/* Copied from unix_stream_wait_data, identical except for lock call. */ > -static long caif_stream_data_wait(struct sock *sk, long timeo) > -{ > - DEFINE_WAIT(wait); > - lock_sock(sk); > - > - for (;;) { > - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); > - > - if (!skb_queue_empty(&sk->sk_receive_queue) || > - sk->sk_err || > - sk->sk_state != CAIF_CONNECTED || > - sock_flag(sk, SOCK_DEAD) || > - (sk->sk_shutdown & RCV_SHUTDOWN) || > - signal_pending(current) || > - !timeo) > - break; > - > - sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); > - release_sock(sk); > - timeo = schedule_timeout(timeo); > - lock_sock(sk); > - > - if (sock_flag(sk, SOCK_DEAD)) > - break; > - > - sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); > - } > - > - finish_wait(sk_sleep(sk), &wait); > - release_sock(sk); > - return timeo; > -} > - > - > -/* > - * Copied from unix_stream_recvmsg, but removed credit checks, > - * changed locking calls, changed address handling. > - */ > -static int caif_stream_recvmsg(struct socket *sock, struct msghdr *msg, > - size_t size, int flags) > -{ > - struct sock *sk = sock->sk; > - int copied = 0; > - int target; > - int err = 0; > - long timeo; > - > - err = -EOPNOTSUPP; > - if (flags&MSG_OOB) > - goto out; > - > - /* > - * Lock the socket to prevent queue disordering > - * while sleeps in memcpy_tomsg > - */ > - err = -EAGAIN; > - if (sk->sk_state == CAIF_CONNECTING) > - goto out; > - > - caif_read_lock(sk); > - target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); > - timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); > - > - do { > - int chunk; > - struct sk_buff *skb; > - > - lock_sock(sk); > - if (sock_flag(sk, SOCK_DEAD)) { > - err = -ECONNRESET; > - goto unlock; > - } > - skb = skb_dequeue(&sk->sk_receive_queue); > - caif_check_flow_release(sk); > - > - if (skb == NULL) { > - if (copied >= target) > - goto unlock; > - /* > - * POSIX 1003.1g mandates this order. > - */ > - err = sock_error(sk); > - if (err) > - goto unlock; > - err = -ECONNRESET; > - if (sk->sk_shutdown & RCV_SHUTDOWN) > - goto unlock; > - > - err = -EPIPE; > - if (sk->sk_state != CAIF_CONNECTED) > - goto unlock; > - if (sock_flag(sk, SOCK_DEAD)) > - goto unlock; > - > - release_sock(sk); > - > - err = -EAGAIN; > - if (!timeo) > - break; > - > - caif_read_unlock(sk); > - > - timeo = caif_stream_data_wait(sk, timeo); > - > - if (signal_pending(current)) { > - err = sock_intr_errno(timeo); > - goto out; > - } > - caif_read_lock(sk); > - continue; > -unlock: > - release_sock(sk); > - break; > - } > - release_sock(sk); > - chunk = min_t(unsigned int, skb->len, size); > - if (memcpy_to_msg(msg, skb->data, chunk)) { > - skb_queue_head(&sk->sk_receive_queue, skb); > - if (copied == 0) > - copied = -EFAULT; > - break; > - } > - copied += chunk; > - size -= chunk; > - > - /* Mark read part of skb as used */ > - if (!(flags & MSG_PEEK)) { > - skb_pull(skb, chunk); > - > - /* put the skb back if we didn't use it up. */ > - if (skb->len) { > - skb_queue_head(&sk->sk_receive_queue, skb); > - break; > - } > - kfree_skb(skb); > - > - } else { > - /* > - * It is questionable, see note in unix_dgram_recvmsg. > - */ > - /* put message back and return */ > - skb_queue_head(&sk->sk_receive_queue, skb); > - break; > - } > - } while (size); > - caif_read_unlock(sk); > - > -out: > - return copied ? : err; > -} > - > -/* > - * Copied from sock.c:sock_wait_for_wmem, but change to wait for > - * CAIF flow-on and sock_writable. > - */ > -static long caif_wait_for_flow_on(struct caifsock *cf_sk, > - int wait_writeable, long timeo, int *err) > -{ > - struct sock *sk = &cf_sk->sk; > - DEFINE_WAIT(wait); > - for (;;) { > - *err = 0; > - if (tx_flow_is_on(cf_sk) && > - (!wait_writeable || sock_writeable(&cf_sk->sk))) > - break; > - *err = -ETIMEDOUT; > - if (!timeo) > - break; > - *err = -ERESTARTSYS; > - if (signal_pending(current)) > - break; > - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); > - *err = -ECONNRESET; > - if (sk->sk_shutdown & SHUTDOWN_MASK) > - break; > - *err = -sk->sk_err; > - if (sk->sk_err) > - break; > - *err = -EPIPE; > - if (cf_sk->sk.sk_state != CAIF_CONNECTED) > - break; > - timeo = schedule_timeout(timeo); > - } > - finish_wait(sk_sleep(sk), &wait); > - return timeo; > -} > - > -/* > - * Transmit a SKB. The device may temporarily request re-transmission > - * by returning EAGAIN. > - */ > -static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, > - int noblock, long timeo) > -{ > - struct cfpkt *pkt; > - > - pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); > - memset(skb->cb, 0, sizeof(struct caif_payload_info)); > - cfpkt_set_prio(pkt, cf_sk->sk.sk_priority); > - > - if (cf_sk->layer.dn == NULL) { > - kfree_skb(skb); > - return -EINVAL; > - } > - > - return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); > -} > - > -/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ > -static int caif_seqpkt_sendmsg(struct socket *sock, struct msghdr *msg, > - size_t len) > -{ > - struct sock *sk = sock->sk; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - int buffer_size; > - int ret = 0; > - struct sk_buff *skb = NULL; > - int noblock; > - long timeo; > - caif_assert(cf_sk); > - ret = sock_error(sk); > - if (ret) > - goto err; > - > - ret = -EOPNOTSUPP; > - if (msg->msg_flags&MSG_OOB) > - goto err; > - > - ret = -EOPNOTSUPP; > - if (msg->msg_namelen) > - goto err; > - > - noblock = msg->msg_flags & MSG_DONTWAIT; > - > - timeo = sock_sndtimeo(sk, noblock); > - timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), > - 1, timeo, &ret); > - > - if (ret) > - goto err; > - ret = -EPIPE; > - if (cf_sk->sk.sk_state != CAIF_CONNECTED || > - sock_flag(sk, SOCK_DEAD) || > - (sk->sk_shutdown & RCV_SHUTDOWN)) > - goto err; > - > - /* Error if trying to write more than maximum frame size. */ > - ret = -EMSGSIZE; > - if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM) > - goto err; > - > - buffer_size = len + cf_sk->headroom + cf_sk->tailroom; > - > - ret = -ENOMEM; > - skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); > - > - if (!skb || skb_tailroom(skb) < buffer_size) > - goto err; > - > - skb_reserve(skb, cf_sk->headroom); > - > - ret = memcpy_from_msg(skb_put(skb, len), msg, len); > - > - if (ret) > - goto err; > - ret = transmit_skb(skb, cf_sk, noblock, timeo); > - if (ret < 0) > - /* skb is already freed */ > - return ret; > - > - return len; > -err: > - kfree_skb(skb); > - return ret; > -} > - > -/* > - * Copied from unix_stream_sendmsg and adapted to CAIF: > - * Changed removed permission handling and added waiting for flow on > - * and other minor adaptations. > - */ > -static int caif_stream_sendmsg(struct socket *sock, struct msghdr *msg, > - size_t len) > -{ > - struct sock *sk = sock->sk; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - int err, size; > - struct sk_buff *skb; > - int sent = 0; > - long timeo; > - > - err = -EOPNOTSUPP; > - if (unlikely(msg->msg_flags&MSG_OOB)) > - goto out_err; > - > - if (unlikely(msg->msg_namelen)) > - goto out_err; > - > - timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); > - timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err); > - > - if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) > - goto pipe_err; > - > - while (sent < len) { > - > - size = len-sent; > - > - if (size > cf_sk->maxframe) > - size = cf_sk->maxframe; > - > - /* If size is more than half of sndbuf, chop up message */ > - if (size > ((sk->sk_sndbuf >> 1) - 64)) > - size = (sk->sk_sndbuf >> 1) - 64; > - > - if (size > SKB_MAX_ALLOC) > - size = SKB_MAX_ALLOC; > - > - skb = sock_alloc_send_skb(sk, > - size + cf_sk->headroom + > - cf_sk->tailroom, > - msg->msg_flags&MSG_DONTWAIT, > - &err); > - if (skb == NULL) > - goto out_err; > - > - skb_reserve(skb, cf_sk->headroom); > - /* > - * If you pass two values to the sock_alloc_send_skb > - * it tries to grab the large buffer with GFP_NOFS > - * (which can fail easily), and if it fails grab the > - * fallback size buffer which is under a page and will > - * succeed. [Alan] > - */ > - size = min_t(int, size, skb_tailroom(skb)); > - > - err = memcpy_from_msg(skb_put(skb, size), msg, size); > - if (err) { > - kfree_skb(skb); > - goto out_err; > - } > - err = transmit_skb(skb, cf_sk, > - msg->msg_flags&MSG_DONTWAIT, timeo); > - if (err < 0) > - /* skb is already freed */ > - goto pipe_err; > - > - sent += size; > - } > - > - return sent; > - > -pipe_err: > - if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) > - send_sig(SIGPIPE, current, 0); > - err = -EPIPE; > -out_err: > - return sent ? : err; > -} > - > -static int setsockopt(struct socket *sock, int lvl, int opt, sockptr_t ov, > - unsigned int ol) > -{ > - struct sock *sk = sock->sk; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - int linksel; > - > - if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) > - return -ENOPROTOOPT; > - > - switch (opt) { > - case CAIFSO_LINK_SELECT: > - if (ol < sizeof(int)) > - return -EINVAL; > - if (lvl != SOL_CAIF) > - goto bad_sol; > - if (copy_from_sockptr(&linksel, ov, sizeof(int))) > - return -EINVAL; > - lock_sock(&(cf_sk->sk)); > - cf_sk->conn_req.link_selector = linksel; > - release_sock(&cf_sk->sk); > - return 0; > - > - case CAIFSO_REQ_PARAM: > - if (lvl != SOL_CAIF) > - goto bad_sol; > - if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) > - return -ENOPROTOOPT; > - lock_sock(&(cf_sk->sk)); > - if (ol > sizeof(cf_sk->conn_req.param.data) || > - copy_from_sockptr(&cf_sk->conn_req.param.data, ov, ol)) { > - release_sock(&cf_sk->sk); > - return -EINVAL; > - } > - cf_sk->conn_req.param.size = ol; > - release_sock(&cf_sk->sk); > - return 0; > - > - default: > - return -ENOPROTOOPT; > - } > - > - return 0; > -bad_sol: > - return -ENOPROTOOPT; > - > -} > - > -/* > - * caif_connect() - Connect a CAIF Socket > - * Copied and modified af_irda.c:irda_connect(). > - * > - * Note : by consulting "errno", the user space caller may learn the cause > - * of the failure. Most of them are visible in the function, others may come > - * from subroutines called and are listed here : > - * o -EAFNOSUPPORT: bad socket family or type. > - * o -ESOCKTNOSUPPORT: bad socket type or protocol > - * o -EINVAL: bad socket address, or CAIF link type > - * o -ECONNREFUSED: remote end refused the connection. > - * o -EINPROGRESS: connect request sent but timed out (or non-blocking) > - * o -EISCONN: already connected. > - * o -ETIMEDOUT: Connection timed out (send timeout) > - * o -ENODEV: No link layer to send request > - * o -ECONNRESET: Received Shutdown indication or lost link layer > - * o -ENOMEM: Out of memory > - * > - * State Strategy: > - * o sk_state: holds the CAIF_* protocol state, it's updated by > - * caif_ctrl_cb. > - * o sock->state: holds the SS_* socket state and is updated by connect and > - * disconnect. > - */ > -static int caif_connect(struct socket *sock, struct sockaddr_unsized *uaddr, > - int addr_len, int flags) > -{ > - struct sock *sk = sock->sk; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - long timeo; > - int err; > - int ifindex, headroom, tailroom; > - unsigned int mtu; > - struct net_device *dev; > - > - lock_sock(sk); > - > - err = -EINVAL; > - if (addr_len < offsetofend(struct sockaddr, sa_family)) > - goto out; > - > - err = -EAFNOSUPPORT; > - if (uaddr->sa_family != AF_CAIF) > - goto out; > - > - switch (sock->state) { > - case SS_UNCONNECTED: > - /* Normal case, a fresh connect */ > - caif_assert(sk->sk_state == CAIF_DISCONNECTED); > - break; > - case SS_CONNECTING: > - switch (sk->sk_state) { > - case CAIF_CONNECTED: > - sock->state = SS_CONNECTED; > - err = -EISCONN; > - goto out; > - case CAIF_DISCONNECTED: > - /* Reconnect allowed */ > - break; > - case CAIF_CONNECTING: > - err = -EALREADY; > - if (flags & O_NONBLOCK) > - goto out; > - goto wait_connect; > - } > - break; > - case SS_CONNECTED: > - caif_assert(sk->sk_state == CAIF_CONNECTED || > - sk->sk_state == CAIF_DISCONNECTED); > - if (sk->sk_shutdown & SHUTDOWN_MASK) { > - /* Allow re-connect after SHUTDOWN_IND */ > - caif_disconnect_client(sock_net(sk), &cf_sk->layer); > - caif_free_client(&cf_sk->layer); > - break; > - } > - /* No reconnect on a seqpacket socket */ > - err = -EISCONN; > - goto out; > - case SS_DISCONNECTING: > - case SS_FREE: > - caif_assert(1); /*Should never happen */ > - break; > - } > - sk->sk_state = CAIF_DISCONNECTED; > - sock->state = SS_UNCONNECTED; > - sk_stream_kill_queues(&cf_sk->sk); > - > - err = -EINVAL; > - if (addr_len != sizeof(struct sockaddr_caif)) > - goto out; > - > - memcpy(&cf_sk->conn_req.sockaddr, uaddr, > - sizeof(struct sockaddr_caif)); > - > - /* Move to connecting socket, start sending Connect Requests */ > - sock->state = SS_CONNECTING; > - sk->sk_state = CAIF_CONNECTING; > - > - /* Check priority value comming from socket */ > - /* if priority value is out of range it will be ajusted */ > - if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) > - cf_sk->conn_req.priority = CAIF_PRIO_MAX; > - else if (cf_sk->sk.sk_priority < CAIF_PRIO_MIN) > - cf_sk->conn_req.priority = CAIF_PRIO_MIN; > - else > - cf_sk->conn_req.priority = cf_sk->sk.sk_priority; > - > - /*ifindex = id of the interface.*/ > - cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if; > - > - cf_sk->layer.receive = caif_sktrecv_cb; > - > - err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, > - &cf_sk->layer, &ifindex, &headroom, &tailroom); > - > - if (err < 0) { > - cf_sk->sk.sk_socket->state = SS_UNCONNECTED; > - cf_sk->sk.sk_state = CAIF_DISCONNECTED; > - goto out; > - } > - > - err = -ENODEV; > - rcu_read_lock(); > - dev = dev_get_by_index_rcu(sock_net(sk), ifindex); > - if (!dev) { > - rcu_read_unlock(); > - goto out; > - } > - cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); > - mtu = dev->mtu; > - rcu_read_unlock(); > - > - cf_sk->tailroom = tailroom; > - cf_sk->maxframe = mtu - (headroom + tailroom); > - if (cf_sk->maxframe < 1) { > - pr_warn("CAIF Interface MTU too small (%d)\n", dev->mtu); > - err = -ENODEV; > - goto out; > - } > - > - err = -EINPROGRESS; > -wait_connect: > - > - if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK)) > - goto out; > - > - timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); > - > - release_sock(sk); > - err = -ERESTARTSYS; > - timeo = wait_event_interruptible_timeout(*sk_sleep(sk), > - sk->sk_state != CAIF_CONNECTING, > - timeo); > - lock_sock(sk); > - if (timeo < 0) > - goto out; /* -ERESTARTSYS */ > - > - err = -ETIMEDOUT; > - if (timeo == 0 && sk->sk_state != CAIF_CONNECTED) > - goto out; > - if (sk->sk_state != CAIF_CONNECTED) { > - sock->state = SS_UNCONNECTED; > - err = sock_error(sk); > - if (!err) > - err = -ECONNREFUSED; > - goto out; > - } > - sock->state = SS_CONNECTED; > - err = 0; > -out: > - release_sock(sk); > - return err; > -} > - > -/* > - * caif_release() - Disconnect a CAIF Socket > - * Copied and modified af_irda.c:irda_release(). > - */ > -static int caif_release(struct socket *sock) > -{ > - struct sock *sk = sock->sk; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - > - if (!sk) > - return 0; > - > - set_tx_flow_off(cf_sk); > - > - /* > - * Ensure that packets are not queued after this point in time. > - * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, > - * this ensures no packets when sock is dead. > - */ > - spin_lock_bh(&sk->sk_receive_queue.lock); > - sock_set_flag(sk, SOCK_DEAD); > - spin_unlock_bh(&sk->sk_receive_queue.lock); > - sock->sk = NULL; > - > - WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); > - debugfs_remove_recursive(cf_sk->debugfs_socket_dir); > - > - lock_sock(&(cf_sk->sk)); > - sk->sk_state = CAIF_DISCONNECTED; > - sk->sk_shutdown = SHUTDOWN_MASK; > - > - caif_disconnect_client(sock_net(sk), &cf_sk->layer); > - cf_sk->sk.sk_socket->state = SS_DISCONNECTING; > - wake_up_interruptible_poll(sk_sleep(sk), EPOLLERR|EPOLLHUP); > - > - sock_orphan(sk); > - sk_stream_kill_queues(&cf_sk->sk); > - release_sock(sk); > - sock_put(sk); > - return 0; > -} > - > -/* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ > -static __poll_t caif_poll(struct file *file, > - struct socket *sock, poll_table *wait) > -{ > - struct sock *sk = sock->sk; > - __poll_t mask; > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - > - sock_poll_wait(file, sock, wait); > - mask = 0; > - > - /* exceptional events? */ > - if (sk->sk_err) > - mask |= EPOLLERR; > - if (sk->sk_shutdown == SHUTDOWN_MASK) > - mask |= EPOLLHUP; > - if (sk->sk_shutdown & RCV_SHUTDOWN) > - mask |= EPOLLRDHUP; > - > - /* readable? */ > - if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || > - (sk->sk_shutdown & RCV_SHUTDOWN)) > - mask |= EPOLLIN | EPOLLRDNORM; > - > - /* > - * we set writable also when the other side has shut down the > - * connection. This prevents stuck sockets. > - */ > - if (sock_writeable(sk) && tx_flow_is_on(cf_sk)) > - mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; > - > - return mask; > -} > - > -static const struct proto_ops caif_seqpacket_ops = { > - .family = PF_CAIF, > - .owner = THIS_MODULE, > - .release = caif_release, > - .bind = sock_no_bind, > - .connect = caif_connect, > - .socketpair = sock_no_socketpair, > - .accept = sock_no_accept, > - .getname = sock_no_getname, > - .poll = caif_poll, > - .ioctl = sock_no_ioctl, > - .listen = sock_no_listen, > - .shutdown = sock_no_shutdown, > - .setsockopt = setsockopt, > - .sendmsg = caif_seqpkt_sendmsg, > - .recvmsg = caif_seqpkt_recvmsg, > - .mmap = sock_no_mmap, > -}; > - > -static const struct proto_ops caif_stream_ops = { > - .family = PF_CAIF, > - .owner = THIS_MODULE, > - .release = caif_release, > - .bind = sock_no_bind, > - .connect = caif_connect, > - .socketpair = sock_no_socketpair, > - .accept = sock_no_accept, > - .getname = sock_no_getname, > - .poll = caif_poll, > - .ioctl = sock_no_ioctl, > - .listen = sock_no_listen, > - .shutdown = sock_no_shutdown, > - .setsockopt = setsockopt, > - .sendmsg = caif_stream_sendmsg, > - .recvmsg = caif_stream_recvmsg, > - .mmap = sock_no_mmap, > -}; > - > -/* This function is called when a socket is finally destroyed. */ > -static void caif_sock_destructor(struct sock *sk) > -{ > - struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); > - caif_assert(!refcount_read(&sk->sk_wmem_alloc)); > - caif_assert(sk_unhashed(sk)); > - caif_assert(!sk->sk_socket); > - if (!sock_flag(sk, SOCK_DEAD)) { > - pr_debug("Attempt to release alive CAIF socket: %p\n", sk); > - return; > - } > - sk_stream_kill_queues(&cf_sk->sk); > - WARN_ON_ONCE(sk->sk_forward_alloc); > - caif_free_client(&cf_sk->layer); > -} > - > -static int caif_create(struct net *net, struct socket *sock, int protocol, > - int kern) > -{ > - struct sock *sk = NULL; > - struct caifsock *cf_sk = NULL; > - static struct proto prot = {.name = "PF_CAIF", > - .owner = THIS_MODULE, > - .obj_size = sizeof(struct caifsock), > - .useroffset = offsetof(struct caifsock, conn_req.param), > - .usersize = sizeof_field(struct caifsock, conn_req.param) > - }; > - > - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) > - return -EPERM; > - /* > - * The sock->type specifies the socket type to use. > - * The CAIF socket is a packet stream in the sense > - * that it is packet based. CAIF trusts the reliability > - * of the link, no resending is implemented. > - */ > - if (sock->type == SOCK_SEQPACKET) > - sock->ops = &caif_seqpacket_ops; > - else if (sock->type == SOCK_STREAM) > - sock->ops = &caif_stream_ops; > - else > - return -ESOCKTNOSUPPORT; > - > - if (protocol < 0 || protocol >= CAIFPROTO_MAX) > - return -EPROTONOSUPPORT; > - /* > - * Set the socket state to unconnected. The socket state > - * is really not used at all in the net/core or socket.c but the > - * initialization makes sure that sock->state is not uninitialized. > - */ > - sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot, kern); > - if (!sk) > - return -ENOMEM; > - > - cf_sk = container_of(sk, struct caifsock, sk); > - > - /* Store the protocol */ > - sk->sk_protocol = (unsigned char) protocol; > - > - /* Initialize default priority for well-known cases */ > - switch (protocol) { > - case CAIFPROTO_AT: > - sk->sk_priority = TC_PRIO_CONTROL; > - break; > - case CAIFPROTO_RFM: > - sk->sk_priority = TC_PRIO_INTERACTIVE_BULK; > - break; > - default: > - sk->sk_priority = TC_PRIO_BESTEFFORT; > - } > - > - /* > - * Lock in order to try to stop someone from opening the socket > - * too early. > - */ > - lock_sock(&(cf_sk->sk)); > - > - /* Initialize the nozero default sock structure data. */ > - sock_init_data(sock, sk); > - sk->sk_destruct = caif_sock_destructor; > - > - mutex_init(&cf_sk->readlock); /* single task reading lock */ > - cf_sk->layer.ctrlcmd = caif_ctrl_cb; > - cf_sk->sk.sk_socket->state = SS_UNCONNECTED; > - cf_sk->sk.sk_state = CAIF_DISCONNECTED; > - > - set_tx_flow_off(cf_sk); > - set_rx_flow_on(cf_sk); > - > - /* Set default options on configuration */ > - cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; > - cf_sk->conn_req.protocol = protocol; > - release_sock(&cf_sk->sk); > - return 0; > -} > - > - > -static const struct net_proto_family caif_family_ops = { > - .family = PF_CAIF, > - .create = caif_create, > - .owner = THIS_MODULE, > -}; > - > -static int __init caif_sktinit_module(void) > -{ > - return sock_register(&caif_family_ops); > -} > - > -static void __exit caif_sktexit_module(void) > -{ > - sock_unregister(PF_CAIF); > -} > -module_init(caif_sktinit_module); > -module_exit(caif_sktexit_module); > diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c > deleted file mode 100644 > index 4d44960d4c2f..000000000000 > --- a/net/caif/caif_usb.c > +++ /dev/null > @@ -1,216 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * CAIF USB handler > - * Copyright (C) ST-Ericsson AB 2011 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -MODULE_DESCRIPTION("ST-Ericsson CAIF modem protocol USB support"); > -MODULE_LICENSE("GPL"); > - > -#define CFUSB_PAD_DESCR_SZ 1 /* Alignment descriptor length */ > -#define CFUSB_ALIGNMENT 4 /* Number of bytes to align. */ > -#define CFUSB_MAX_HEADLEN (CFUSB_PAD_DESCR_SZ + CFUSB_ALIGNMENT-1) > -#define STE_USB_VID 0x04cc /* USB Product ID for ST-Ericsson */ > -#define STE_USB_PID_CAIF 0x230f /* Product id for CAIF Modems */ > - > -struct cfusbl { > - struct cflayer layer; > - u8 tx_eth_hdr[ETH_HLEN]; > -}; > - > -static bool pack_added; > - > -static int cfusbl_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 hpad; > - > - /* Remove padding. */ > - cfpkt_extr_head(pkt, &hpad, 1); > - cfpkt_extr_head(pkt, NULL, hpad); > - return layr->up->receive(layr->up, pkt); > -} > - > -static int cfusbl_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct caif_payload_info *info; > - u8 hpad; > - u8 zeros[CFUSB_ALIGNMENT]; > - struct sk_buff *skb; > - struct cfusbl *usbl = container_of(layr, struct cfusbl, layer); > - > - skb = cfpkt_tonative(pkt); > - > - skb_reset_network_header(skb); > - skb->protocol = htons(ETH_P_IP); > - > - info = cfpkt_info(pkt); > - hpad = (info->hdr_len + CFUSB_PAD_DESCR_SZ) & (CFUSB_ALIGNMENT - 1); > - > - if (skb_headroom(skb) < ETH_HLEN + CFUSB_PAD_DESCR_SZ + hpad) { > - pr_warn("Headroom too small\n"); > - kfree_skb(skb); > - return -EIO; > - } > - memset(zeros, 0, hpad); > - > - cfpkt_add_head(pkt, zeros, hpad); > - cfpkt_add_head(pkt, &hpad, 1); > - cfpkt_add_head(pkt, usbl->tx_eth_hdr, sizeof(usbl->tx_eth_hdr)); > - return layr->dn->transmit(layr->dn, pkt); > -} > - > -static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - if (layr->up && layr->up->ctrlcmd) > - layr->up->ctrlcmd(layr->up, ctrl, layr->id); > -} > - > -static struct cflayer *cfusbl_create(int phyid, const u8 ethaddr[ETH_ALEN], > - u8 braddr[ETH_ALEN]) > -{ > - struct cfusbl *this = kmalloc_obj(struct cfusbl, GFP_ATOMIC); > - > - if (!this) > - return NULL; > - > - caif_assert(offsetof(struct cfusbl, layer) == 0); > - > - memset(&this->layer, 0, sizeof(this->layer)); > - this->layer.receive = cfusbl_receive; > - this->layer.transmit = cfusbl_transmit; > - this->layer.ctrlcmd = cfusbl_ctrlcmd; > - snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "usb%d", phyid); > - this->layer.id = phyid; > - > - /* > - * Construct TX ethernet header: > - * 0-5 destination address > - * 5-11 source address > - * 12-13 protocol type > - */ > - ether_addr_copy(&this->tx_eth_hdr[ETH_ALEN], braddr); > - ether_addr_copy(&this->tx_eth_hdr[ETH_ALEN], ethaddr); > - this->tx_eth_hdr[12] = cpu_to_be16(ETH_P_802_EX1) & 0xff; > - this->tx_eth_hdr[13] = (cpu_to_be16(ETH_P_802_EX1) >> 8) & 0xff; > - pr_debug("caif ethernet TX-header dst:%pM src:%pM type:%02x%02x\n", > - this->tx_eth_hdr, this->tx_eth_hdr + ETH_ALEN, > - this->tx_eth_hdr[12], this->tx_eth_hdr[13]); > - > - return (struct cflayer *) this; > -} > - > -static void cfusbl_release(struct cflayer *layer) > -{ > - kfree(layer); > -} > - > -static struct packet_type caif_usb_type __read_mostly = { > - .type = cpu_to_be16(ETH_P_802_EX1), > -}; > - > -static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, > - void *ptr) > -{ > - struct net_device *dev = netdev_notifier_info_to_dev(ptr); > - struct caif_dev_common common; > - struct cflayer *layer, *link_support; > - struct usbnet *usbnet; > - struct usb_device *usbdev; > - int res; > - > - if (what == NETDEV_UNREGISTER && dev->reg_state >= NETREG_UNREGISTERED) > - return 0; > - > - /* Check whether we have a NCM device, and find its VID/PID. */ > - if (!(dev->dev.parent && dev->dev.parent->driver && > - strcmp(dev->dev.parent->driver->name, "cdc_ncm") == 0)) > - return 0; > - > - usbnet = netdev_priv(dev); > - usbdev = usbnet->udev; > - > - pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n", > - le16_to_cpu(usbdev->descriptor.idVendor), > - le16_to_cpu(usbdev->descriptor.idProduct)); > - > - /* Check for VID/PID that supports CAIF */ > - if (!(le16_to_cpu(usbdev->descriptor.idVendor) == STE_USB_VID && > - le16_to_cpu(usbdev->descriptor.idProduct) == STE_USB_PID_CAIF)) > - return 0; > - > - if (what == NETDEV_UNREGISTER) > - module_put(THIS_MODULE); > - > - if (what != NETDEV_REGISTER) > - return 0; > - > - __module_get(THIS_MODULE); > - > - memset(&common, 0, sizeof(common)); > - common.use_frag = false; > - common.use_fcs = false; > - common.use_stx = false; > - common.link_select = CAIF_LINK_HIGH_BANDW; > - common.flowctrl = NULL; > - > - link_support = cfusbl_create(dev->ifindex, dev->dev_addr, > - dev->broadcast); > - > - if (!link_support) > - return -ENOMEM; > - > - if (dev->num_tx_queues > 1) > - pr_warn("USB device uses more than one tx queue\n"); > - > - res = caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, > - &layer, &caif_usb_type.func); > - if (res) > - goto err; > - > - if (!pack_added) > - dev_add_pack(&caif_usb_type); > - pack_added = true; > - > - strscpy(layer->name, dev->name, sizeof(layer->name)); > - > - return 0; > -err: > - cfusbl_release(link_support); > - return res; > -} > - > -static struct notifier_block caif_device_notifier = { > - .notifier_call = cfusbl_device_notify, > - .priority = 0, > -}; > - > -static int __init cfusbl_init(void) > -{ > - return register_netdevice_notifier(&caif_device_notifier); > -} > - > -static void __exit cfusbl_exit(void) > -{ > - unregister_netdevice_notifier(&caif_device_notifier); > - dev_remove_pack(&caif_usb_type); > -} > - > -module_init(cfusbl_init); > -module_exit(cfusbl_exit); > diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c > deleted file mode 100644 > index 8a80914783e8..000000000000 > --- a/net/caif/cfcnfg.c > +++ /dev/null > @@ -1,612 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) container_of(layr, struct cfcnfg, layer) > - > -/* Information about CAIF physical interfaces held by Config Module in order > - * to manage physical interfaces > - */ > -struct cfcnfg_phyinfo { > - struct list_head node; > - bool up; > - > - /* Pointer to the layer below the MUX (framing layer) */ > - struct cflayer *frm_layer; > - /* Pointer to the lowest actual physical layer */ > - struct cflayer *phy_layer; > - /* Unique identifier of the physical interface */ > - unsigned int id; > - /* Preference of the physical in interface */ > - enum cfcnfg_phy_preference pref; > - > - /* Information about the physical device */ > - struct dev_info dev_info; > - > - /* Interface index */ > - int ifindex; > - > - /* Protocol head room added for CAIF link layer */ > - int head_room; > - > - /* Use Start of frame checksum */ > - bool use_fcs; > -}; > - > -struct cfcnfg { > - struct cflayer layer; > - struct cflayer *ctrl; > - struct cflayer *mux; > - struct list_head phys; > - struct mutex lock; > -}; > - > -static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, > - enum cfctrl_srv serv, u8 phyid, > - struct cflayer *adapt_layer); > -static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id); > -static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, > - struct cflayer *adapt_layer); > -static void cfctrl_resp_func(void); > -static void cfctrl_enum_resp(void); > - > -struct cfcnfg *cfcnfg_create(void) > -{ > - struct cfcnfg *this; > - struct cfctrl_rsp *resp; > - > - might_sleep(); > - > - /* Initiate this layer */ > - this = kzalloc_obj(struct cfcnfg, GFP_ATOMIC); > - if (!this) > - return NULL; > - this->mux = cfmuxl_create(); > - if (!this->mux) > - goto out_of_mem; > - this->ctrl = cfctrl_create(); > - if (!this->ctrl) > - goto out_of_mem; > - /* Initiate response functions */ > - resp = cfctrl_get_respfuncs(this->ctrl); > - resp->enum_rsp = cfctrl_enum_resp; > - resp->linkerror_ind = cfctrl_resp_func; > - resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp; > - resp->sleep_rsp = cfctrl_resp_func; > - resp->wake_rsp = cfctrl_resp_func; > - resp->restart_rsp = cfctrl_resp_func; > - resp->radioset_rsp = cfctrl_resp_func; > - resp->linksetup_rsp = cfcnfg_linkup_rsp; > - resp->reject_rsp = cfcnfg_reject_rsp; > - INIT_LIST_HEAD(&this->phys); > - > - cfmuxl_set_uplayer(this->mux, this->ctrl, 0); > - layer_set_dn(this->ctrl, this->mux); > - layer_set_up(this->ctrl, this); > - mutex_init(&this->lock); > - > - return this; > -out_of_mem: > - synchronize_rcu(); > - > - kfree(this->mux); > - kfree(this->ctrl); > - kfree(this); > - return NULL; > -} > - > -void cfcnfg_remove(struct cfcnfg *cfg) > -{ > - might_sleep(); > - if (cfg) { > - synchronize_rcu(); > - > - kfree(cfg->mux); > - cfctrl_remove(cfg->ctrl); > - kfree(cfg); > - } > -} > - > -static void cfctrl_resp_func(void) > -{ > -} > - > -static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg, > - u8 phyid) > -{ > - struct cfcnfg_phyinfo *phy; > - > - list_for_each_entry_rcu(phy, &cnfg->phys, node) > - if (phy->id == phyid) > - return phy; > - return NULL; > -} > - > -static void cfctrl_enum_resp(void) > -{ > -} > - > -static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, > - enum cfcnfg_phy_preference phy_pref) > -{ > - /* Try to match with specified preference */ > - struct cfcnfg_phyinfo *phy; > - > - list_for_each_entry_rcu(phy, &cnfg->phys, node) { > - if (phy->up && phy->pref == phy_pref && > - phy->frm_layer != NULL) > - > - return &phy->dev_info; > - } > - > - /* Otherwise just return something */ > - list_for_each_entry_rcu(phy, &cnfg->phys, node) > - if (phy->up) > - return &phy->dev_info; > - > - return NULL; > -} > - > -static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) > -{ > - struct cfcnfg_phyinfo *phy; > - > - list_for_each_entry_rcu(phy, &cnfg->phys, node) > - if (phy->ifindex == ifi && phy->up) > - return phy->id; > - return -ENODEV; > -} > - > -int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) > -{ > - u8 channel_id; > - struct cfcnfg *cfg = get_cfcnfg(net); > - > - caif_assert(adap_layer != NULL); > - cfctrl_cancel_req(cfg->ctrl, adap_layer); > - channel_id = adap_layer->id; > - if (channel_id != 0) { > - struct cflayer *servl; > - servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); > - cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); > - if (servl != NULL) > - layer_set_up(servl, NULL); > - } else > - pr_debug("nothing to disconnect\n"); > - > - /* Do RCU sync before initiating cleanup */ > - synchronize_rcu(); > - if (adap_layer->ctrlcmd != NULL) > - adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); > - return 0; > - > -} > -EXPORT_SYMBOL(caif_disconnect_client); > - > -static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) > -{ > -} > - > -static const int protohead[CFCTRL_SRV_MASK] = { > - [CFCTRL_SRV_VEI] = 4, > - [CFCTRL_SRV_DATAGRAM] = 7, > - [CFCTRL_SRV_UTIL] = 4, > - [CFCTRL_SRV_RFM] = 3, > - [CFCTRL_SRV_DBG] = 3, > -}; > - > - > -static int caif_connect_req_to_link_param(struct cfcnfg *cnfg, > - struct caif_connect_request *s, > - struct cfctrl_link_param *l) > -{ > - struct dev_info *dev_info; > - enum cfcnfg_phy_preference pref; > - int res; > - > - memset(l, 0, sizeof(*l)); > - /* In caif protocol low value is high priority */ > - l->priority = CAIF_PRIO_MAX - s->priority + 1; > - > - if (s->ifindex != 0) { > - res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); > - if (res < 0) > - return res; > - l->phyid = res; > - } else { > - switch (s->link_selector) { > - case CAIF_LINK_HIGH_BANDW: > - pref = CFPHYPREF_HIGH_BW; > - break; > - case CAIF_LINK_LOW_LATENCY: > - pref = CFPHYPREF_LOW_LAT; > - break; > - default: > - return -EINVAL; > - } > - dev_info = cfcnfg_get_phyid(cnfg, pref); > - if (dev_info == NULL) > - return -ENODEV; > - l->phyid = dev_info->id; > - } > - switch (s->protocol) { > - case CAIFPROTO_AT: > - l->linktype = CFCTRL_SRV_VEI; > - l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3; > - l->chtype = s->sockaddr.u.at.type & 0x3; > - break; > - case CAIFPROTO_DATAGRAM: > - l->linktype = CFCTRL_SRV_DATAGRAM; > - l->chtype = 0x00; > - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; > - break; > - case CAIFPROTO_DATAGRAM_LOOP: > - l->linktype = CFCTRL_SRV_DATAGRAM; > - l->chtype = 0x03; > - l->endpoint = 0x00; > - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; > - break; > - case CAIFPROTO_RFM: > - l->linktype = CFCTRL_SRV_RFM; > - l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; > - strscpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, > - sizeof(l->u.rfm.volume)); > - break; > - case CAIFPROTO_UTIL: > - l->linktype = CFCTRL_SRV_UTIL; > - l->endpoint = 0x00; > - l->chtype = 0x00; > - strscpy(l->u.utility.name, s->sockaddr.u.util.service, > - sizeof(l->u.utility.name)); > - caif_assert(sizeof(l->u.utility.name) > 10); > - l->u.utility.paramlen = s->param.size; > - if (l->u.utility.paramlen > sizeof(l->u.utility.params)) > - l->u.utility.paramlen = sizeof(l->u.utility.params); > - > - memcpy(l->u.utility.params, s->param.data, > - l->u.utility.paramlen); > - > - break; > - case CAIFPROTO_DEBUG: > - l->linktype = CFCTRL_SRV_DBG; > - l->endpoint = s->sockaddr.u.dbg.service; > - l->chtype = s->sockaddr.u.dbg.type; > - break; > - default: > - return -EINVAL; > - } > - return 0; > -} > - > -int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, > - struct cflayer *adap_layer, int *ifindex, > - int *proto_head, int *proto_tail) > -{ > - struct cflayer *frml; > - struct cfcnfg_phyinfo *phy; > - int err; > - struct cfctrl_link_param param; > - struct cfcnfg *cfg = get_cfcnfg(net); > - > - rcu_read_lock(); > - err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); > - if (err) > - goto unlock; > - > - phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid); > - if (!phy) { > - err = -ENODEV; > - goto unlock; > - } > - err = -EINVAL; > - > - if (adap_layer == NULL) { > - pr_err("adap_layer is zero\n"); > - goto unlock; > - } > - if (adap_layer->receive == NULL) { > - pr_err("adap_layer->receive is NULL\n"); > - goto unlock; > - } > - if (adap_layer->ctrlcmd == NULL) { > - pr_err("adap_layer->ctrlcmd == NULL\n"); > - goto unlock; > - } > - > - err = -ENODEV; > - frml = phy->frm_layer; > - if (frml == NULL) { > - pr_err("Specified PHY type does not exist!\n"); > - goto unlock; > - } > - caif_assert(param.phyid == phy->id); > - caif_assert(phy->frm_layer->id == > - param.phyid); > - caif_assert(phy->phy_layer->id == > - param.phyid); > - > - *ifindex = phy->ifindex; > - *proto_tail = 2; > - *proto_head = protohead[param.linktype] + phy->head_room; > - > - rcu_read_unlock(); > - > - /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ > - cfctrl_enum_req(cfg->ctrl, param.phyid); > - return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer); > - > -unlock: > - rcu_read_unlock(); > - return err; > -} > -EXPORT_SYMBOL(caif_connect_client); > - > -static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, > - struct cflayer *adapt_layer) > -{ > - if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) > - adapt_layer->ctrlcmd(adapt_layer, > - CAIF_CTRLCMD_INIT_FAIL_RSP, 0); > -} > - > -static void > -cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, > - u8 phyid, struct cflayer *adapt_layer) > -{ > - struct cfcnfg *cnfg = container_obj(layer); > - struct cflayer *servicel = NULL; > - struct cfcnfg_phyinfo *phyinfo; > - struct net_device *netdev; > - > - if (channel_id == 0) { > - pr_warn("received channel_id zero\n"); > - if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) > - adapt_layer->ctrlcmd(adapt_layer, > - CAIF_CTRLCMD_INIT_FAIL_RSP, 0); > - return; > - } > - > - rcu_read_lock(); > - > - if (adapt_layer == NULL) { > - pr_debug("link setup response but no client exist, send linkdown back\n"); > - cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); > - goto unlock; > - } > - > - caif_assert(cnfg != NULL); > - caif_assert(phyid != 0); > - > - phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); > - if (phyinfo == NULL) { > - pr_err("ERROR: Link Layer Device disappeared while connecting\n"); > - goto unlock; > - } > - > - caif_assert(phyinfo != NULL); > - caif_assert(phyinfo->id == phyid); > - caif_assert(phyinfo->phy_layer != NULL); > - caif_assert(phyinfo->phy_layer->id == phyid); > - > - adapt_layer->id = channel_id; > - > - switch (serv) { > - case CFCTRL_SRV_VEI: > - servicel = cfvei_create(channel_id, &phyinfo->dev_info); > - break; > - case CFCTRL_SRV_DATAGRAM: > - servicel = cfdgml_create(channel_id, > - &phyinfo->dev_info); > - break; > - case CFCTRL_SRV_RFM: > - netdev = phyinfo->dev_info.dev; > - servicel = cfrfml_create(channel_id, &phyinfo->dev_info, > - netdev->mtu); > - break; > - case CFCTRL_SRV_UTIL: > - servicel = cfutill_create(channel_id, &phyinfo->dev_info); > - break; > - case CFCTRL_SRV_VIDEO: > - servicel = cfvidl_create(channel_id, &phyinfo->dev_info); > - break; > - case CFCTRL_SRV_DBG: > - servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); > - break; > - default: > - pr_err("Protocol error. Link setup response - unknown channel type\n"); > - goto unlock; > - } > - if (!servicel) > - goto unlock; > - layer_set_dn(servicel, cnfg->mux); > - cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); > - layer_set_up(servicel, adapt_layer); > - layer_set_dn(adapt_layer, servicel); > - > - rcu_read_unlock(); > - > - servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); > - return; > -unlock: > - rcu_read_unlock(); > -} > - > -int > -cfcnfg_add_phy_layer(struct cfcnfg *cnfg, > - struct net_device *dev, struct cflayer *phy_layer, > - enum cfcnfg_phy_preference pref, > - struct cflayer *link_support, > - bool fcs, int head_room) > -{ > - struct cflayer *frml; > - struct cfcnfg_phyinfo *phyinfo = NULL; > - int i, res = 0; > - u8 phyid; > - > - mutex_lock(&cnfg->lock); > - > - /* CAIF protocol allow maximum 6 link-layers */ > - for (i = 0; i < 7; i++) { > - phyid = (dev->ifindex + i) & 0x7; > - if (phyid == 0) > - continue; > - if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL) > - goto got_phyid; > - } > - pr_warn("Too many CAIF Link Layers (max 6)\n"); > - res = -EEXIST; > - goto out; > - > -got_phyid: > - phyinfo = kzalloc_obj(struct cfcnfg_phyinfo, GFP_ATOMIC); > - if (!phyinfo) { > - res = -ENOMEM; > - goto out; > - } > - > - phy_layer->id = phyid; > - phyinfo->pref = pref; > - phyinfo->id = phyid; > - phyinfo->dev_info.id = phyid; > - phyinfo->dev_info.dev = dev; > - phyinfo->phy_layer = phy_layer; > - phyinfo->ifindex = dev->ifindex; > - phyinfo->head_room = head_room; > - phyinfo->use_fcs = fcs; > - > - frml = cffrml_create(phyid, fcs); > - > - if (!frml) { > - res = -ENOMEM; > - goto out_err; > - } > - phyinfo->frm_layer = frml; > - layer_set_up(frml, cnfg->mux); > - > - if (link_support != NULL) { > - link_support->id = phyid; > - layer_set_dn(frml, link_support); > - layer_set_up(link_support, frml); > - layer_set_dn(link_support, phy_layer); > - layer_set_up(phy_layer, link_support); > - } else { > - layer_set_dn(frml, phy_layer); > - layer_set_up(phy_layer, frml); > - } > - > - list_add_rcu(&phyinfo->node, &cnfg->phys); > -out: > - mutex_unlock(&cnfg->lock); > - return res; > - > -out_err: > - kfree(phyinfo); > - mutex_unlock(&cnfg->lock); > - return res; > -} > -EXPORT_SYMBOL(cfcnfg_add_phy_layer); > - > -int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, > - bool up) > -{ > - struct cfcnfg_phyinfo *phyinfo; > - > - rcu_read_lock(); > - phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id); > - if (phyinfo == NULL) { > - rcu_read_unlock(); > - return -ENODEV; > - } > - > - if (phyinfo->up == up) { > - rcu_read_unlock(); > - return 0; > - } > - phyinfo->up = up; > - > - if (up) { > - cffrml_hold(phyinfo->frm_layer); > - cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer, > - phy_layer->id); > - } else { > - cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); > - cffrml_put(phyinfo->frm_layer); > - } > - > - rcu_read_unlock(); > - return 0; > -} > -EXPORT_SYMBOL(cfcnfg_set_phy_state); > - > -int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) > -{ > - struct cflayer *frml, *frml_dn; > - u16 phyid; > - struct cfcnfg_phyinfo *phyinfo; > - > - might_sleep(); > - > - mutex_lock(&cnfg->lock); > - > - phyid = phy_layer->id; > - phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); > - > - if (phyinfo == NULL) { > - mutex_unlock(&cnfg->lock); > - return 0; > - } > - caif_assert(phyid == phyinfo->id); > - caif_assert(phy_layer == phyinfo->phy_layer); > - caif_assert(phy_layer->id == phyid); > - caif_assert(phyinfo->frm_layer->id == phyid); > - > - list_del_rcu(&phyinfo->node); > - synchronize_rcu(); > - > - /* Fail if reference count is not zero */ > - if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { > - pr_info("Wait for device inuse\n"); > - list_add_rcu(&phyinfo->node, &cnfg->phys); > - mutex_unlock(&cnfg->lock); > - return -EAGAIN; > - } > - > - frml = phyinfo->frm_layer; > - frml_dn = frml->dn; > - cffrml_set_uplayer(frml, NULL); > - cffrml_set_dnlayer(frml, NULL); > - if (phy_layer != frml_dn) { > - layer_set_up(frml_dn, NULL); > - layer_set_dn(frml_dn, NULL); > - } > - layer_set_up(phy_layer, NULL); > - > - if (phyinfo->phy_layer != frml_dn) > - kfree(frml_dn); > - > - cffrml_free(frml); > - kfree(phyinfo); > - mutex_unlock(&cnfg->lock); > - > - return 0; > -} > -EXPORT_SYMBOL(cfcnfg_del_phy_layer); > diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c > deleted file mode 100644 > index c6cc2bfed65d..000000000000 > --- a/net/caif/cfctrl.c > +++ /dev/null > @@ -1,631 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) container_of(layr, struct cfctrl, serv.layer) > -#define UTILITY_NAME_LENGTH 16 > -#define CFPKT_CTRL_PKT_LEN 20 > - > -#ifdef CAIF_NO_LOOP > -static int handle_loop(struct cfctrl *ctrl, > - int cmd, struct cfpkt *pkt){ > - return -1; > -} > -#else > -static int handle_loop(struct cfctrl *ctrl, > - int cmd, struct cfpkt *pkt); > -#endif > -static int cfctrl_recv(struct cflayer *layr, struct cfpkt *pkt); > -static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid); > - > - > -struct cflayer *cfctrl_create(void) > -{ > - struct dev_info dev_info; > - struct cfctrl *this = > - kzalloc_obj(struct cfctrl, GFP_ATOMIC); > - if (!this) > - return NULL; > - caif_assert(offsetof(struct cfctrl, serv.layer) == 0); > - memset(&dev_info, 0, sizeof(dev_info)); > - dev_info.id = 0xff; > - cfsrvl_init(&this->serv, 0, &dev_info, false); > - atomic_set(&this->req_seq_no, 1); > - atomic_set(&this->rsp_seq_no, 1); > - this->serv.layer.receive = cfctrl_recv; > - sprintf(this->serv.layer.name, "ctrl"); > - this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; > -#ifndef CAIF_NO_LOOP > - spin_lock_init(&this->loop_linkid_lock); > - this->loop_linkid = 1; > -#endif > - spin_lock_init(&this->info_list_lock); > - INIT_LIST_HEAD(&this->list); > - return &this->serv.layer; > -} > - > -void cfctrl_remove(struct cflayer *layer) > -{ > - struct cfctrl_request_info *p, *tmp; > - struct cfctrl *ctrl = container_obj(layer); > - > - spin_lock_bh(&ctrl->info_list_lock); > - list_for_each_entry_safe(p, tmp, &ctrl->list, list) { > - list_del(&p->list); > - kfree(p); > - } > - spin_unlock_bh(&ctrl->info_list_lock); > - kfree(layer); > -} > - > -static bool param_eq(const struct cfctrl_link_param *p1, > - const struct cfctrl_link_param *p2) > -{ > - bool eq = > - p1->linktype == p2->linktype && > - p1->priority == p2->priority && > - p1->phyid == p2->phyid && > - p1->endpoint == p2->endpoint && p1->chtype == p2->chtype; > - > - if (!eq) > - return false; > - > - switch (p1->linktype) { > - case CFCTRL_SRV_VEI: > - return true; > - case CFCTRL_SRV_DATAGRAM: > - return p1->u.datagram.connid == p2->u.datagram.connid; > - case CFCTRL_SRV_RFM: > - return > - p1->u.rfm.connid == p2->u.rfm.connid && > - strcmp(p1->u.rfm.volume, p2->u.rfm.volume) == 0; > - case CFCTRL_SRV_UTIL: > - return > - p1->u.utility.fifosize_kb == p2->u.utility.fifosize_kb > - && p1->u.utility.fifosize_bufs == > - p2->u.utility.fifosize_bufs > - && strcmp(p1->u.utility.name, p2->u.utility.name) == 0 > - && p1->u.utility.paramlen == p2->u.utility.paramlen > - && memcmp(p1->u.utility.params, p2->u.utility.params, > - p1->u.utility.paramlen) == 0; > - > - case CFCTRL_SRV_VIDEO: > - return p1->u.video.connid == p2->u.video.connid; > - case CFCTRL_SRV_DBG: > - return true; > - case CFCTRL_SRV_DECM: > - return false; > - default: > - return false; > - } > - return false; > -} > - > -static bool cfctrl_req_eq(const struct cfctrl_request_info *r1, > - const struct cfctrl_request_info *r2) > -{ > - if (r1->cmd != r2->cmd) > - return false; > - if (r1->cmd == CFCTRL_CMD_LINK_SETUP) > - return param_eq(&r1->param, &r2->param); > - else > - return r1->channel_id == r2->channel_id; > -} > - > -/* Insert request at the end */ > -static void cfctrl_insert_req(struct cfctrl *ctrl, > - struct cfctrl_request_info *req) > -{ > - spin_lock_bh(&ctrl->info_list_lock); > - atomic_inc(&ctrl->req_seq_no); > - req->sequence_no = atomic_read(&ctrl->req_seq_no); > - list_add_tail(&req->list, &ctrl->list); > - spin_unlock_bh(&ctrl->info_list_lock); > -} > - > -/* Compare and remove request */ > -static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, > - struct cfctrl_request_info *req) > -{ > - struct cfctrl_request_info *p, *tmp, *first; > - > - first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list); > - > - list_for_each_entry_safe(p, tmp, &ctrl->list, list) { > - if (cfctrl_req_eq(req, p)) { > - if (p != first) > - pr_warn("Requests are not received in order\n"); > - > - atomic_set(&ctrl->rsp_seq_no, > - p->sequence_no); > - list_del(&p->list); > - goto out; > - } > - } > - p = NULL; > -out: > - return p; > -} > - > -struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer) > -{ > - struct cfctrl *this = container_obj(layer); > - return &this->res; > -} > - > -static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) > -{ > - info->hdr_len = 0; > - info->channel_id = cfctrl->serv.layer.id; > - info->dev_info = &cfctrl->serv.dev_info; > -} > - > -void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) > -{ > - struct cfpkt *pkt; > - struct cfctrl *cfctrl = container_obj(layer); > - struct cflayer *dn = cfctrl->serv.layer.dn; > - > - if (!dn) { > - pr_debug("not able to send enum request\n"); > - return; > - } > - pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); > - if (!pkt) > - return; > - caif_assert(offsetof(struct cfctrl, serv.layer) == 0); > - init_info(cfpkt_info(pkt), cfctrl); > - cfpkt_info(pkt)->dev_info->id = physlinkid; > - cfctrl->serv.dev_info.id = physlinkid; > - cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM); > - cfpkt_addbdy(pkt, physlinkid); > - cfpkt_set_prio(pkt, TC_PRIO_CONTROL); > - dn->transmit(dn, pkt); > -} > - > -int cfctrl_linkup_request(struct cflayer *layer, > - struct cfctrl_link_param *param, > - struct cflayer *user_layer) > -{ > - struct cfctrl *cfctrl = container_obj(layer); > - struct cflayer *dn = cfctrl->serv.layer.dn; > - char utility_name[UTILITY_NAME_LENGTH]; > - struct cfctrl_request_info *req; > - struct cfpkt *pkt; > - u32 tmp32; > - u16 tmp16; > - u8 tmp8; > - int ret; > - > - if (!dn) { > - pr_debug("not able to send linkup request\n"); > - return -ENODEV; > - } > - > - if (cfctrl_cancel_req(layer, user_layer) > 0) { > - /* Slight Paranoia, check if already connecting */ > - pr_err("Duplicate connect request for same client\n"); > - WARN_ON(1); > - return -EALREADY; > - } > - > - pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); > - if (!pkt) > - return -ENOMEM; > - cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); > - cfpkt_addbdy(pkt, (param->chtype << 4) | param->linktype); > - cfpkt_addbdy(pkt, (param->priority << 3) | param->phyid); > - cfpkt_addbdy(pkt, param->endpoint & 0x03); > - > - switch (param->linktype) { > - case CFCTRL_SRV_VEI: > - break; > - case CFCTRL_SRV_VIDEO: > - cfpkt_addbdy(pkt, (u8) param->u.video.connid); > - break; > - case CFCTRL_SRV_DBG: > - break; > - case CFCTRL_SRV_DATAGRAM: > - tmp32 = cpu_to_le32(param->u.datagram.connid); > - cfpkt_add_body(pkt, &tmp32, 4); > - break; > - case CFCTRL_SRV_RFM: > - /* Construct a frame, convert DatagramConnectionID to network > - * format long and copy it out... > - */ > - tmp32 = cpu_to_le32(param->u.rfm.connid); > - cfpkt_add_body(pkt, &tmp32, 4); > - /* Add volume name, including zero termination... */ > - cfpkt_add_body(pkt, param->u.rfm.volume, > - strlen(param->u.rfm.volume) + 1); > - break; > - case CFCTRL_SRV_UTIL: > - tmp16 = cpu_to_le16(param->u.utility.fifosize_kb); > - cfpkt_add_body(pkt, &tmp16, 2); > - tmp16 = cpu_to_le16(param->u.utility.fifosize_bufs); > - cfpkt_add_body(pkt, &tmp16, 2); > - strscpy_pad(utility_name, param->u.utility.name); > - cfpkt_add_body(pkt, utility_name, UTILITY_NAME_LENGTH); > - tmp8 = param->u.utility.paramlen; > - cfpkt_add_body(pkt, &tmp8, 1); > - cfpkt_add_body(pkt, param->u.utility.params, > - param->u.utility.paramlen); > - break; > - default: > - pr_warn("Request setup of bad link type = %d\n", > - param->linktype); > - cfpkt_destroy(pkt); > - return -EINVAL; > - } > - req = kzalloc_obj(*req); > - if (!req) { > - cfpkt_destroy(pkt); > - return -ENOMEM; > - } > - > - req->client_layer = user_layer; > - req->cmd = CFCTRL_CMD_LINK_SETUP; > - req->param = *param; > - cfctrl_insert_req(cfctrl, req); > - init_info(cfpkt_info(pkt), cfctrl); > - /* > - * NOTE:Always send linkup and linkdown request on the same > - * device as the payload. Otherwise old queued up payload > - * might arrive with the newly allocated channel ID. > - */ > - cfpkt_info(pkt)->dev_info->id = param->phyid; > - cfpkt_set_prio(pkt, TC_PRIO_CONTROL); > - ret = > - dn->transmit(dn, pkt); > - if (ret < 0) { > - int count; > - > - count = cfctrl_cancel_req(&cfctrl->serv.layer, > - user_layer); > - if (count != 1) { > - pr_err("Could not remove request (%d)", count); > - return -ENODEV; > - } > - } > - return 0; > -} > - > -int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, > - struct cflayer *client) > -{ > - int ret; > - struct cfpkt *pkt; > - struct cfctrl *cfctrl = container_obj(layer); > - struct cflayer *dn = cfctrl->serv.layer.dn; > - > - if (!dn) { > - pr_debug("not able to send link-down request\n"); > - return -ENODEV; > - } > - pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); > - if (!pkt) > - return -ENOMEM; > - cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); > - cfpkt_addbdy(pkt, channelid); > - init_info(cfpkt_info(pkt), cfctrl); > - cfpkt_set_prio(pkt, TC_PRIO_CONTROL); > - ret = > - dn->transmit(dn, pkt); > -#ifndef CAIF_NO_LOOP > - cfctrl->loop_linkused[channelid] = 0; > -#endif > - return ret; > -} > - > -int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) > -{ > - struct cfctrl_request_info *p, *tmp; > - struct cfctrl *ctrl = container_obj(layr); > - int found = 0; > - spin_lock_bh(&ctrl->info_list_lock); > - > - list_for_each_entry_safe(p, tmp, &ctrl->list, list) { > - if (p->client_layer == adap_layer) { > - list_del(&p->list); > - kfree(p); > - found++; > - } > - } > - > - spin_unlock_bh(&ctrl->info_list_lock); > - return found; > -} > - > -static int cfctrl_link_setup(struct cfctrl *cfctrl, struct cfpkt *pkt, u8 cmdrsp) > -{ > - u8 len; > - u8 linkid = 0; > - enum cfctrl_srv serv; > - enum cfctrl_srv servtype; > - u8 endpoint; > - u8 physlinkid; > - u8 prio; > - u8 tmp; > - u8 *cp; > - int i; > - struct cfctrl_link_param linkparam; > - struct cfctrl_request_info rsp, *req; > - > - memset(&linkparam, 0, sizeof(linkparam)); > - > - tmp = cfpkt_extr_head_u8(pkt); > - > - serv = tmp & CFCTRL_SRV_MASK; > - linkparam.linktype = serv; > - > - servtype = tmp >> 4; > - linkparam.chtype = servtype; > - > - tmp = cfpkt_extr_head_u8(pkt); > - physlinkid = tmp & 0x07; > - prio = tmp >> 3; > - > - linkparam.priority = prio; > - linkparam.phyid = physlinkid; > - endpoint = cfpkt_extr_head_u8(pkt); > - linkparam.endpoint = endpoint & 0x03; > - > - switch (serv) { > - case CFCTRL_SRV_VEI: > - case CFCTRL_SRV_DBG: > - if (CFCTRL_ERR_BIT & cmdrsp) > - break; > - /* Link ID */ > - linkid = cfpkt_extr_head_u8(pkt); > - break; > - case CFCTRL_SRV_VIDEO: > - tmp = cfpkt_extr_head_u8(pkt); > - linkparam.u.video.connid = tmp; > - if (CFCTRL_ERR_BIT & cmdrsp) > - break; > - /* Link ID */ > - linkid = cfpkt_extr_head_u8(pkt); > - break; > - > - case CFCTRL_SRV_DATAGRAM: > - linkparam.u.datagram.connid = cfpkt_extr_head_u32(pkt); > - if (CFCTRL_ERR_BIT & cmdrsp) > - break; > - /* Link ID */ > - linkid = cfpkt_extr_head_u8(pkt); > - break; > - case CFCTRL_SRV_RFM: > - /* Construct a frame, convert > - * DatagramConnectionID > - * to network format long and copy it out... > - */ > - linkparam.u.rfm.connid = cfpkt_extr_head_u32(pkt); > - cp = (u8 *) linkparam.u.rfm.volume; > - for (tmp = cfpkt_extr_head_u8(pkt); > - cfpkt_more(pkt) && tmp != '\0'; > - tmp = cfpkt_extr_head_u8(pkt)) > - *cp++ = tmp; > - *cp = '\0'; > - > - if (CFCTRL_ERR_BIT & cmdrsp) > - break; > - /* Link ID */ > - linkid = cfpkt_extr_head_u8(pkt); > - > - break; > - case CFCTRL_SRV_UTIL: > - /* Construct a frame, convert > - * DatagramConnectionID > - * to network format long and copy it out... > - */ > - /* Fifosize KB */ > - linkparam.u.utility.fifosize_kb = cfpkt_extr_head_u16(pkt); > - /* Fifosize bufs */ > - linkparam.u.utility.fifosize_bufs = cfpkt_extr_head_u16(pkt); > - /* name */ > - cp = (u8 *) linkparam.u.utility.name; > - caif_assert(sizeof(linkparam.u.utility.name) > - >= UTILITY_NAME_LENGTH); > - for (i = 0; i < UTILITY_NAME_LENGTH && cfpkt_more(pkt); i++) { > - tmp = cfpkt_extr_head_u8(pkt); > - *cp++ = tmp; > - } > - /* Length */ > - len = cfpkt_extr_head_u8(pkt); > - linkparam.u.utility.paramlen = len; > - /* Param Data */ > - cp = linkparam.u.utility.params; > - while (cfpkt_more(pkt) && len--) { > - tmp = cfpkt_extr_head_u8(pkt); > - *cp++ = tmp; > - } > - if (CFCTRL_ERR_BIT & cmdrsp) > - break; > - /* Link ID */ > - linkid = cfpkt_extr_head_u8(pkt); > - /* Length */ > - len = cfpkt_extr_head_u8(pkt); > - /* Param Data */ > - cfpkt_extr_head(pkt, NULL, len); > - break; > - default: > - pr_warn("Request setup, invalid type (%d)\n", serv); > - return -1; > - } > - > - rsp.cmd = CFCTRL_CMD_LINK_SETUP; > - rsp.param = linkparam; > - spin_lock_bh(&cfctrl->info_list_lock); > - req = cfctrl_remove_req(cfctrl, &rsp); > - > - if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || > - cfpkt_erroneous(pkt)) { > - pr_err("Invalid O/E bit or parse error " > - "on CAIF control channel\n"); > - cfctrl->res.reject_rsp(cfctrl->serv.layer.up, 0, > - req ? req->client_layer : NULL); > - } else { > - cfctrl->res.linksetup_rsp(cfctrl->serv.layer.up, linkid, > - serv, physlinkid, > - req ? req->client_layer : NULL); > - } > - > - kfree(req); > - > - spin_unlock_bh(&cfctrl->info_list_lock); > - > - return 0; > -} > - > -static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) > -{ > - u8 cmdrsp; > - u8 cmd; > - int ret = 0; > - u8 linkid = 0; > - struct cfctrl *cfctrl = container_obj(layer); > - > - cmdrsp = cfpkt_extr_head_u8(pkt); > - cmd = cmdrsp & CFCTRL_CMD_MASK; > - if (cmd != CFCTRL_CMD_LINK_ERR > - && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp) > - && CFCTRL_ERR_BIT != (CFCTRL_ERR_BIT & cmdrsp)) { > - if (handle_loop(cfctrl, cmd, pkt) != 0) > - cmdrsp |= CFCTRL_ERR_BIT; > - } > - > - switch (cmd) { > - case CFCTRL_CMD_LINK_SETUP: > - ret = cfctrl_link_setup(cfctrl, pkt, cmdrsp); > - break; > - case CFCTRL_CMD_LINK_DESTROY: > - linkid = cfpkt_extr_head_u8(pkt); > - cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid); > - break; > - case CFCTRL_CMD_LINK_ERR: > - pr_err("Frame Error Indication received\n"); > - cfctrl->res.linkerror_ind(); > - break; > - case CFCTRL_CMD_ENUM: > - cfctrl->res.enum_rsp(); > - break; > - case CFCTRL_CMD_SLEEP: > - cfctrl->res.sleep_rsp(); > - break; > - case CFCTRL_CMD_WAKE: > - cfctrl->res.wake_rsp(); > - break; > - case CFCTRL_CMD_LINK_RECONF: > - cfctrl->res.restart_rsp(); > - break; > - case CFCTRL_CMD_RADIO_SET: > - cfctrl->res.radioset_rsp(); > - break; > - default: > - pr_err("Unrecognized Control Frame\n"); > - ret = -1; > - goto error; > - } > -error: > - cfpkt_destroy(pkt); > - return ret; > -} > - > -static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - struct cfctrl *this = container_obj(layr); > - switch (ctrl) { > - case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: > - case CAIF_CTRLCMD_FLOW_OFF_IND: > - spin_lock_bh(&this->info_list_lock); > - if (!list_empty(&this->list)) > - pr_debug("Received flow off in control layer\n"); > - spin_unlock_bh(&this->info_list_lock); > - break; > - case _CAIF_CTRLCMD_PHYIF_DOWN_IND: { > - struct cfctrl_request_info *p, *tmp; > - > - /* Find all connect request and report failure */ > - spin_lock_bh(&this->info_list_lock); > - list_for_each_entry_safe(p, tmp, &this->list, list) { > - if (p->param.phyid == phyid) { > - list_del(&p->list); > - p->client_layer->ctrlcmd(p->client_layer, > - CAIF_CTRLCMD_INIT_FAIL_RSP, > - phyid); > - kfree(p); > - } > - } > - spin_unlock_bh(&this->info_list_lock); > - break; > - } > - default: > - break; > - } > -} > - > -#ifndef CAIF_NO_LOOP > -static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) > -{ > - static int last_linkid; > - static int dec; > - u8 linkid, linktype, tmp; > - switch (cmd) { > - case CFCTRL_CMD_LINK_SETUP: > - spin_lock_bh(&ctrl->loop_linkid_lock); > - if (!dec) { > - for (linkid = last_linkid + 1; linkid < 254; linkid++) > - if (!ctrl->loop_linkused[linkid]) > - goto found; > - } > - dec = 1; > - for (linkid = last_linkid - 1; linkid > 1; linkid--) > - if (!ctrl->loop_linkused[linkid]) > - goto found; > - spin_unlock_bh(&ctrl->loop_linkid_lock); > - return -1; > -found: > - if (linkid < 10) > - dec = 0; > - > - if (!ctrl->loop_linkused[linkid]) > - ctrl->loop_linkused[linkid] = 1; > - > - last_linkid = linkid; > - > - cfpkt_add_trail(pkt, &linkid, 1); > - spin_unlock_bh(&ctrl->loop_linkid_lock); > - cfpkt_peek_head(pkt, &linktype, 1); > - if (linktype == CFCTRL_SRV_UTIL) { > - tmp = 0x01; > - cfpkt_add_trail(pkt, &tmp, 1); > - cfpkt_add_trail(pkt, &tmp, 1); > - } > - break; > - > - case CFCTRL_CMD_LINK_DESTROY: > - spin_lock_bh(&ctrl->loop_linkid_lock); > - cfpkt_peek_head(pkt, &linkid, 1); > - ctrl->loop_linkused[linkid] = 0; > - spin_unlock_bh(&ctrl->loop_linkid_lock); > - break; > - default: > - break; > - } > - return 0; > -} > -#endif > diff --git a/net/caif/cfdbgl.c b/net/caif/cfdbgl.c > deleted file mode 100644 > index 57ad3f82e004..000000000000 > --- a/net/caif/cfdbgl.c > +++ /dev/null > @@ -1,55 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) ((struct cfsrvl *) layr) > - > -static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info) > -{ > - struct cfsrvl *dbg = kzalloc_obj(struct cfsrvl, GFP_ATOMIC); > - if (!dbg) > - return NULL; > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - cfsrvl_init(dbg, channel_id, dev_info, false); > - dbg->layer.receive = cfdbgl_receive; > - dbg->layer.transmit = cfdbgl_transmit; > - snprintf(dbg->layer.name, CAIF_LAYER_NAME_SZ, "dbg%d", channel_id); > - return &dbg->layer; > -} > - > -static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - return layr->up->receive(layr->up, pkt); > -} > - > -static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct cfsrvl *service = container_obj(layr); > - struct caif_payload_info *info; > - int ret; > - > - if (!cfsrvl_ready(service, &ret)) { > - cfpkt_destroy(pkt); > - return ret; > - } > - > - /* Add info for MUX-layer to route the packet out */ > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - info->dev_info = &service->dev_info; > - > - return layr->dn->transmit(layr->dn, pkt); > -} > diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c > deleted file mode 100644 > index c451ddd155a7..000000000000 > --- a/net/caif/cfdgml.c > +++ /dev/null > @@ -1,113 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > - > - > -#define container_obj(layr) ((struct cfsrvl *) layr) > - > -#define DGM_CMD_BIT 0x80 > -#define DGM_FLOW_OFF 0x81 > -#define DGM_FLOW_ON 0x80 > -#define DGM_MTU 1500 > - > -static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info) > -{ > - struct cfsrvl *dgm = kzalloc_obj(struct cfsrvl, GFP_ATOMIC); > - if (!dgm) > - return NULL; > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - cfsrvl_init(dgm, channel_id, dev_info, true); > - dgm->layer.receive = cfdgml_receive; > - dgm->layer.transmit = cfdgml_transmit; > - snprintf(dgm->layer.name, CAIF_LAYER_NAME_SZ, "dgm%d", channel_id); > - return &dgm->layer; > -} > - > -static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 cmd = -1; > - u8 dgmhdr[3]; > - int ret; > - caif_assert(layr->up != NULL); > - caif_assert(layr->receive != NULL); > - caif_assert(layr->ctrlcmd != NULL); > - > - if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - > - if ((cmd & DGM_CMD_BIT) == 0) { > - if (cfpkt_extr_head(pkt, &dgmhdr, 3) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - ret = layr->up->receive(layr->up, pkt); > - return ret; > - } > - > - switch (cmd) { > - case DGM_FLOW_OFF: /* FLOW OFF */ > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - case DGM_FLOW_ON: /* FLOW ON */ > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - default: > - cfpkt_destroy(pkt); > - pr_info("Unknown datagram control %d (0x%x)\n", cmd, cmd); > - return -EPROTO; > - } > -} > - > -static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 packet_type; > - u32 zero = 0; > - struct caif_payload_info *info; > - struct cfsrvl *service = container_obj(layr); > - int ret; > - > - if (!cfsrvl_ready(service, &ret)) { > - cfpkt_destroy(pkt); > - return ret; > - } > - > - /* STE Modem cannot handle more than 1500 bytes datagrams */ > - if (cfpkt_getlen(pkt) > DGM_MTU) { > - cfpkt_destroy(pkt); > - return -EMSGSIZE; > - } > - > - cfpkt_add_head(pkt, &zero, 3); > - packet_type = 0x08; /* B9 set - UNCLASSIFIED */ > - cfpkt_add_head(pkt, &packet_type, 1); > - > - /* Add info for MUX-layer to route the packet out. */ > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - /* To optimize alignment, we add up the size of CAIF header > - * before payload. > - */ > - info->hdr_len = 4; > - info->dev_info = &service->dev_info; > - return layr->dn->transmit(layr->dn, pkt); > -} > diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c > deleted file mode 100644 > index 0f4979d89fcb..000000000000 > --- a/net/caif/cffrml.c > +++ /dev/null > @@ -1,204 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * CAIF Framing Layer. > - * > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) container_of(layr, struct cffrml, layer) > - > -struct cffrml { > - struct cflayer layer; > - bool dofcs; /* !< FCS active */ > - int __percpu *pcpu_refcnt; > -}; > - > -static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt); > -static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid); > - > -static u32 cffrml_rcv_error; > -static u32 cffrml_rcv_checsum_error; > -struct cflayer *cffrml_create(u16 phyid, bool use_fcs) > -{ > - struct cffrml *this = kzalloc_obj(struct cffrml, GFP_ATOMIC); > - if (!this) > - return NULL; > - this->pcpu_refcnt = alloc_percpu(int); > - if (this->pcpu_refcnt == NULL) { > - kfree(this); > - return NULL; > - } > - > - caif_assert(offsetof(struct cffrml, layer) == 0); > - > - this->layer.receive = cffrml_receive; > - this->layer.transmit = cffrml_transmit; > - this->layer.ctrlcmd = cffrml_ctrlcmd; > - snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid); > - this->dofcs = use_fcs; > - this->layer.id = phyid; > - return (struct cflayer *) this; > -} > - > -void cffrml_free(struct cflayer *layer) > -{ > - struct cffrml *this = container_obj(layer); > - free_percpu(this->pcpu_refcnt); > - kfree(layer); > -} > - > -void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) > -{ > - this->up = up; > -} > - > -void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn) > -{ > - this->dn = dn; > -} > - > -static u16 cffrml_checksum(u16 chks, void *buf, u16 len) > -{ > - /* FIXME: FCS should be moved to glue in order to use OS-Specific > - * solutions > - */ > - return crc_ccitt(chks, buf, len); > -} > - > -static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u16 tmp; > - u16 len; > - u16 hdrchks; > - int pktchks; > - struct cffrml *this; > - this = container_obj(layr); > - > - cfpkt_extr_head(pkt, &tmp, 2); > - len = le16_to_cpu(tmp); > - > - /* Subtract for FCS on length if FCS is not used. */ > - if (!this->dofcs) { > - if (len < 2) { > - ++cffrml_rcv_error; > - pr_err("Invalid frame length (%d)\n", len); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - len -= 2; > - } > - > - if (cfpkt_setlen(pkt, len) < 0) { > - ++cffrml_rcv_error; > - pr_err("Framing length error (%d)\n", len); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - /* > - * Don't do extract if FCS is false, rather do setlen - then we don't > - * get a cache-miss. > - */ > - if (this->dofcs) { > - cfpkt_extr_trail(pkt, &tmp, 2); > - hdrchks = le16_to_cpu(tmp); > - pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); > - if (pktchks != hdrchks) { > - cfpkt_add_trail(pkt, &tmp, 2); > - ++cffrml_rcv_error; > - ++cffrml_rcv_checsum_error; > - pr_info("Frame checksum error (0x%x != 0x%x)\n", > - hdrchks, pktchks); > - return -EILSEQ; > - } > - } > - if (cfpkt_erroneous(pkt)) { > - ++cffrml_rcv_error; > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - > - if (layr->up == NULL) { > - pr_err("Layr up is missing!\n"); > - cfpkt_destroy(pkt); > - return -EINVAL; > - } > - > - return layr->up->receive(layr->up, pkt); > -} > - > -static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u16 chks; > - u16 len; > - __le16 data; > - > - struct cffrml *this = container_obj(layr); > - if (this->dofcs) { > - chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); > - data = cpu_to_le16(chks); > - cfpkt_add_trail(pkt, &data, 2); > - } else { > - cfpkt_pad_trail(pkt, 2); > - } > - len = cfpkt_getlen(pkt); > - data = cpu_to_le16(len); > - cfpkt_add_head(pkt, &data, 2); > - cfpkt_info(pkt)->hdr_len += 2; > - if (cfpkt_erroneous(pkt)) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - > - if (layr->dn == NULL) { > - cfpkt_destroy(pkt); > - return -ENODEV; > - > - } > - return layr->dn->transmit(layr->dn, pkt); > -} > - > -static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - if (layr->up && layr->up->ctrlcmd) > - layr->up->ctrlcmd(layr->up, ctrl, layr->id); > -} > - > -void cffrml_put(struct cflayer *layr) > -{ > - struct cffrml *this = container_obj(layr); > - if (layr != NULL && this->pcpu_refcnt != NULL) > - this_cpu_dec(*this->pcpu_refcnt); > -} > - > -void cffrml_hold(struct cflayer *layr) > -{ > - struct cffrml *this = container_obj(layr); > - if (layr != NULL && this->pcpu_refcnt != NULL) > - this_cpu_inc(*this->pcpu_refcnt); > -} > - > -int cffrml_refcnt_read(struct cflayer *layr) > -{ > - int i, refcnt = 0; > - struct cffrml *this = container_obj(layr); > - for_each_possible_cpu(i) > - refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); > - return refcnt; > -} > diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c > deleted file mode 100644 > index 77a1f31639b7..000000000000 > --- a/net/caif/cfmuxl.c > +++ /dev/null > @@ -1,267 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) container_of(layr, struct cfmuxl, layer) > - > -#define CAIF_CTRL_CHANNEL 0 > -#define UP_CACHE_SIZE 8 > -#define DN_CACHE_SIZE 8 > - > -struct cfmuxl { > - struct cflayer layer; > - struct list_head srvl_list; > - struct list_head frml_list; > - struct cflayer *up_cache[UP_CACHE_SIZE]; > - struct cflayer *dn_cache[DN_CACHE_SIZE]; > - /* > - * Set when inserting or removing downwards layers. > - */ > - spinlock_t transmit_lock; > - > - /* > - * Set when inserting or removing upwards layers. > - */ > - spinlock_t receive_lock; > - > -}; > - > -static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt); > -static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid); > -static struct cflayer *get_up(struct cfmuxl *muxl, u16 id); > - > -struct cflayer *cfmuxl_create(void) > -{ > - struct cfmuxl *this = kzalloc_obj(struct cfmuxl, GFP_ATOMIC); > - > - if (!this) > - return NULL; > - this->layer.receive = cfmuxl_receive; > - this->layer.transmit = cfmuxl_transmit; > - this->layer.ctrlcmd = cfmuxl_ctrlcmd; > - INIT_LIST_HEAD(&this->srvl_list); > - INIT_LIST_HEAD(&this->frml_list); > - spin_lock_init(&this->transmit_lock); > - spin_lock_init(&this->receive_lock); > - snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "mux"); > - return &this->layer; > -} > - > -int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) > -{ > - struct cfmuxl *muxl = (struct cfmuxl *) layr; > - > - spin_lock_bh(&muxl->transmit_lock); > - list_add_rcu(&dn->node, &muxl->frml_list); > - spin_unlock_bh(&muxl->transmit_lock); > - return 0; > -} > - > -static struct cflayer *get_from_id(struct list_head *list, u16 id) > -{ > - struct cflayer *lyr; > - list_for_each_entry_rcu(lyr, list, node) { > - if (lyr->id == id) > - return lyr; > - } > - > - return NULL; > -} > - > -int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) > -{ > - struct cfmuxl *muxl = container_obj(layr); > - struct cflayer *old; > - > - spin_lock_bh(&muxl->receive_lock); > - > - /* Two entries with same id is wrong, so remove old layer from mux */ > - old = get_from_id(&muxl->srvl_list, linkid); > - if (old != NULL) > - list_del_rcu(&old->node); > - > - list_add_rcu(&up->node, &muxl->srvl_list); > - spin_unlock_bh(&muxl->receive_lock); > - > - return 0; > -} > - > -struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid) > -{ > - struct cfmuxl *muxl = container_obj(layr); > - struct cflayer *dn; > - int idx = phyid % DN_CACHE_SIZE; > - > - spin_lock_bh(&muxl->transmit_lock); > - RCU_INIT_POINTER(muxl->dn_cache[idx], NULL); > - dn = get_from_id(&muxl->frml_list, phyid); > - if (dn == NULL) > - goto out; > - > - list_del_rcu(&dn->node); > - caif_assert(dn != NULL); > -out: > - spin_unlock_bh(&muxl->transmit_lock); > - return dn; > -} > - > -static struct cflayer *get_up(struct cfmuxl *muxl, u16 id) > -{ > - struct cflayer *up; > - int idx = id % UP_CACHE_SIZE; > - up = rcu_dereference(muxl->up_cache[idx]); > - if (up == NULL || up->id != id) { > - spin_lock_bh(&muxl->receive_lock); > - up = get_from_id(&muxl->srvl_list, id); > - rcu_assign_pointer(muxl->up_cache[idx], up); > - spin_unlock_bh(&muxl->receive_lock); > - } > - return up; > -} > - > -static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info) > -{ > - struct cflayer *dn; > - int idx = dev_info->id % DN_CACHE_SIZE; > - dn = rcu_dereference(muxl->dn_cache[idx]); > - if (dn == NULL || dn->id != dev_info->id) { > - spin_lock_bh(&muxl->transmit_lock); > - dn = get_from_id(&muxl->frml_list, dev_info->id); > - rcu_assign_pointer(muxl->dn_cache[idx], dn); > - spin_unlock_bh(&muxl->transmit_lock); > - } > - return dn; > -} > - > -struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) > -{ > - struct cflayer *up; > - struct cfmuxl *muxl = container_obj(layr); > - int idx = id % UP_CACHE_SIZE; > - > - if (id == 0) { > - pr_warn("Trying to remove control layer\n"); > - return NULL; > - } > - > - spin_lock_bh(&muxl->receive_lock); > - up = get_from_id(&muxl->srvl_list, id); > - if (up == NULL) > - goto out; > - > - RCU_INIT_POINTER(muxl->up_cache[idx], NULL); > - list_del_rcu(&up->node); > -out: > - spin_unlock_bh(&muxl->receive_lock); > - return up; > -} > - > -static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - int ret; > - struct cfmuxl *muxl = container_obj(layr); > - u8 id; > - struct cflayer *up; > - if (cfpkt_extr_head(pkt, &id, 1) < 0) { > - pr_err("erroneous Caif Packet\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - rcu_read_lock(); > - up = get_up(muxl, id); > - > - if (up == NULL) { > - pr_debug("Received data on unknown link ID = %d (0x%x)" > - " up == NULL", id, id); > - cfpkt_destroy(pkt); > - /* > - * Don't return ERROR, since modem misbehaves and sends out > - * flow on before linksetup response. > - */ > - > - rcu_read_unlock(); > - return /* CFGLU_EPROT; */ 0; > - } > - > - /* We can't hold rcu_lock during receive, so take a ref count instead */ > - cfsrvl_get(up); > - rcu_read_unlock(); > - > - ret = up->receive(up, pkt); > - > - cfsrvl_put(up); > - return ret; > -} > - > -static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct cfmuxl *muxl = container_obj(layr); > - int err; > - u8 linkid; > - struct cflayer *dn; > - struct caif_payload_info *info = cfpkt_info(pkt); > - BUG_ON(!info); > - > - rcu_read_lock(); > - > - dn = get_dn(muxl, info->dev_info); > - if (dn == NULL) { > - pr_debug("Send data on unknown phy ID = %d (0x%x)\n", > - info->dev_info->id, info->dev_info->id); > - rcu_read_unlock(); > - cfpkt_destroy(pkt); > - return -ENOTCONN; > - } > - > - info->hdr_len += 1; > - linkid = info->channel_id; > - cfpkt_add_head(pkt, &linkid, 1); > - > - /* We can't hold rcu_lock during receive, so take a ref count instead */ > - cffrml_hold(dn); > - > - rcu_read_unlock(); > - > - err = dn->transmit(dn, pkt); > - > - cffrml_put(dn); > - return err; > -} > - > -static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - struct cfmuxl *muxl = container_obj(layr); > - struct cflayer *layer; > - > - rcu_read_lock(); > - list_for_each_entry_rcu(layer, &muxl->srvl_list, node) { > - > - if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) { > - > - if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND || > - ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && > - layer->id != 0) > - cfmuxl_remove_uplayer(layr, layer->id); > - > - /* NOTE: ctrlcmd is not allowed to block */ > - layer->ctrlcmd(layer, ctrl, phyid); > - } > - } > - rcu_read_unlock(); > -} > diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c > deleted file mode 100644 > index 96236d21b18e..000000000000 > --- a/net/caif/cfpkt_skbuff.c > +++ /dev/null > @@ -1,373 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > - > -#define PKT_PREFIX 48 > -#define PKT_POSTFIX 2 > -#define PKT_LEN_WHEN_EXTENDING 128 > -#define PKT_ERROR(pkt, errmsg) \ > -do { \ > - cfpkt_priv(pkt)->erronous = true; \ > - skb_reset_tail_pointer(&pkt->skb); \ > - pr_warn(errmsg); \ > -} while (0) > - > -/* > - * net/caif/ is generic and does not > - * understand SKB, so we do this typecast > - */ > -struct cfpkt { > - struct sk_buff skb; > -}; > - > -/* Private data inside SKB */ > -struct cfpkt_priv_data { > - struct dev_info dev_info; > - bool erronous; > -}; > - > -static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) > -{ > - return (struct cfpkt_priv_data *) pkt->skb.cb; > -} > - > -static inline bool is_erronous(struct cfpkt *pkt) > -{ > - return cfpkt_priv(pkt)->erronous; > -} > - > -static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) > -{ > - return &pkt->skb; > -} > - > -static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) > -{ > - return (struct cfpkt *) skb; > -} > - > -struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt) > -{ > - struct cfpkt *pkt = skb_to_pkt(nativepkt); > - cfpkt_priv(pkt)->erronous = false; > - return pkt; > -} > -EXPORT_SYMBOL(cfpkt_fromnative); > - > -void *cfpkt_tonative(struct cfpkt *pkt) > -{ > - return (void *) pkt; > -} > -EXPORT_SYMBOL(cfpkt_tonative); > - > -static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) > -{ > - struct sk_buff *skb; > - > - skb = alloc_skb(len + pfx, GFP_ATOMIC); > - if (unlikely(skb == NULL)) > - return NULL; > - > - skb_reserve(skb, pfx); > - return skb_to_pkt(skb); > -} > - > -inline struct cfpkt *cfpkt_create(u16 len) > -{ > - return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); > -} > - > -void cfpkt_destroy(struct cfpkt *pkt) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - kfree_skb(skb); > -} > - > -inline bool cfpkt_more(struct cfpkt *pkt) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - return skb->len > 0; > -} > - > -int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - if (skb_headlen(skb) >= len) { > - memcpy(data, skb->data, len); > - return 0; > - } > - return !cfpkt_extr_head(pkt, data, len) && > - !cfpkt_add_head(pkt, data, len); > -} > - > -int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - u8 *from; > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - > - if (unlikely(len > skb->len)) { > - PKT_ERROR(pkt, "read beyond end of packet\n"); > - return -EPROTO; > - } > - > - if (unlikely(len > skb_headlen(skb))) { > - if (unlikely(skb_linearize(skb) != 0)) { > - PKT_ERROR(pkt, "linearize failed\n"); > - return -EPROTO; > - } > - } > - from = skb_pull(skb, len); > - from -= len; > - if (data) > - memcpy(data, from, len); > - return 0; > -} > -EXPORT_SYMBOL(cfpkt_extr_head); > - > -int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - u8 *data = dta; > - u8 *from; > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - > - if (unlikely(skb_linearize(skb) != 0)) { > - PKT_ERROR(pkt, "linearize failed\n"); > - return -EPROTO; > - } > - if (unlikely(skb->data + len > skb_tail_pointer(skb))) { > - PKT_ERROR(pkt, "read beyond end of packet\n"); > - return -EPROTO; > - } > - from = skb_tail_pointer(skb) - len; > - skb_trim(skb, skb->len - len); > - memcpy(data, from, len); > - return 0; > -} > - > -int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) > -{ > - return cfpkt_add_body(pkt, NULL, len); > -} > - > -int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - struct sk_buff *lastskb; > - u8 *to; > - u16 addlen = 0; > - > - > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - > - lastskb = skb; > - > - /* Check whether we need to add space at the tail */ > - if (unlikely(skb_tailroom(skb) < len)) { > - if (likely(len < PKT_LEN_WHEN_EXTENDING)) > - addlen = PKT_LEN_WHEN_EXTENDING; > - else > - addlen = len; > - } > - > - /* Check whether we need to change the SKB before writing to the tail */ > - if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) { > - > - /* Make sure data is writable */ > - if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) { > - PKT_ERROR(pkt, "cow failed\n"); > - return -EPROTO; > - } > - } > - > - /* All set to put the last SKB and optionally write data there. */ > - to = pskb_put(skb, lastskb, len); > - if (likely(data)) > - memcpy(to, data, len); > - return 0; > -} > - > -inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) > -{ > - return cfpkt_add_body(pkt, &data, 1); > -} > - > -int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - struct sk_buff *lastskb; > - u8 *to; > - const u8 *data = data2; > - int ret; > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - if (unlikely(skb_headroom(skb) < len)) { > - PKT_ERROR(pkt, "no headroom\n"); > - return -EPROTO; > - } > - > - /* Make sure data is writable */ > - ret = skb_cow_data(skb, 0, &lastskb); > - if (unlikely(ret < 0)) { > - PKT_ERROR(pkt, "cow failed\n"); > - return ret; > - } > - > - to = skb_push(skb, len); > - memcpy(to, data, len); > - return 0; > -} > -EXPORT_SYMBOL(cfpkt_add_head); > - > -inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) > -{ > - return cfpkt_add_body(pkt, data, len); > -} > - > -inline u16 cfpkt_getlen(struct cfpkt *pkt) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - return skb->len; > -} > - > -int cfpkt_iterate(struct cfpkt *pkt, > - u16 (*iter_func)(u16, void *, u16), > - u16 data) > -{ > - /* > - * Don't care about the performance hit of linearizing, > - * Checksum should not be used on high-speed interfaces anyway. > - */ > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - if (unlikely(skb_linearize(&pkt->skb) != 0)) { > - PKT_ERROR(pkt, "linearize failed\n"); > - return -EPROTO; > - } > - return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); > -} > - > -int cfpkt_setlen(struct cfpkt *pkt, u16 len) > -{ > - struct sk_buff *skb = pkt_to_skb(pkt); > - > - > - if (unlikely(is_erronous(pkt))) > - return -EPROTO; > - > - if (likely(len <= skb->len)) { > - if (unlikely(skb->data_len)) > - ___pskb_trim(skb, len); > - else > - skb_trim(skb, len); > - > - return cfpkt_getlen(pkt); > - } > - > - /* Need to expand SKB */ > - if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len))) > - PKT_ERROR(pkt, "skb_pad_trail failed\n"); > - > - return cfpkt_getlen(pkt); > -} > - > -struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, > - struct cfpkt *addpkt, > - u16 expectlen) > -{ > - struct sk_buff *dst = pkt_to_skb(dstpkt); > - struct sk_buff *add = pkt_to_skb(addpkt); > - u16 addlen = skb_headlen(add); > - u16 neededtailspace; > - struct sk_buff *tmp; > - u16 dstlen; > - u16 createlen; > - if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) { > - return dstpkt; > - } > - > - neededtailspace = max(expectlen, addlen); > - > - if (dst->tail + neededtailspace > dst->end) { > - /* Create a dumplicate of 'dst' with more tail space */ > - struct cfpkt *tmppkt; > - dstlen = skb_headlen(dst); > - createlen = dstlen + neededtailspace; > - tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX); > - if (tmppkt == NULL) > - return NULL; > - tmp = pkt_to_skb(tmppkt); > - skb_put_data(tmp, dst->data, dstlen); > - cfpkt_destroy(dstpkt); > - dst = tmp; > - } > - skb_put_data(dst, add->data, skb_headlen(add)); > - cfpkt_destroy(addpkt); > - return skb_to_pkt(dst); > -} > - > -struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) > -{ > - struct sk_buff *skb2; > - struct sk_buff *skb = pkt_to_skb(pkt); > - struct cfpkt *tmppkt; > - u8 *split = skb->data + pos; > - u16 len2nd = skb_tail_pointer(skb) - split; > - > - if (unlikely(is_erronous(pkt))) > - return NULL; > - > - if (skb->data + pos > skb_tail_pointer(skb)) { > - PKT_ERROR(pkt, "trying to split beyond end of packet\n"); > - return NULL; > - } > - > - /* Create a new packet for the second part of the data */ > - tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX, > - PKT_PREFIX); > - if (tmppkt == NULL) > - return NULL; > - skb2 = pkt_to_skb(tmppkt); > - > - > - if (skb2 == NULL) > - return NULL; > - > - skb_put_data(skb2, split, len2nd); > - > - /* Reduce the length of the original packet */ > - skb_trim(skb, pos); > - > - skb2->priority = skb->priority; > - return skb_to_pkt(skb2); > -} > - > -bool cfpkt_erroneous(struct cfpkt *pkt) > -{ > - return cfpkt_priv(pkt)->erronous; > -} > - > -struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) > -{ > - return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; > -} > -EXPORT_SYMBOL(cfpkt_info); > - > -void cfpkt_set_prio(struct cfpkt *pkt, int prio) > -{ > - pkt_to_skb(pkt)->priority = prio; > -} > -EXPORT_SYMBOL(cfpkt_set_prio); > diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c > deleted file mode 100644 > index 93732ebbd1e2..000000000000 > --- a/net/caif/cfrfml.c > +++ /dev/null > @@ -1,299 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) container_of(layr, struct cfrfml, serv.layer) > -#define RFM_SEGMENTATION_BIT 0x01 > -#define RFM_HEAD_SIZE 7 > - > -static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cfrfml { > - struct cfsrvl serv; > - struct cfpkt *incomplete_frm; > - int fragment_size; > - u8 seghead[6]; > - u16 pdu_size; > - /* Protects serialized processing of packets */ > - spinlock_t sync; > -}; > - > -static void cfrfml_release(struct cflayer *layer) > -{ > - struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); > - struct cfrfml *rfml = container_obj(&srvl->layer); > - > - if (rfml->incomplete_frm) > - cfpkt_destroy(rfml->incomplete_frm); > - > - kfree(srvl); > -} > - > -struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info, > - int mtu_size) > -{ > - int tmp; > - struct cfrfml *this = kzalloc_obj(struct cfrfml, GFP_ATOMIC); > - > - if (!this) > - return NULL; > - > - cfsrvl_init(&this->serv, channel_id, dev_info, false); > - this->serv.release = cfrfml_release; > - this->serv.layer.receive = cfrfml_receive; > - this->serv.layer.transmit = cfrfml_transmit; > - > - /* Round down to closest multiple of 16 */ > - tmp = (mtu_size - RFM_HEAD_SIZE - 6) / 16; > - tmp *= 16; > - > - this->fragment_size = tmp; > - spin_lock_init(&this->sync); > - snprintf(this->serv.layer.name, CAIF_LAYER_NAME_SZ, > - "rfm%d", channel_id); > - > - return &this->serv.layer; > -} > - > -static struct cfpkt *rfm_append(struct cfrfml *rfml, char *seghead, > - struct cfpkt *pkt, int *err) > -{ > - struct cfpkt *tmppkt; > - *err = -EPROTO; > - /* n-th but not last segment */ > - > - if (cfpkt_extr_head(pkt, seghead, 6) < 0) > - return NULL; > - > - /* Verify correct header */ > - if (memcmp(seghead, rfml->seghead, 6) != 0) > - return NULL; > - > - tmppkt = cfpkt_append(rfml->incomplete_frm, pkt, > - rfml->pdu_size + RFM_HEAD_SIZE); > - > - /* If cfpkt_append failes input pkts are not freed */ > - *err = -ENOMEM; > - if (tmppkt == NULL) > - return NULL; > - > - *err = 0; > - return tmppkt; > -} > - > -static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 tmp; > - bool segmented; > - int err; > - u8 seghead[6]; > - struct cfrfml *rfml; > - struct cfpkt *tmppkt = NULL; > - > - caif_assert(layr->up != NULL); > - caif_assert(layr->receive != NULL); > - rfml = container_obj(layr); > - spin_lock(&rfml->sync); > - > - err = -EPROTO; > - if (cfpkt_extr_head(pkt, &tmp, 1) < 0) > - goto out; > - segmented = tmp & RFM_SEGMENTATION_BIT; > - > - if (segmented) { > - if (rfml->incomplete_frm == NULL) { > - /* Initial Segment */ > - if (cfpkt_peek_head(pkt, rfml->seghead, 6) != 0) > - goto out; > - > - rfml->pdu_size = get_unaligned_le16(rfml->seghead+4); > - > - if (cfpkt_erroneous(pkt)) > - goto out; > - rfml->incomplete_frm = pkt; > - pkt = NULL; > - } else { > - > - tmppkt = rfm_append(rfml, seghead, pkt, &err); > - if (tmppkt == NULL) > - goto out; > - > - if (cfpkt_erroneous(tmppkt)) > - goto out; > - > - rfml->incomplete_frm = tmppkt; > - > - > - if (cfpkt_erroneous(tmppkt)) > - goto out; > - } > - err = 0; > - goto out; > - } > - > - if (rfml->incomplete_frm) { > - > - /* Last Segment */ > - tmppkt = rfm_append(rfml, seghead, pkt, &err); > - if (tmppkt == NULL) > - goto out; > - > - if (cfpkt_erroneous(tmppkt)) > - goto out; > - > - rfml->incomplete_frm = NULL; > - pkt = tmppkt; > - tmppkt = NULL; > - > - /* Verify that length is correct */ > - err = -EPROTO; > - if (rfml->pdu_size != cfpkt_getlen(pkt) - RFM_HEAD_SIZE + 1) > - goto out; > - } > - > - err = rfml->serv.layer.up->receive(rfml->serv.layer.up, pkt); > - > -out: > - > - if (err != 0) { > - if (tmppkt) > - cfpkt_destroy(tmppkt); > - if (pkt) > - cfpkt_destroy(pkt); > - if (rfml->incomplete_frm) > - cfpkt_destroy(rfml->incomplete_frm); > - rfml->incomplete_frm = NULL; > - > - pr_info("Connection error %d triggered on RFM link\n", err); > - > - /* Trigger connection error upon failure.*/ > - layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, > - rfml->serv.dev_info.id); > - } > - spin_unlock(&rfml->sync); > - > - if (unlikely(err == -EAGAIN)) > - /* It is not possible to recover after drop of a fragment */ > - err = -EIO; > - > - return err; > -} > - > - > -static int cfrfml_transmit_segment(struct cfrfml *rfml, struct cfpkt *pkt) > -{ > - caif_assert(cfpkt_getlen(pkt) < rfml->fragment_size + RFM_HEAD_SIZE); > - > - /* Add info for MUX-layer to route the packet out. */ > - cfpkt_info(pkt)->channel_id = rfml->serv.layer.id; > - > - /* > - * To optimize alignment, we add up the size of CAIF header before > - * payload. > - */ > - cfpkt_info(pkt)->hdr_len = RFM_HEAD_SIZE; > - cfpkt_info(pkt)->dev_info = &rfml->serv.dev_info; > - > - return rfml->serv.layer.dn->transmit(rfml->serv.layer.dn, pkt); > -} > - > -static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - int err; > - u8 seg; > - u8 head[6]; > - struct cfpkt *rearpkt = NULL; > - struct cfpkt *frontpkt = pkt; > - struct cfrfml *rfml = container_obj(layr); > - > - caif_assert(layr->dn != NULL); > - caif_assert(layr->dn->transmit != NULL); > - > - if (!cfsrvl_ready(&rfml->serv, &err)) > - goto out; > - > - err = -EPROTO; > - if (cfpkt_getlen(pkt) <= RFM_HEAD_SIZE-1) > - goto out; > - > - err = 0; > - if (cfpkt_getlen(pkt) > rfml->fragment_size + RFM_HEAD_SIZE) > - err = cfpkt_peek_head(pkt, head, 6); > - > - if (err != 0) > - goto out; > - > - while (cfpkt_getlen(frontpkt) > rfml->fragment_size + RFM_HEAD_SIZE) { > - > - seg = 1; > - err = -EPROTO; > - > - if (cfpkt_add_head(frontpkt, &seg, 1) < 0) > - goto out; > - /* > - * On OOM error cfpkt_split returns NULL. > - * > - * NOTE: Segmented pdu is not correctly aligned. > - * This has negative performance impact. > - */ > - > - rearpkt = cfpkt_split(frontpkt, rfml->fragment_size); > - if (rearpkt == NULL) > - goto out; > - > - err = cfrfml_transmit_segment(rfml, frontpkt); > - > - if (err != 0) { > - frontpkt = NULL; > - goto out; > - } > - > - frontpkt = rearpkt; > - rearpkt = NULL; > - > - err = -EPROTO; > - if (cfpkt_add_head(frontpkt, head, 6) < 0) > - goto out; > - > - } > - > - seg = 0; > - err = -EPROTO; > - > - if (cfpkt_add_head(frontpkt, &seg, 1) < 0) > - goto out; > - > - err = cfrfml_transmit_segment(rfml, frontpkt); > - > - frontpkt = NULL; > -out: > - > - if (err != 0) { > - pr_info("Connection error %d triggered on RFM link\n", err); > - /* Trigger connection error upon failure.*/ > - > - layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, > - rfml->serv.dev_info.id); > - > - if (rearpkt) > - cfpkt_destroy(rearpkt); > - > - if (frontpkt) > - cfpkt_destroy(frontpkt); > - } > - > - return err; > -} > diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c > deleted file mode 100644 > index faf78fb754e2..000000000000 > --- a/net/caif/cfserl.c > +++ /dev/null > @@ -1,192 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) ((struct cfserl *) layr) > - > -#define CFSERL_STX 0x02 > -#define SERIAL_MINIUM_PACKET_SIZE 4 > -#define SERIAL_MAX_FRAMESIZE 4096 > -struct cfserl { > - struct cflayer layer; > - struct cfpkt *incomplete_frm; > - /* Protects parallel processing of incoming packets */ > - spinlock_t sync; > - bool usestx; > -}; > - > -static int cfserl_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt); > -static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid); > - > -void cfserl_release(struct cflayer *layer) > -{ > - kfree(layer); > -} > - > -struct cflayer *cfserl_create(int instance, bool use_stx) > -{ > - struct cfserl *this = kzalloc_obj(struct cfserl, GFP_ATOMIC); > - if (!this) > - return NULL; > - caif_assert(offsetof(struct cfserl, layer) == 0); > - this->layer.receive = cfserl_receive; > - this->layer.transmit = cfserl_transmit; > - this->layer.ctrlcmd = cfserl_ctrlcmd; > - this->usestx = use_stx; > - spin_lock_init(&this->sync); > - snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "ser1"); > - return &this->layer; > -} > - > -static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) > -{ > - struct cfserl *layr = container_obj(l); > - u16 pkt_len; > - struct cfpkt *pkt = NULL; > - struct cfpkt *tail_pkt = NULL; > - u8 tmp8; > - u16 tmp; > - u8 stx = CFSERL_STX; > - int ret; > - u16 expectlen = 0; > - > - caif_assert(newpkt != NULL); > - spin_lock(&layr->sync); > - > - if (layr->incomplete_frm != NULL) { > - layr->incomplete_frm = > - cfpkt_append(layr->incomplete_frm, newpkt, expectlen); > - pkt = layr->incomplete_frm; > - if (pkt == NULL) { > - spin_unlock(&layr->sync); > - return -ENOMEM; > - } > - } else { > - pkt = newpkt; > - } > - layr->incomplete_frm = NULL; > - > - do { > - /* Search for STX at start of pkt if STX is used */ > - if (layr->usestx) { > - cfpkt_extr_head(pkt, &tmp8, 1); > - if (tmp8 != CFSERL_STX) { > - while (cfpkt_more(pkt) > - && tmp8 != CFSERL_STX) { > - cfpkt_extr_head(pkt, &tmp8, 1); > - } > - if (!cfpkt_more(pkt)) { > - cfpkt_destroy(pkt); > - layr->incomplete_frm = NULL; > - spin_unlock(&layr->sync); > - return -EPROTO; > - } > - } > - } > - > - pkt_len = cfpkt_getlen(pkt); > - > - /* > - * pkt_len is the accumulated length of the packet data > - * we have received so far. > - * Exit if frame doesn't hold length. > - */ > - > - if (pkt_len < 2) { > - if (layr->usestx) > - cfpkt_add_head(pkt, &stx, 1); > - layr->incomplete_frm = pkt; > - spin_unlock(&layr->sync); > - return 0; > - } > - > - /* > - * Find length of frame. > - * expectlen is the length we need for a full frame. > - */ > - cfpkt_peek_head(pkt, &tmp, 2); > - expectlen = le16_to_cpu(tmp) + 2; > - /* > - * Frame error handling > - */ > - if (expectlen < SERIAL_MINIUM_PACKET_SIZE > - || expectlen > SERIAL_MAX_FRAMESIZE) { > - if (!layr->usestx) { > - if (pkt != NULL) > - cfpkt_destroy(pkt); > - layr->incomplete_frm = NULL; > - spin_unlock(&layr->sync); > - return -EPROTO; > - } > - continue; > - } > - > - if (pkt_len < expectlen) { > - /* Too little received data */ > - if (layr->usestx) > - cfpkt_add_head(pkt, &stx, 1); > - layr->incomplete_frm = pkt; > - spin_unlock(&layr->sync); > - return 0; > - } > - > - /* > - * Enough data for at least one frame. > - * Split the frame, if too long > - */ > - if (pkt_len > expectlen) > - tail_pkt = cfpkt_split(pkt, expectlen); > - else > - tail_pkt = NULL; > - > - /* Send the first part of packet upwards.*/ > - spin_unlock(&layr->sync); > - ret = layr->layer.up->receive(layr->layer.up, pkt); > - spin_lock(&layr->sync); > - if (ret == -EILSEQ) { > - if (layr->usestx) { > - if (tail_pkt != NULL) > - pkt = cfpkt_append(pkt, tail_pkt, 0); > - /* Start search for next STX if frame failed */ > - continue; > - } else { > - cfpkt_destroy(pkt); > - pkt = NULL; > - } > - } > - > - pkt = tail_pkt; > - > - } while (pkt != NULL); > - > - spin_unlock(&layr->sync); > - return 0; > -} > - > -static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) > -{ > - struct cfserl *layr = container_obj(layer); > - u8 tmp8 = CFSERL_STX; > - if (layr->usestx) > - cfpkt_add_head(newpkt, &tmp8, 1); > - return layer->dn->transmit(layer->dn, newpkt); > -} > - > -static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - layr->up->ctrlcmd(layr->up, ctrl, phyid); > -} > diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c > deleted file mode 100644 > index d687fd0b4ed3..000000000000 > --- a/net/caif/cfsrvl.c > +++ /dev/null > @@ -1,224 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define SRVL_CTRL_PKT_SIZE 1 > -#define SRVL_FLOW_OFF 0x81 > -#define SRVL_FLOW_ON 0x80 > -#define SRVL_SET_PIN 0x82 > - > -#define container_obj(layr) container_of(layr, struct cfsrvl, layer) > - > -static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, > - int phyid) > -{ > - struct cfsrvl *service = container_obj(layr); > - > - if (layr->up == NULL || layr->up->ctrlcmd == NULL) > - return; > - > - switch (ctrl) { > - case CAIF_CTRLCMD_INIT_RSP: > - service->open = true; > - layr->up->ctrlcmd(layr->up, ctrl, phyid); > - break; > - case CAIF_CTRLCMD_DEINIT_RSP: > - case CAIF_CTRLCMD_INIT_FAIL_RSP: > - service->open = false; > - layr->up->ctrlcmd(layr->up, ctrl, phyid); > - break; > - case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: > - if (phyid != service->dev_info.id) > - break; > - if (service->modem_flow_on) > - layr->up->ctrlcmd(layr->up, > - CAIF_CTRLCMD_FLOW_OFF_IND, phyid); > - service->phy_flow_on = false; > - break; > - case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: > - if (phyid != service->dev_info.id) > - return; > - if (service->modem_flow_on) { > - layr->up->ctrlcmd(layr->up, > - CAIF_CTRLCMD_FLOW_ON_IND, > - phyid); > - } > - service->phy_flow_on = true; > - break; > - case CAIF_CTRLCMD_FLOW_OFF_IND: > - if (service->phy_flow_on) { > - layr->up->ctrlcmd(layr->up, > - CAIF_CTRLCMD_FLOW_OFF_IND, phyid); > - } > - service->modem_flow_on = false; > - break; > - case CAIF_CTRLCMD_FLOW_ON_IND: > - if (service->phy_flow_on) { > - layr->up->ctrlcmd(layr->up, > - CAIF_CTRLCMD_FLOW_ON_IND, phyid); > - } > - service->modem_flow_on = true; > - break; > - case _CAIF_CTRLCMD_PHYIF_DOWN_IND: > - /* In case interface is down, let's fake a remove shutdown */ > - layr->up->ctrlcmd(layr->up, > - CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid); > - break; > - case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: > - layr->up->ctrlcmd(layr->up, ctrl, phyid); > - break; > - default: > - pr_warn("Unexpected ctrl in cfsrvl (%d)\n", ctrl); > - /* We have both modem and phy flow on, send flow on */ > - layr->up->ctrlcmd(layr->up, ctrl, phyid); > - service->phy_flow_on = true; > - break; > - } > -} > - > -static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) > -{ > - struct cfsrvl *service = container_obj(layr); > - > - caif_assert(layr != NULL); > - caif_assert(layr->dn != NULL); > - caif_assert(layr->dn->transmit != NULL); > - > - if (!service->supports_flowctrl) > - return 0; > - > - switch (ctrl) { > - case CAIF_MODEMCMD_FLOW_ON_REQ: > - { > - struct cfpkt *pkt; > - struct caif_payload_info *info; > - u8 flow_on = SRVL_FLOW_ON; > - pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); > - if (!pkt) > - return -ENOMEM; > - > - if (cfpkt_add_head(pkt, &flow_on, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - info->hdr_len = 1; > - info->dev_info = &service->dev_info; > - cfpkt_set_prio(pkt, TC_PRIO_CONTROL); > - return layr->dn->transmit(layr->dn, pkt); > - } > - case CAIF_MODEMCMD_FLOW_OFF_REQ: > - { > - struct cfpkt *pkt; > - struct caif_payload_info *info; > - u8 flow_off = SRVL_FLOW_OFF; > - pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); > - if (!pkt) > - return -ENOMEM; > - > - if (cfpkt_add_head(pkt, &flow_off, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - info->hdr_len = 1; > - info->dev_info = &service->dev_info; > - cfpkt_set_prio(pkt, TC_PRIO_CONTROL); > - return layr->dn->transmit(layr->dn, pkt); > - } > - default: > - break; > - } > - return -EINVAL; > -} > - > -static void cfsrvl_release(struct cflayer *layer) > -{ > - struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); > - kfree(service); > -} > - > -void cfsrvl_init(struct cfsrvl *service, > - u8 channel_id, > - struct dev_info *dev_info, > - bool supports_flowctrl) > -{ > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - service->open = false; > - service->modem_flow_on = true; > - service->phy_flow_on = true; > - service->layer.id = channel_id; > - service->layer.ctrlcmd = cfservl_ctrlcmd; > - service->layer.modemcmd = cfservl_modemcmd; > - service->dev_info = *dev_info; > - service->supports_flowctrl = supports_flowctrl; > - service->release = cfsrvl_release; > -} > - > -bool cfsrvl_ready(struct cfsrvl *service, int *err) > -{ > - if (!service->open) { > - *err = -ENOTCONN; > - return false; > - } > - return true; > -} > - > -bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) > -{ > - struct cfsrvl *servl = container_obj(layer); > - return servl->dev_info.id == phyid; > -} > - > -void caif_free_client(struct cflayer *adap_layer) > -{ > - struct cflayer *serv_layer; > - struct cfsrvl *servl; > - > - if (!adap_layer) > - return; > - > - serv_layer = adap_layer->dn; > - if (!serv_layer) > - return; > - > - layer_set_dn(adap_layer, NULL); > - layer_set_up(serv_layer, NULL); > - > - servl = container_obj(serv_layer); > - servl->release(&servl->layer); > -} > -EXPORT_SYMBOL(caif_free_client); > - > -void caif_client_register_refcnt(struct cflayer *adapt_layer, > - void (*hold)(struct cflayer *lyr), > - void (*put)(struct cflayer *lyr)) > -{ > - struct cfsrvl *service; > - > - if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL)) > - return; > - service = container_of(adapt_layer->dn, struct cfsrvl, layer); > - service->hold = hold; > - service->put = put; > -} > -EXPORT_SYMBOL(caif_client_register_refcnt); > diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c > deleted file mode 100644 > index 5111090bb2c0..000000000000 > --- a/net/caif/cfutill.c > +++ /dev/null > @@ -1,104 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) ((struct cfsrvl *) layr) > -#define UTIL_PAYLOAD 0x00 > -#define UTIL_CMD_BIT 0x80 > -#define UTIL_REMOTE_SHUTDOWN 0x82 > -#define UTIL_FLOW_OFF 0x81 > -#define UTIL_FLOW_ON 0x80 > - > -static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info) > -{ > - struct cfsrvl *util = kzalloc_obj(struct cfsrvl, GFP_ATOMIC); > - if (!util) > - return NULL; > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - cfsrvl_init(util, channel_id, dev_info, true); > - util->layer.receive = cfutill_receive; > - util->layer.transmit = cfutill_transmit; > - snprintf(util->layer.name, CAIF_LAYER_NAME_SZ, "util1"); > - return &util->layer; > -} > - > -static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 cmd = -1; > - struct cfsrvl *service = container_obj(layr); > - caif_assert(layr != NULL); > - caif_assert(layr->up != NULL); > - caif_assert(layr->up->receive != NULL); > - caif_assert(layr->up->ctrlcmd != NULL); > - if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - > - switch (cmd) { > - case UTIL_PAYLOAD: > - return layr->up->receive(layr->up, pkt); > - case UTIL_FLOW_OFF: > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - case UTIL_FLOW_ON: > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - case UTIL_REMOTE_SHUTDOWN: /* Remote Shutdown Request */ > - pr_err("REMOTE SHUTDOWN REQUEST RECEIVED\n"); > - layr->ctrlcmd(layr, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, 0); > - service->open = false; > - cfpkt_destroy(pkt); > - return 0; > - default: > - cfpkt_destroy(pkt); > - pr_warn("Unknown service control %d (0x%x)\n", cmd, cmd); > - return -EPROTO; > - } > -} > - > -static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 zero = 0; > - struct caif_payload_info *info; > - int ret; > - struct cfsrvl *service = container_obj(layr); > - caif_assert(layr != NULL); > - caif_assert(layr->dn != NULL); > - caif_assert(layr->dn->transmit != NULL); > - > - if (!cfsrvl_ready(service, &ret)) { > - cfpkt_destroy(pkt); > - return ret; > - } > - > - cfpkt_add_head(pkt, &zero, 1); > - /* Add info for MUX-layer to route the packet out. */ > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - /* > - * To optimize alignment, we add up the size of CAIF header before > - * payload. > - */ > - info->hdr_len = 1; > - info->dev_info = &service->dev_info; > - return layr->dn->transmit(layr->dn, pkt); > -} > diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c > deleted file mode 100644 > index 53f844c49bbb..000000000000 > --- a/net/caif/cfveil.c > +++ /dev/null > @@ -1,101 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > - > -#define VEI_PAYLOAD 0x00 > -#define VEI_CMD_BIT 0x80 > -#define VEI_FLOW_OFF 0x81 > -#define VEI_FLOW_ON 0x80 > -#define VEI_SET_PIN 0x82 > - > -#define container_obj(layr) container_of(layr, struct cfsrvl, layer) > - > -static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cflayer *cfvei_create(u8 channel_id, struct dev_info *dev_info) > -{ > - struct cfsrvl *vei = kzalloc_obj(struct cfsrvl, GFP_ATOMIC); > - if (!vei) > - return NULL; > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - cfsrvl_init(vei, channel_id, dev_info, true); > - vei->layer.receive = cfvei_receive; > - vei->layer.transmit = cfvei_transmit; > - snprintf(vei->layer.name, CAIF_LAYER_NAME_SZ, "vei%d", channel_id); > - return &vei->layer; > -} > - > -static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 cmd; > - int ret; > - caif_assert(layr->up != NULL); > - caif_assert(layr->receive != NULL); > - caif_assert(layr->ctrlcmd != NULL); > - > - > - if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - switch (cmd) { > - case VEI_PAYLOAD: > - ret = layr->up->receive(layr->up, pkt); > - return ret; > - case VEI_FLOW_OFF: > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - case VEI_FLOW_ON: > - layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); > - cfpkt_destroy(pkt); > - return 0; > - case VEI_SET_PIN: /* SET RS232 PIN */ > - cfpkt_destroy(pkt); > - return 0; > - default: /* SET RS232 PIN */ > - pr_warn("Unknown VEI control packet %d (0x%x)!\n", cmd, cmd); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > -} > - > -static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u8 tmp = 0; > - struct caif_payload_info *info; > - int ret; > - struct cfsrvl *service = container_obj(layr); > - if (!cfsrvl_ready(service, &ret)) > - goto err; > - caif_assert(layr->dn != NULL); > - caif_assert(layr->dn->transmit != NULL); > - > - if (cfpkt_add_head(pkt, &tmp, 1) < 0) { > - pr_err("Packet is erroneous!\n"); > - ret = -EPROTO; > - goto err; > - } > - > - /* Add info-> for MUX-layer to route the packet out. */ > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - info->hdr_len = 1; > - info->dev_info = &service->dev_info; > - return layr->dn->transmit(layr->dn, pkt); > -err: > - cfpkt_destroy(pkt); > - return ret; > -} > diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c > deleted file mode 100644 > index 39e075b0a259..000000000000 > --- a/net/caif/cfvidl.c > +++ /dev/null > @@ -1,65 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Author: Sjur Brendeland > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#define container_obj(layr) ((struct cfsrvl *) layr) > - > -static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt); > -static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt); > - > -struct cflayer *cfvidl_create(u8 channel_id, struct dev_info *dev_info) > -{ > - struct cfsrvl *vid = kzalloc_obj(struct cfsrvl, GFP_ATOMIC); > - if (!vid) > - return NULL; > - caif_assert(offsetof(struct cfsrvl, layer) == 0); > - > - cfsrvl_init(vid, channel_id, dev_info, false); > - vid->layer.receive = cfvidl_receive; > - vid->layer.transmit = cfvidl_transmit; > - snprintf(vid->layer.name, CAIF_LAYER_NAME_SZ, "vid1"); > - return &vid->layer; > -} > - > -static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt) > -{ > - u32 videoheader; > - if (cfpkt_extr_head(pkt, &videoheader, 4) < 0) { > - pr_err("Packet is erroneous!\n"); > - cfpkt_destroy(pkt); > - return -EPROTO; > - } > - return layr->up->receive(layr->up, pkt); > -} > - > -static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct cfsrvl *service = container_obj(layr); > - struct caif_payload_info *info; > - u32 videoheader = 0; > - int ret; > - > - if (!cfsrvl_ready(service, &ret)) { > - cfpkt_destroy(pkt); > - return ret; > - } > - > - cfpkt_add_head(pkt, &videoheader, 4); > - /* Add info for MUX-layer to route the packet out */ > - info = cfpkt_info(pkt); > - info->channel_id = service->layer.id; > - info->dev_info = &service->dev_info; > - return layr->dn->transmit(layr->dn, pkt); > -} > diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c > deleted file mode 100644 > index fa6a3c2634a8..000000000000 > --- a/net/caif/chnl_net.c > +++ /dev/null > @@ -1,531 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright (C) ST-Ericsson AB 2010 > - * Authors: Sjur Brendeland > - * Daniel Martensson > - */ > - > -#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ > - > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -/* GPRS PDP connection has MTU to 1500 */ > -#define GPRS_PDP_MTU 1500 > -/* 5 sec. connect timeout */ > -#define CONNECT_TIMEOUT (5 * HZ) > -#define CAIF_NET_DEFAULT_QUEUE_LEN 500 > -#define UNDEF_CONNID 0xffffffff > - > -/*This list is protected by the rtnl lock. */ > -static LIST_HEAD(chnl_net_list); > - > -MODULE_DESCRIPTION("ST-Ericsson CAIF modem protocol GPRS network device"); > -MODULE_LICENSE("GPL"); > -MODULE_ALIAS_RTNL_LINK("caif"); > - > -enum caif_states { > - CAIF_CONNECTED = 1, > - CAIF_CONNECTING, > - CAIF_DISCONNECTED, > - CAIF_SHUTDOWN > -}; > - > -struct chnl_net { > - struct cflayer chnl; > - struct caif_connect_request conn_req; > - struct list_head list_field; > - struct net_device *netdev; > - wait_queue_head_t netmgmt_wq; > - /* Flow status to remember and control the transmission. */ > - bool flowenabled; > - enum caif_states state; > -}; > - > -static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) > -{ > - struct sk_buff *skb; > - struct chnl_net *priv; > - int pktlen; > - const u8 *ip_version; > - u8 buf; > - > - priv = container_of(layr, struct chnl_net, chnl); > - > - skb = (struct sk_buff *) cfpkt_tonative(pkt); > - > - /* Get length of CAIF packet. */ > - pktlen = skb->len; > - > - /* Pass some minimum information and > - * send the packet to the net stack. > - */ > - skb->dev = priv->netdev; > - > - /* check the version of IP */ > - ip_version = skb_header_pointer(skb, 0, 1, &buf); > - if (!ip_version) { > - kfree_skb(skb); > - return -EINVAL; > - } > - > - switch (*ip_version >> 4) { > - case 4: > - skb->protocol = htons(ETH_P_IP); > - break; > - case 6: > - skb->protocol = htons(ETH_P_IPV6); > - break; > - default: > - kfree_skb(skb); > - priv->netdev->stats.rx_errors++; > - return -EINVAL; > - } > - > - /* If we change the header in loop mode, the checksum is corrupted. */ > - if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP) > - skb->ip_summed = CHECKSUM_UNNECESSARY; > - else > - skb->ip_summed = CHECKSUM_NONE; > - > - netif_rx(skb); > - > - /* Update statistics. */ > - priv->netdev->stats.rx_packets++; > - priv->netdev->stats.rx_bytes += pktlen; > - > - return 0; > -} > - > -static int delete_device(struct chnl_net *dev) > -{ > - ASSERT_RTNL(); > - if (dev->netdev) > - unregister_netdevice(dev->netdev); > - return 0; > -} > - > -static void close_work(struct work_struct *work) > -{ > - struct chnl_net *dev = NULL; > - struct list_head *list_node; > - struct list_head *_tmp; > - > - rtnl_lock(); > - list_for_each_safe(list_node, _tmp, &chnl_net_list) { > - dev = list_entry(list_node, struct chnl_net, list_field); > - if (dev->state == CAIF_SHUTDOWN) > - dev_close(dev->netdev); > - } > - rtnl_unlock(); > -} > -static DECLARE_WORK(close_worker, close_work); > - > -static void chnl_hold(struct cflayer *lyr) > -{ > - struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); > - dev_hold(priv->netdev); > -} > - > -static void chnl_put(struct cflayer *lyr) > -{ > - struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); > - dev_put(priv->netdev); > -} > - > -static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, > - int phyid) > -{ > - struct chnl_net *priv = container_of(layr, struct chnl_net, chnl); > - pr_debug("NET flowctrl func called flow: %s\n", > - flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" : > - flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" : > - flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" : > - flow == CAIF_CTRLCMD_DEINIT_RSP ? "CLOSE/DEINIT" : > - flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "OPEN_FAIL" : > - flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? > - "REMOTE_SHUTDOWN" : "UNKNOWN CTRL COMMAND"); > - > - > - > - switch (flow) { > - case CAIF_CTRLCMD_FLOW_OFF_IND: > - priv->flowenabled = false; > - netif_stop_queue(priv->netdev); > - break; > - case CAIF_CTRLCMD_DEINIT_RSP: > - priv->state = CAIF_DISCONNECTED; > - break; > - case CAIF_CTRLCMD_INIT_FAIL_RSP: > - priv->state = CAIF_DISCONNECTED; > - wake_up_interruptible(&priv->netmgmt_wq); > - break; > - case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: > - priv->state = CAIF_SHUTDOWN; > - netif_tx_disable(priv->netdev); > - schedule_work(&close_worker); > - break; > - case CAIF_CTRLCMD_FLOW_ON_IND: > - priv->flowenabled = true; > - netif_wake_queue(priv->netdev); > - break; > - case CAIF_CTRLCMD_INIT_RSP: > - caif_client_register_refcnt(&priv->chnl, chnl_hold, chnl_put); > - priv->state = CAIF_CONNECTED; > - priv->flowenabled = true; > - netif_wake_queue(priv->netdev); > - wake_up_interruptible(&priv->netmgmt_wq); > - break; > - default: > - break; > - } > -} > - > -static netdev_tx_t chnl_net_start_xmit(struct sk_buff *skb, > - struct net_device *dev) > -{ > - struct chnl_net *priv; > - struct cfpkt *pkt = NULL; > - int len; > - int result = -1; > - /* Get our private data. */ > - priv = netdev_priv(dev); > - > - if (skb->len > priv->netdev->mtu) { > - pr_warn("Size of skb exceeded MTU\n"); > - kfree_skb(skb); > - dev->stats.tx_errors++; > - return NETDEV_TX_OK; > - } > - > - if (!priv->flowenabled) { > - pr_debug("dropping packets flow off\n"); > - kfree_skb(skb); > - dev->stats.tx_dropped++; > - return NETDEV_TX_OK; > - } > - > - if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP) > - swap(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); > - > - /* Store original SKB length. */ > - len = skb->len; > - > - pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb); > - > - /* Send the packet down the stack. */ > - result = priv->chnl.dn->transmit(priv->chnl.dn, pkt); > - if (result) { > - dev->stats.tx_dropped++; > - return NETDEV_TX_OK; > - } > - > - /* Update statistics. */ > - dev->stats.tx_packets++; > - dev->stats.tx_bytes += len; > - > - return NETDEV_TX_OK; > -} > - > -static int chnl_net_open(struct net_device *dev) > -{ > - struct chnl_net *priv = NULL; > - int result = -1; > - int llifindex, headroom, tailroom, mtu; > - struct net_device *lldev; > - ASSERT_RTNL(); > - priv = netdev_priv(dev); > - if (!priv) { > - pr_debug("chnl_net_open: no priv\n"); > - return -ENODEV; > - } > - > - if (priv->state != CAIF_CONNECTING) { > - priv->state = CAIF_CONNECTING; > - result = caif_connect_client(dev_net(dev), &priv->conn_req, > - &priv->chnl, &llifindex, > - &headroom, &tailroom); > - if (result != 0) { > - pr_debug("err: " > - "Unable to register and open device," > - " Err:%d\n", > - result); > - goto error; > - } > - > - lldev = __dev_get_by_index(dev_net(dev), llifindex); > - > - if (lldev == NULL) { > - pr_debug("no interface?\n"); > - result = -ENODEV; > - goto error; > - } > - > - dev->needed_tailroom = tailroom + lldev->needed_tailroom; > - dev->hard_header_len = headroom + lldev->hard_header_len + > - lldev->needed_tailroom; > - > - /* > - * MTU, head-room etc is not know before we have a > - * CAIF link layer device available. MTU calculation may > - * override initial RTNL configuration. > - * MTU is minimum of current mtu, link layer mtu pluss > - * CAIF head and tail, and PDP GPRS contexts max MTU. > - */ > - mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom)); > - mtu = min_t(int, GPRS_PDP_MTU, mtu); > - dev_set_mtu(dev, mtu); > - > - if (mtu < 100) { > - pr_warn("CAIF Interface MTU too small (%d)\n", mtu); > - result = -ENODEV; > - goto error; > - } > - } > - > - rtnl_unlock(); /* Release RTNL lock during connect wait */ > - > - result = wait_event_interruptible_timeout(priv->netmgmt_wq, > - priv->state != CAIF_CONNECTING, > - CONNECT_TIMEOUT); > - > - rtnl_lock(); > - > - if (result == -ERESTARTSYS) { > - pr_debug("wait_event_interruptible woken by a signal\n"); > - result = -ERESTARTSYS; > - goto error; > - } > - > - if (result == 0) { > - pr_debug("connect timeout\n"); > - result = -ETIMEDOUT; > - goto error; > - } > - > - if (priv->state != CAIF_CONNECTED) { > - pr_debug("connect failed\n"); > - result = -ECONNREFUSED; > - goto error; > - } > - pr_debug("CAIF Netdevice connected\n"); > - return 0; > - > -error: > - caif_disconnect_client(dev_net(dev), &priv->chnl); > - priv->state = CAIF_DISCONNECTED; > - pr_debug("state disconnected\n"); > - return result; > - > -} > - > -static int chnl_net_stop(struct net_device *dev) > -{ > - struct chnl_net *priv; > - > - ASSERT_RTNL(); > - priv = netdev_priv(dev); > - priv->state = CAIF_DISCONNECTED; > - caif_disconnect_client(dev_net(dev), &priv->chnl); > - return 0; > -} > - > -static int chnl_net_init(struct net_device *dev) > -{ > - struct chnl_net *priv; > - ASSERT_RTNL(); > - priv = netdev_priv(dev); > - INIT_LIST_HEAD(&priv->list_field); > - return 0; > -} > - > -static void chnl_net_uninit(struct net_device *dev) > -{ > - struct chnl_net *priv; > - ASSERT_RTNL(); > - priv = netdev_priv(dev); > - list_del_init(&priv->list_field); > -} > - > -static const struct net_device_ops netdev_ops = { > - .ndo_open = chnl_net_open, > - .ndo_stop = chnl_net_stop, > - .ndo_init = chnl_net_init, > - .ndo_uninit = chnl_net_uninit, > - .ndo_start_xmit = chnl_net_start_xmit, > -}; > - > -static void chnl_net_destructor(struct net_device *dev) > -{ > - struct chnl_net *priv = netdev_priv(dev); > - caif_free_client(&priv->chnl); > -} > - > -static void ipcaif_net_setup(struct net_device *dev) > -{ > - struct chnl_net *priv; > - dev->netdev_ops = &netdev_ops; > - dev->needs_free_netdev = true; > - dev->priv_destructor = chnl_net_destructor; > - dev->flags |= IFF_NOARP; > - dev->flags |= IFF_POINTOPOINT; > - dev->mtu = GPRS_PDP_MTU; > - dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; > - > - priv = netdev_priv(dev); > - priv->chnl.receive = chnl_recv_cb; > - priv->chnl.ctrlcmd = chnl_flowctrl_cb; > - priv->netdev = dev; > - priv->conn_req.protocol = CAIFPROTO_DATAGRAM; > - priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; > - priv->conn_req.priority = CAIF_PRIO_LOW; > - /* Insert illegal value */ > - priv->conn_req.sockaddr.u.dgm.connection_id = UNDEF_CONNID; > - priv->flowenabled = false; > - > - init_waitqueue_head(&priv->netmgmt_wq); > -} > - > - > -static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev) > -{ > - struct chnl_net *priv; > - u8 loop; > - priv = netdev_priv(dev); > - if (nla_put_u32(skb, IFLA_CAIF_IPV4_CONNID, > - priv->conn_req.sockaddr.u.dgm.connection_id) || > - nla_put_u32(skb, IFLA_CAIF_IPV6_CONNID, > - priv->conn_req.sockaddr.u.dgm.connection_id)) > - goto nla_put_failure; > - loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP; > - if (nla_put_u8(skb, IFLA_CAIF_LOOPBACK, loop)) > - goto nla_put_failure; > - return 0; > -nla_put_failure: > - return -EMSGSIZE; > - > -} > - > -static void caif_netlink_parms(struct nlattr *data[], > - struct caif_connect_request *conn_req) > -{ > - if (!data) { > - pr_warn("no params data found\n"); > - return; > - } > - if (data[IFLA_CAIF_IPV4_CONNID]) > - conn_req->sockaddr.u.dgm.connection_id = > - nla_get_u32(data[IFLA_CAIF_IPV4_CONNID]); > - if (data[IFLA_CAIF_IPV6_CONNID]) > - conn_req->sockaddr.u.dgm.connection_id = > - nla_get_u32(data[IFLA_CAIF_IPV6_CONNID]); > - if (data[IFLA_CAIF_LOOPBACK]) { > - if (nla_get_u8(data[IFLA_CAIF_LOOPBACK])) > - conn_req->protocol = CAIFPROTO_DATAGRAM_LOOP; > - else > - conn_req->protocol = CAIFPROTO_DATAGRAM; > - } > -} > - > -static int ipcaif_newlink(struct net_device *dev, > - struct rtnl_newlink_params *params, > - struct netlink_ext_ack *extack) > -{ > - struct nlattr **data = params->data; > - int ret; > - struct chnl_net *caifdev; > - ASSERT_RTNL(); > - caifdev = netdev_priv(dev); > - caif_netlink_parms(data, &caifdev->conn_req); > - > - ret = register_netdevice(dev); > - if (ret) > - pr_warn("device rtml registration failed\n"); > - else > - list_add(&caifdev->list_field, &chnl_net_list); > - > - /* Use ifindex as connection id, and use loopback channel default. */ > - if (caifdev->conn_req.sockaddr.u.dgm.connection_id == UNDEF_CONNID) { > - caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex; > - caifdev->conn_req.protocol = CAIFPROTO_DATAGRAM_LOOP; > - } > - return ret; > -} > - > -static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[], > - struct nlattr *data[], > - struct netlink_ext_ack *extack) > -{ > - struct chnl_net *caifdev; > - ASSERT_RTNL(); > - caifdev = netdev_priv(dev); > - caif_netlink_parms(data, &caifdev->conn_req); > - netdev_state_change(dev); > - return 0; > -} > - > -static size_t ipcaif_get_size(const struct net_device *dev) > -{ > - return > - /* IFLA_CAIF_IPV4_CONNID */ > - nla_total_size(4) + > - /* IFLA_CAIF_IPV6_CONNID */ > - nla_total_size(4) + > - /* IFLA_CAIF_LOOPBACK */ > - nla_total_size(2) + > - 0; > -} > - > -static const struct nla_policy ipcaif_policy[IFLA_CAIF_MAX + 1] = { > - [IFLA_CAIF_IPV4_CONNID] = { .type = NLA_U32 }, > - [IFLA_CAIF_IPV6_CONNID] = { .type = NLA_U32 }, > - [IFLA_CAIF_LOOPBACK] = { .type = NLA_U8 } > -}; > - > - > -static struct rtnl_link_ops ipcaif_link_ops __read_mostly = { > - .kind = "caif", > - .priv_size = sizeof(struct chnl_net), > - .setup = ipcaif_net_setup, > - .maxtype = IFLA_CAIF_MAX, > - .policy = ipcaif_policy, > - .newlink = ipcaif_newlink, > - .changelink = ipcaif_changelink, > - .get_size = ipcaif_get_size, > - .fill_info = ipcaif_fill_info, > - > -}; > - > -static int __init chnl_init_module(void) > -{ > - return rtnl_link_register(&ipcaif_link_ops); > -} > - > -static void __exit chnl_exit_module(void) > -{ > - struct chnl_net *dev = NULL; > - struct list_head *list_node; > - struct list_head *_tmp; > - rtnl_link_unregister(&ipcaif_link_ops); > - rtnl_lock(); > - list_for_each_safe(list_node, _tmp, &chnl_net_list) { > - dev = list_entry(list_node, struct chnl_net, list_field); > - list_del_init(list_node); > - delete_device(dev); > - } > - rtnl_unlock(); > -} > - > -module_init(chnl_init_module); > -module_exit(chnl_exit_module); > diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig > index e88533b78327..de4af7c750ca 100644 > --- a/arch/arm/configs/u8500_defconfig > +++ b/arch/arm/configs/u8500_defconfig > @@ -37,7 +37,6 @@ CONFIG_CFG80211=y > CONFIG_CFG80211_DEBUGFS=y > CONFIG_MAC80211=y > CONFIG_MAC80211_LEDS=y > -CONFIG_CAIF=y > CONFIG_NFC=m > CONFIG_NFC_HCI=m > CONFIG_NFC_SHDLC=y > -- > 2.53.0