From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 051C5330D29 for ; Thu, 16 Apr 2026 18:28:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776364120; cv=none; b=gsJhP5O8V50KiZjLPyEej/C8KOGWmeuqXg7UPqUV/HqRHMyFPJK7+Lg5Yj0cYyC6sHewbOap4eKxeLTLolTb3r4mYWEaHbWfR6ZfCz+VD3F/46za1S0tWNB720LjOc+PZu6BbW70TVPhgE0gQxVNUEGNpuF0GfjuAAiSMl/z90o= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776364120; c=relaxed/simple; bh=Ee0BaTMgcauatYED9qz0t1UahsC/v11bTvul/wuIzhY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=uHOj8hm3WqxdTCi9+qyk9v+fn9HE2ruDAmUylkpxeckZtxlrB2vWtPJnd/kcAymUXOmlwgiul8Q2pzelkYfKm9mC27JMRTowXf7IFn5iUgOKeH59dB9j7DyvZwZy1BzeFFCxwnzt49XEahTe4kj9uAXvcAdga2qdklXeQYLzVlU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cuvb1P/3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cuvb1P/3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BB001C2BCAF; Thu, 16 Apr 2026 18:28:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776364119; bh=Ee0BaTMgcauatYED9qz0t1UahsC/v11bTvul/wuIzhY=; h=From:To:Cc:Subject:Date:From; b=cuvb1P/3IvZwleDwCyi+NkxqsTYhBfEaGLVj2EhH80v4O16zC2XKO+u+yOwoHv3Kg ovfbruyEXDBU8qJeZCet5eYEFK3RBBOCwx+mma1AVYMOcqfRY1oOO+4olat04a1Vnd OqoVcEUo33xM7tWxGARIPQZQsyXr8uH4kdVFXco8y3ZjvQL1r4LCvS1412agbVXu7q U+Bjdw5duRi7UGmigqmb8lIiiGiqyBn5NogwSLmJ5F5VS6OiEJ6GylixjjJMVVtRBY 3U1Mg2YIaB7oAFgTT2dZf6BkjEnfbWSc0A2VGcKv+HmlAPJRWbymq/3YrMfORRxow4 t7Hx/gzQN7X4Q== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org, Jakub Kicinski , corbet@lwn.net, skhan@linuxfoundation.org, alexs@kernel.org, si.yanteng@linux.dev, dzm91@hust.edu.cn, linux@armlinux.org.uk, mst@redhat.com, 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: [PATCH net-deletions] caif: remove CAIF NETWORK LAYER Date: Thu, 16 Apr 2026 11:28:28 -0700 Message-ID: <20260416182829.1440262-1-kuba@kernel.org> X-Mailer: git-send-email 2.53.0 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-Transfer-Encoding: 8bit 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 --- 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