^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) }