Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * Intel Wireless WiMAX Connection 2400m
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Generic (non-bus specific) TX handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *   * Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *     notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *   * Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *     notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *     the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *     distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *   * Neither the name of Intel Corporation nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  *     contributors may be used to endorse or promote products derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *     from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  * Intel Corporation <linux-wimax@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  * Yanir Lubetkin <yanirx.lubetkin@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  *  - Initial implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  * Intel Corporation <linux-wimax@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  *  - Rewritten to use a single FIFO to lower the memory allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  *    pressure and optimize cache hits when copying to the queue, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43)  *    well as splitting out bus-specific code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  * Implements data transmission to the device; this is done through a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47)  * software FIFO, as data/control frames can be coalesced (while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  * device is reading the previous tx transaction, others accumulate).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * A FIFO is used because at the end it is resource-cheaper that trying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * to implement scatter/gather over USB. As well, most traffic is going
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  * to be download (vs upload).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  * The format for sending/receiving data to/from the i2400m is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  * described in detail in rx.c:PROTOCOL FORMAT. In here we implement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  * the transmission of that. This is split between a bus-independent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  * part that just prepares everything and a bus-specific part that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  * does the actual transmission over the bus to the device (in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  * bus-specific driver).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  * The general format of a device-host transaction is MSG-HDR, PLD1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63)  * PLD2...PLDN, PL1, PL2,...PLN, PADDING.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65)  * Because we need the send payload descriptors and then payloads and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66)  * because it is kind of expensive to do scatterlists in USB (one URB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67)  * per node), it becomes cheaper to append all the data to a FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)  * (copying to a FIFO potentially in cache is cheaper).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70)  * Then the bus-specific code takes the parts of that FIFO that are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71)  * written and passes them to the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73)  * So the concepts to keep in mind there are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75)  * We use a FIFO to queue the data in a linear buffer. We first append
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76)  * a MSG-HDR, space for I2400M_TX_PLD_MAX payload descriptors and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77)  * go appending payloads until we run out of space or of payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78)  * descriptors. Then we append padding to make the whole transaction a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79)  * multiple of i2400m->bus_tx_block_size (as defined by the bus layer).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81)  * - A TX message: a combination of a message header, payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82)  *   descriptors and payloads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84)  *     Open: it is marked as active (i2400m->tx_msg is valid) and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85)  *       can keep adding payloads to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87)  *     Closed: we are not appending more payloads to this TX message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88)  *       (exahusted space in the queue, too many payloads or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  *       whichever).  We have appended padding so the whole message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  *       length is aligned to i2400m->bus_tx_block_size (as set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  *       bus/transport layer).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  * - Most of the time we keep a TX message open to which we append
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  *   payloads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  * - If we are going to append and there is no more space (we are at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)  *   the end of the FIFO), we close the message, mark the rest of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  *   FIFO space unusable (skip_tail), create a new message at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  *   beginning of the FIFO (if there is space) and append the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  *   there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  *   This is because we need to give linear TX messages to the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  *   engine. So we don't write a message to the remaining FIFO space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  *   until the tail and continue at the head of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  * - We overload one of the fields in the message header to use it as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  *   'size' of the TX message, so we can iterate over them. It also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108)  *   contains a flag that indicates if we have to skip it or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109)  *   When we send the buffer, we update that to its real on-the-wire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110)  *   value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  * - The MSG-HDR PLD1...PLD2 stuff has to be a size multiple of 16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114)  *   It follows that if MSG-HDR says we have N messages, the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115)  *   header + descriptors is 16 + 4*N; for those to be a multiple of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116)  *   16, it follows that N can be 4, 8, 12, ... (32, 48, 64, 80...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  *   bytes).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  *   So if we have only 1 payload, we have to submit a header that in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  *   all truth has space for 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122)  *   The implication is that we reserve space for 12 (64 bytes); but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  *   if we fill up only (eg) 2, our header becomes 32 bytes only. So
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  *   the TX engine has to shift those 32 bytes of msg header and 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  *   payloads and padding so that right after it the payloads start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  *   and the TX engine has to know about that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  *   It is cheaper to move the header up than the whole payloads down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  *   We do this in i2400m_tx_close(). See 'i2400m_msg_hdr->offset'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132)  * - Each payload has to be size-padded to 16 bytes; before appending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  *   it, we just do it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135)  * - The whole message has to be padded to i2400m->bus_tx_block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136)  *   we do this at close time. Thus, when reserving space for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)  *   payload, we always make sure there is also free space for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138)  *   padding that sooner or later will happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140)  * When we append a message, we tell the bus specific code to kick in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141)  * TXs. It will TX (in parallel) until the buffer is exhausted--hence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142)  * the lockin we do. The TX code will only send a TX message at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143)  * time (which remember, might contain more than one payload). Of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144)  * course, when the bus-specific driver attempts to TX a message that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145)  * is still open, it gets closed first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147)  * Gee, this is messy; well a picture. In the example below we have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)  * partially full FIFO, with a closed message ready to be delivered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)  * (with a moved message header to make sure it is size-aligned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150)  * 16), TAIL room that was unusable (and thus is marked with a message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151)  * header that says 'skip this') and at the head of the buffer, an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * incomplete message with a couple of payloads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)  * N   ___________________________________________________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156)  *    |     TAIL room                                     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158)  *    |  msg_hdr to skip (size |= 0x80000)                |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159)  *    |---------------------------------------------------|-------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)  *    |                                                   |  /|\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  *    |  TX message padding                               |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  *    |  payload 1                                        |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  *    |                                                   | N * tx_block_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  *    |  payload 1                                        |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174)  *    |                                                   |   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|- -|- - - -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)  *    |  padding 3                  /|\                   |   |   /|\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  *    |  padding 2                   |                    |   |    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  *    |  pld 1                32 bytes (2 * 16)           |   |    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  *    |  pld 0                       |                    |   |    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  *    |  moved msg_hdr              \|/                   |  \|/   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|- - -   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182)  *    |                                                   |    _PLD_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  *    |  unused                                           |        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  *    |                                                   |        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  *    |  msg_hdr (size X)       [this message is closed]  |       \|/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187)  *    |===================================================|========== <=== OUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191)  *    |          Free rooom                               |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  *    |===================================================|========== <=== IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206)  *    |  payload 1                                        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211)  *    |  payload 0                                        |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213)  *    |                                                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214)  *    |- - - - - - - - - - - - - - - - - - - - - - - - - -|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215)  *    |  pld 11                     /|\                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216)  *    |  ...                         |                    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217)  *    |  pld 1                64 bytes (2 * 16)           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218)  *    |  pld 0                       |                    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219)  *    |  msg_hdr (size X)           \|/ [message is open] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220)  * 0   ---------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223)  * ROADMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225)  * i2400m_tx_setup()           Called by i2400m_setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226)  * i2400m_tx_release()         Called by i2400m_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228)  *  i2400m_tx()                 Called to send data or control frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229)  *    i2400m_tx_fifo_push()     Allocates append-space in the FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230)  *    i2400m_tx_new()           Opens a new message in the FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231)  *    i2400m_tx_fits()          Checks if a new payload fits in the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  *    i2400m_tx_close()         Closes an open message in the FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)  *    i2400m_tx_skip_tail()     Marks unusable FIFO tail space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234)  *    i2400m->bus_tx_kick()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236)  * Now i2400m->bus_tx_kick() is the the bus-specific driver backend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237)  * implementation; that would do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239)  * i2400m->bus_tx_kick()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240)  *   i2400m_tx_msg_get()	Gets first message ready to go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241)  *   ...sends it...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242)  *   i2400m_tx_msg_sent()       Ack the message is sent; repeat from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243)  *                              _tx_msg_get() until it returns NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244)  *                               (FIFO empty).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) #include "i2400m.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) #define D_SUBMODULE tx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) #include "debug-levels.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	/**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	 * TX Buffer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	 * Doc says maximum transaction is 16KiB. If we had 16KiB en
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	 * route and 16KiB being queued, it boils down to needing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	 * 32KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	 * 32KiB is insufficient for 1400 MTU, hence increasing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	 * tx buffer size to 64KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	I2400M_TX_BUF_SIZE = 65536,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	/**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	 * Message header and payload descriptors have to be 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	 * aligned (16 + 4 * N = 16 * M). If we take that average sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	 * packets are MTU size (~1400-~1500) it follows that we could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	 * fit at most 10-11 payloads in one transaction. To meet the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	 * alignment requirement, that means we need to leave space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	 * for 12 (64 bytes). To simplify, we leave space for that. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	 * at the end there are less, we pad up to the nearest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	 * multiple of 16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	 * According to Intel Wimax i3200, i5x50 and i6x50 specification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	 * documents, the maximum number of payloads per message can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	 * up to 60. Increasing the number of payloads to 60 per message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	 * helps to accommodate smaller payloads in a single transaction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	I2400M_TX_PLD_MAX = 60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	I2400M_TX_PLD_SIZE = sizeof(struct i2400m_msg_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	+ I2400M_TX_PLD_MAX * sizeof(struct i2400m_pld),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	I2400M_TX_SKIP = 0x80000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	 * According to Intel Wimax i3200, i5x50 and i6x50 specification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	 * documents, the maximum size of each message can be up to 16KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	I2400M_TX_MSG_SIZE = 16384,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) #define TAIL_FULL ((void *)~(unsigned long)NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296)  * Calculate how much tail room is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298)  * Note the trick here. This path is ONLY caleed for Case A (see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299)  * i2400m_tx_fifo_push() below), where we have:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301)  *       Case A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)  * N  ___________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303)  *   | tail room |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305)  *   |<-  IN   ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)  *   |   data    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309)  *   |<-  OUT  ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311)  *   | head room |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312)  * 0  -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314)  * When calculating the tail_room, tx_in might get to be zero if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315)  * i2400m->tx_in is right at the end of the buffer (really full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316)  * buffer) if there is no head room. In this case, tail_room would be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)  * I2400M_TX_BUF_SIZE, although it is actually zero. Hence the final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318)  * mod (%) operation. However, when doing this kind of optimization,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319)  * i2400m->tx_in being zero would fail, so we treat is an a special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320)  * case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) size_t __i2400m_tx_tail_room(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	size_t tail_room;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	size_t tx_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	if (unlikely(i2400m->tx_in == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 		return I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	tail_room = I2400M_TX_BUF_SIZE - tx_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	tail_room %= I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	return tail_room;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338)  * Allocate @size bytes in the TX fifo, return a pointer to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340)  * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341)  * @size: size of the buffer we need to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342)  * @padding: ensure that there is at least this many bytes of free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343)  *     contiguous space in the fifo. This is needed because later on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344)  *     we might need to add padding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345)  * @try_head: specify either to allocate head room or tail room space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346)  *     in the TX FIFO. This boolean is required to avoids a system hang
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347)  *     due to an infinite loop caused by i2400m_tx_fifo_push().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348)  *     The caller must always try to allocate tail room space first by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349)  *     calling this routine with try_head = 0. In case if there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350)  *     is not enough tail room space but there is enough head room space,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351)  *     (i2400m_tx_fifo_push() returns TAIL_FULL) try to allocate head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352)  *     room space, by calling this routine again with try_head = 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356)  *     Pointer to the allocated space. NULL if there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357)  *     space. TAIL_FULL if there is no space at the tail but there is at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358)  *     the head (Case B below).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360)  * These are the two basic cases we need to keep an eye for -- it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361)  * much better explained in linux/kernel/kfifo.c, but this code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362)  * basically does the same. No rocket science here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364)  *       Case A               Case B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365)  * N  ___________          ___________
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366)  *   | tail room |        |   data    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367)  *   |           |        |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368)  *   |<-  IN   ->|        |<-  OUT  ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369)  *   |           |        |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370)  *   |   data    |        |   room    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371)  *   |           |        |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)  *   |<-  OUT  ->|        |<-  IN   ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)  *   |           |        |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)  *   | head room |        |   data    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375)  * 0  -----------          -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377)  * We allocate only *contiguous* space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379)  * We can allocate only from 'room'. In Case B, it is simple; in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)  * A, we only try from the tail room; if it is not enough, we just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381)  * fail and return TAIL_FULL and let the caller figure out if we wants to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382)  * skip the tail room and try to allocate from the head.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)  * There is a corner case, wherein i2400m_tx_new() can get into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)  * an infinite loop calling i2400m_tx_fifo_push().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386)  * In certain situations, tx_in would have reached on the top of TX FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)  * and i2400m_tx_tail_room() returns 0, as described below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)  * N  ___________ tail room is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)  *   |<-  IN   ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)  *   |   data    |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)  *   |<-  OUT  ->|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)  *   |           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  *   | head room |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  * 0  -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)  * During such a time, where tail room is zero in the TX FIFO and if there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  * is a request to add a payload to TX FIFO, which calls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  * i2400m_tx()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)  *         ->calls i2400m_tx_close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)  *         ->calls i2400m_tx_skip_tail()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)  *         goto try_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)  *         ->calls i2400m_tx_new()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407)  *                    |----> [try_head:]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408)  *     infinite loop  |     ->calls i2400m_tx_fifo_push()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409)  *                    |                if (tail_room < needed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410)  *                    |                   if (head_room => needed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411)  *                    |                       return TAIL_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412)  *                    |<----  goto try_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414)  * i2400m_tx() calls i2400m_tx_close() to close the message, since there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415)  * is no tail room to accommodate the payload and calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416)  * i2400m_tx_skip_tail() to skip the tail space. Now i2400m_tx() calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  * i2400m_tx_new() to allocate space for new message header calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418)  * i2400m_tx_fifo_push() that returns TAIL_FULL, since there is no tail space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419)  * to accommodate the message header, but there is enough head space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420)  * The i2400m_tx_new() keeps re-retrying by calling i2400m_tx_fifo_push()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421)  * ending up in a loop causing system freeze.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423)  * This corner case is avoided by using a try_head boolean,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424)  * as an argument to i2400m_tx_fifo_push().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)  *     Assumes i2400m->tx_lock is taken, and we use that as a barrier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430)  *     The indexes keep increasing and we reset them to zero when we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431)  *     pop data off the queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 			  size_t padding, bool try_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	size_t room, tail_room, needed_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	needed_size = size + padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	room = I2400M_TX_BUF_SIZE - (i2400m->tx_in - i2400m->tx_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	if (room < needed_size)	{ /* this takes care of Case B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		d_printf(2, dev, "fifo push %zu/%zu: no space\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 			 size, padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	/* Is there space at the tail? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	tail_room = __i2400m_tx_tail_room(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	if (!try_head && tail_room < needed_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		 * If the tail room space is not enough to push the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		 * in the TX FIFO, then there are two possibilities:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		 * 1. There is enough head room space to accommodate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		 * this message in the TX FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		 * 2. There is not enough space in the head room and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		 * in tail room of the TX FIFO to accommodate the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		 * In the case (1), return TAIL_FULL so that the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		 * can figure out, if the caller wants to push the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		 * into the head room space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		 * In the case (2), return NULL, indicating that the TX FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		 * cannot accommodate the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		if (room - tail_room >= needed_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 			d_printf(2, dev, "fifo push %zu/%zu: tail full\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 				 size, padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 			return TAIL_FULL;	/* There might be head space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 			d_printf(2, dev, "fifo push %zu/%zu: no head space\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 				 size, padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 			return NULL;	/* There is no space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	ptr = i2400m->tx_buf + i2400m->tx_in % I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	d_printf(2, dev, "fifo push %zu/%zu: at @%zu\n", size, padding,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		 i2400m->tx_in % I2400M_TX_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	i2400m->tx_in += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483)  * Mark the tail of the FIFO buffer as 'to-skip'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485)  * We should never hit the BUG_ON() because all the sizes we push to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486)  * the FIFO are padded to be a multiple of 16 -- the size of *msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487)  * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)  * header).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)  * Tail room can get to be zero if a message was opened when there was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)  * space only for a header. _tx_close() will mark it as to-skip (as it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)  * will have no payloads) and there will be no more space to flush, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493)  * nothing has to be done here. This is probably cheaper than ensuring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494)  * in _tx_new() that there is some space for payloads...as we could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  * always possibly hit the same problem if the payload wouldn't fit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  *     Assumes i2400m->tx_lock is taken, and we use that as a barrier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  *     This path is only taken for Case A FIFO situations [see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  *     i2400m_tx_fifo_push()]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) void i2400m_tx_skip_tail(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	size_t tail_room = __i2400m_tx_tail_room(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	if (unlikely(tail_room == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	BUG_ON(tail_room < sizeof(*msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	msg->size = tail_room | I2400M_TX_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		 tail_room, tx_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	i2400m->tx_in += tail_room;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522)  * Check if a skb will fit in the TX queue's current active TX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523)  * message (if there are still descriptors left unused).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526)  *     0 if the message won't fit, 1 if it will.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530)  *     Assumes a TX message is active (i2400m->tx_msg).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532)  *     Assumes i2400m->tx_lock is taken, and we use that as a barrier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) unsigned i2400m_tx_fits(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	struct i2400m_msg_hdr *msg_hdr = i2400m->tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	return le16_to_cpu(msg_hdr->num_pls) < I2400M_TX_PLD_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)  * Start a new TX message header in the queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546)  * Reserve memory from the base FIFO engine and then just initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547)  * the message header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549)  * We allocate the biggest TX message header we might need (one that'd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)  * fit I2400M_TX_PLD_MAX payloads) -- when it is closed it will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)  * 'ironed it out' and the unneeded parts removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)  * NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)  *     Assumes that the previous message is CLOSED (eg: either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)  *     there was none or 'i2400m_tx_close()' was called on it).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  *     Assumes i2400m->tx_lock is taken, and we use that as a barrier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) void i2400m_tx_new(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	struct i2400m_msg_hdr *tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	bool try_head = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	BUG_ON(i2400m->tx_msg != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	 * In certain situations, TX queue might have enough space to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	 * accommodate the new message header I2400M_TX_PLD_SIZE, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	 * might not have enough space to accommodate the payloads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	 * Adding bus_tx_room_min padding while allocating a new TX message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	 * increases the possibilities of including at least one payload of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	 * size <= bus_tx_room_min.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) try_head:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	tx_msg = i2400m_tx_fifo_push(i2400m, I2400M_TX_PLD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 				     i2400m->bus_tx_room_min, try_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	if (tx_msg == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	else if (tx_msg == TAIL_FULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		i2400m_tx_skip_tail(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		d_printf(2, dev, "new TX message: tail full, trying head\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		try_head = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		goto try_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	memset(tx_msg, 0, I2400M_TX_PLD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	tx_msg->size = I2400M_TX_PLD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	i2400m->tx_msg = tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	d_printf(2, dev, "new TX message: %p @%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		 tx_msg, (void *) tx_msg - i2400m->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)  * Finalize the current TX message header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598)  * Sets the message header to be at the proper location depending on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599)  * how many descriptors we have (check documentation at the file's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600)  * header for more info on that).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)  * Appends padding bytes to make sure the whole TX message (counting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)  * from the 'relocated' message header) is aligned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)  * tx_block_size. We assume the _append() code has left enough space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605)  * in the FIFO for that. If there are no payloads, just pass, as it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606)  * won't be transferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608)  * The amount of padding bytes depends on how many payloads are in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)  * TX message, as the "msg header and payload descriptors" will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610)  * shifted up in the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) void i2400m_tx_close(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	struct i2400m_msg_hdr *tx_msg_moved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	size_t aligned_size, padding, hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	void *pad_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	unsigned num_pls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	if (tx_msg->size & I2400M_TX_SKIP)	/* a skipper? nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	num_pls = le16_to_cpu(tx_msg->num_pls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	/* We can get this situation when a new message was started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	 * and there was no space to add payloads before hitting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	 tail (and taking padding into consideration). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	if (num_pls == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 		tx_msg->size |= I2400M_TX_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	/* Relocate the message header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	 * Find the current header size, align it to 16 and if we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	 * to move it so the tail is next to the payloads, move it and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	 * set the offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	 * If it moved, this header is good only for transmission; the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	 * original one (it is kept if we moved) is still used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	 * figure out where the next TX message starts (and where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	 * offset to the moved header is).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	hdr_size = struct_size(tx_msg, pld, le16_to_cpu(tx_msg->num_pls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	hdr_size = ALIGN(hdr_size, I2400M_PL_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	tx_msg_moved = (void *) tx_msg + tx_msg->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	memmove(tx_msg_moved, tx_msg, hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	tx_msg_moved->size -= tx_msg->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	 * Now figure out how much we have to add to the (moved!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	 * message so the size is a multiple of i2400m->bus_tx_block_size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	aligned_size = ALIGN(tx_msg_moved->size, i2400m->bus_tx_block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	padding = aligned_size - tx_msg_moved->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	if (padding > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		if (WARN_ON(pad_buf == NULL || pad_buf == TAIL_FULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 			/* This should not happen -- append should verify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			 * there is always space left at least to append
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 			 * tx_block_size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 			dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 				"SW BUG! Possible data leakage from memory the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 				"device should not read for padding - "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 				"size %lu aligned_size %zu tx_buf %p in "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 				"%zu out %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 				(unsigned long) tx_msg_moved->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 				aligned_size, i2400m->tx_buf, i2400m->tx_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 				i2400m->tx_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			memset(pad_buf, 0xad, padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	tx_msg_moved->padding = cpu_to_le16(padding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	tx_msg_moved->size += padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	if (tx_msg != tx_msg_moved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		tx_msg->size += padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	i2400m->tx_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  * i2400m_tx - send the data in a buffer to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  * @buf: pointer to the buffer to transmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  * @buf_len: buffer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688)  * @pl_type: type of the payload we are sending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691)  *     0 if ok, < 0 errno code on error (-ENOSPC, if there is no more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692)  *     room for the message in the queue).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694)  * Appends the buffer to the TX FIFO and notifies the bus-specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695)  * part of the driver that there is new data ready to transmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696)  * Once this function returns, the buffer has been copied, so it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697)  * be reused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699)  * The steps followed to append are explained in detail in the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700)  * header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702)  * Whenever we write to a message, we increase msg->size, so it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703)  * reflects exactly how big the message is. This is needed so that if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704)  * we concatenate two messages before they can be sent, the code that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705)  * sends the messages can find the boundaries (and it will replace the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706)  * size with the real barker before sending).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710)  *     Cold and warm reset payloads need to be sent as a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711)  *     payload, so we handle that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	      enum i2400m_pt pl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	int result = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	size_t padded_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	bool try_head = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	unsigned is_singleton = pl_type == I2400M_PT_RESET_WARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		|| pl_type == I2400M_PT_RESET_COLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		  i2400m, buf, buf_len, pl_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	padded_len = ALIGN(buf_len, I2400M_PL_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	/* If there is no current TX message, create one; if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	 * current one is out of payload slots or we have a singleton,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	 * close it and start a new one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	/* If tx_buf is NULL, device is shutdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	if (i2400m->tx_buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		result = -ESHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		goto error_tx_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) try_new:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	if (unlikely(i2400m->tx_msg == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		i2400m_tx_new(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	else if (unlikely(!i2400m_tx_fits(i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 			  || (is_singleton && i2400m->tx_msg->num_pls != 0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		d_printf(2, dev, "closing TX message (fits %u singleton "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 			 "%u num_pls %u)\n", i2400m_tx_fits(i2400m),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 			 is_singleton, i2400m->tx_msg->num_pls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		i2400m_tx_close(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		i2400m_tx_new(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	if (i2400m->tx_msg == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 		goto error_tx_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	 * Check if this skb will fit in the TX queue's current active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	 * TX message. The total message size must not exceed the maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	 * size of each message I2400M_TX_MSG_SIZE. If it exceeds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	 * close the current message and push this skb into the new message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	if (i2400m->tx_msg->size + padded_len > I2400M_TX_MSG_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		d_printf(2, dev, "TX: message too big, going new\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 		i2400m_tx_close(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		i2400m_tx_new(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	if (i2400m->tx_msg == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		goto error_tx_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	/* So we have a current message header; now append space for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	 * the message -- if there is not enough, try the head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	ptr = i2400m_tx_fifo_push(i2400m, padded_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 				  i2400m->bus_tx_block_size, try_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	if (ptr == TAIL_FULL) {	/* Tail is full, try head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		d_printf(2, dev, "pl append: tail full\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		i2400m_tx_close(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		i2400m_tx_skip_tail(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		try_head = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		goto try_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	} else if (ptr == NULL) {	/* All full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		result = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		d_printf(2, dev, "pl append: all full\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	} else {			/* Got space, copy it, set padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		unsigned num_pls = le16_to_cpu(tx_msg->num_pls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		memcpy(ptr, buf, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		memset(ptr + buf_len, 0xad, padded_len - buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		i2400m_pld_set(&tx_msg->pld[num_pls], buf_len, pl_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		d_printf(3, dev, "pld 0x%08x (type 0x%1x len 0x%04zx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			 le32_to_cpu(tx_msg->pld[num_pls].val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 			 pl_type, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		tx_msg->num_pls = le16_to_cpu(num_pls+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		tx_msg->size += padded_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		d_printf(2, dev, "TX: appended %zu b (up to %u b) pl #%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			padded_len, tx_msg->size, num_pls+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		d_printf(2, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			 "TX: appended hdr @%zu %zu b pl #%u @%zu %zu/%zu b\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			 (void *)tx_msg - i2400m->tx_buf, (size_t)tx_msg->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 			 num_pls+1, ptr - i2400m->tx_buf, buf_len, padded_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		if (is_singleton)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 			i2400m_tx_close(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) error_tx_new:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	/* kick in most cases, except when the TX subsys is down, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	 * it might free space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	if (likely(result != -ESHUTDOWN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		i2400m->bus_tx_kick(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	d_fnend(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		i2400m, buf, buf_len, pl_type, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) EXPORT_SYMBOL_GPL(i2400m_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812)  * i2400m_tx_msg_get - Get the first TX message in the FIFO to start sending it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814)  * @i2400m: device descriptors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815)  * @bus_size: where to place the size of the TX message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817)  * Called by the bus-specific driver to get the first TX message at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)  * the FIF that is ready for transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820)  * It sets the state in @i2400m to indicate the bus-specific driver is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821)  * transferring that message (i2400m->tx_msg_size).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823)  * Once the transfer is completed, call i2400m_tx_msg_sent().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825)  * Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827)  *     The size of the TX message to be transmitted might be smaller than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828)  *     that of the TX message in the FIFO (in case the header was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829)  *     shorter). Hence, we copy it in @bus_size, for the bus layer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830)  *     use. We keep the message's size in i2400m->tx_msg_size so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831)  *     when the bus later is done transferring we know how much to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832)  *     advance the fifo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834)  *     We collect statistics here as all the data is available and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835)  *     assume it is going to work [see i2400m_tx_msg_sent()].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *i2400m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 					 size_t *bus_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	struct i2400m_msg_hdr *tx_msg, *tx_msg_moved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	unsigned long flags, pls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	d_fnstart(3, dev, "(i2400m %p bus_size %p)\n", i2400m, bus_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	tx_msg_moved = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	if (i2400m->tx_buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	tx_msg_moved = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	if (i2400m->tx_in == i2400m->tx_out) {	/* Empty FIFO? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		i2400m->tx_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		i2400m->tx_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		d_printf(2, dev, "TX: FIFO empty: resetting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	tx_msg = i2400m->tx_buf + i2400m->tx_out % I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	if (tx_msg->size & I2400M_TX_SKIP) {	/* skip? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		d_printf(2, dev, "TX: skip: msg @%zu (%zu b)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 			 i2400m->tx_out % I2400M_TX_BUF_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			 (size_t) tx_msg->size & ~I2400M_TX_SKIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	if (tx_msg->num_pls == 0) {		/* No payloads? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		if (tx_msg == i2400m->tx_msg) {	/* open, we are done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			d_printf(2, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 				 "TX: FIFO empty: open msg w/o payloads @%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 				 (void *) tx_msg - i2400m->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 			tx_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		} else {			/* closed, skip it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			d_printf(2, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 				 "TX: skip msg w/o payloads @%zu (%zu b)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 				 (void *) tx_msg - i2400m->tx_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 				 (size_t) tx_msg->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 			i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	if (tx_msg == i2400m->tx_msg)		/* open msg? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		i2400m_tx_close(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	/* Now we have a valid TX message (with payloads) to TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	tx_msg_moved = (void *) tx_msg + tx_msg->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	i2400m->tx_msg_size = tx_msg->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	*bus_size = tx_msg_moved->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	d_printf(2, dev, "TX: pid %d msg hdr at @%zu offset +@%zu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		 "size %zu bus_size %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		 current->pid, (void *) tx_msg - i2400m->tx_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		 (size_t) tx_msg->offset, (size_t) tx_msg->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		 (size_t) tx_msg_moved->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	tx_msg_moved->barker = le32_to_cpu(I2400M_H2D_PREVIEW_BARKER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	tx_msg_moved->sequence = le32_to_cpu(i2400m->tx_sequence++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	pls = le32_to_cpu(tx_msg_moved->num_pls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	i2400m->tx_pl_num += pls;		/* Update stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	if (pls > i2400m->tx_pl_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		i2400m->tx_pl_max = pls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	if (pls < i2400m->tx_pl_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		i2400m->tx_pl_min = pls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	i2400m->tx_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	i2400m->tx_size_acc += *bus_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	if (*bus_size < i2400m->tx_size_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		i2400m->tx_size_min = *bus_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	if (*bus_size > i2400m->tx_size_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		i2400m->tx_size_max = *bus_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	d_fnstart(3, dev, "(i2400m %p bus_size %p [%zu]) = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		  i2400m, bus_size, *bus_size, tx_msg_moved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	return tx_msg_moved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) EXPORT_SYMBOL_GPL(i2400m_tx_msg_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919)  * i2400m_tx_msg_sent - indicate the transmission of a TX message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921)  * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923)  * Called by the bus-specific driver when a message has been sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)  * this pops it from the FIFO; and as there is space, start the queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  * in case it was stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927)  * Should be called even if the message send failed and we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928)  * dropping this TX message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) void i2400m_tx_msg_sent(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	unsigned n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	if (i2400m->tx_buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	i2400m->tx_out += i2400m->tx_msg_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	i2400m->tx_msg_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	BUG_ON(i2400m->tx_out > i2400m->tx_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	/* level them FIFO markers off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	n = i2400m->tx_out / I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	i2400m->tx_out %= I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	i2400m->tx_in -= n * I2400M_TX_BUF_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) EXPORT_SYMBOL_GPL(i2400m_tx_msg_sent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956)  * i2400m_tx_setup - Initialize the TX queue and infrastructure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958)  * Make sure we reset the TX sequence to zero, as when this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959)  * is called, the firmware has been just restarted. Same rational
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960)  * for tx_in, tx_out, tx_msg_size and tx_msg. We reset them since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961)  * the memory for TX queue is reallocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) int i2400m_tx_setup(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	void *tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	/* Do this here only once -- can't do on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	 * i2400m_hard_start_xmit() as we'll cause race conditions if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	 * the WS was scheduled on another CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	INIT_WORK(&i2400m->wake_tx_ws, i2400m_wake_tx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	if (tx_buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		goto error_kmalloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	 * Fail the build if we can't fit at least two maximum size messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	 * on the TX FIFO [one being delivered while one is constructed].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	BUILD_BUG_ON(2 * I2400M_TX_MSG_SIZE > I2400M_TX_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	i2400m->tx_sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	i2400m->tx_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	i2400m->tx_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	i2400m->tx_msg_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	i2400m->tx_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	i2400m->tx_buf = tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	/* Huh? the bus layer has to define this... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	BUG_ON(i2400m->bus_tx_block_size == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) error_kmalloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)  * i2400m_tx_release - Tear down the TX queue and infrastructure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) void i2400m_tx_release(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	kfree(i2400m->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	i2400m->tx_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }