^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) * USB 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) * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - Split transport/device specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Takes the TX messages in the i2400m's driver TX FIFO and sends them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * to the device until there are no more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * If we fail sending the message, we just drop it. There isn't much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * we can do at this point. We could also retry, but the USB stack has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * already retried and still failed, so there is not much of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * point. As well, most of the traffic is network, which has recovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * methods for dropped packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * For sending we just obtain a FIFO buffer to send, send it to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * USB bulk out, tell the TX FIFO code we have sent it; query for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * another one, etc... until done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * We use a thread so we can call usb_autopm_enable() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * usb_autopm_disable() for each transaction; this way when the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * goes idle, it will suspend. It also has less overhead than a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * dedicated workqueue, as it is being used for a single task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * ROADMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * i2400mu_tx_setup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * i2400mu_tx_release()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * i2400mu_bus_tx_kick() - Called by the tx.c code when there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * is new data in the FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * i2400mu_txd()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * i2400m_tx_msg_get()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * i2400m_tx_msg_sent()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include "i2400m-usb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define D_SUBMODULE tx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include "usb-debug-levels.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Get the next TX message in the TX FIFO and send it to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Note that any iteration consumes a message to be sent, no matter if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * it succeeds or fails (we have no real way to retry or complain).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Return: 0 if ok, < 0 errno code on hard error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) size_t tx_msg_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct i2400m *i2400m = &i2400mu->i2400m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int usb_pipe, sent_size, do_autopm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct usb_endpoint_descriptor *epd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) do_autopm = atomic_read(&i2400mu->do_autopm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) result = do_autopm ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) usb_autopm_get_interface(i2400mu->usb_iface) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dev_err(dev, "TX: can't get autopm: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) do_autopm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) tx_msg, tx_msg_size, &sent_size, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) usb_mark_last_busy(i2400mu->usb_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) switch (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (sent_size != tx_msg_size) { /* Too short? drop it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_err(dev, "TX: short write (%d B vs %zu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) "expected)\n", sent_size, tx_msg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) result = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case -EPIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Stall -- maybe the device is choking with our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * requests. Clear it and give it some time. If they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * happen to often, it might be another symptom, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * No error handling for usb_clear_halt(0; if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * works, the retry works; if it fails, this switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * does the error handling for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (edc_inc(&i2400mu->urb_edc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_err(dev, "BM-CMD: too many stalls in "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "URB; resetting device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) usb_queue_reset_device(i2400mu->usb_iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) usb_clear_halt(i2400mu->usb_dev, usb_pipe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) msleep(10); /* give the device some time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case -EINVAL: /* while removing driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case -ENODEV: /* dev disconnect ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case -ENOENT: /* just ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case -ESHUTDOWN: /* and exit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) result = -ESHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) default: /* Some error? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (edc_inc(&i2400mu->urb_edc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dev_err(dev, "TX: maximum errors in URB "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "exceeded; resetting device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) usb_queue_reset_device(i2400mu->usb_iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev_err(dev, "TX: cannot send URB; retrying. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) "tx_msg @%zu %zu B [%d sent]: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (void *) tx_msg - i2400m->tx_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tx_msg_size, sent_size, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) goto retry;
^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) if (do_autopm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) usb_autopm_put_interface(i2400mu->usb_iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) d_fnend(4, dev, "(i2400mu %p) = result\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return result;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Get the next TX message in the TX FIFO and send it to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * Note we exit the loop if i2400mu_tx() fails; that function only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * fails on hard error (failing to tx a buffer not being one of them,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * see its doc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * Return: 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int i2400mu_txd(void *_i2400mu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct i2400mu *i2400mu = _i2400mu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct i2400m *i2400m = &i2400mu->i2400m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct i2400m_msg_hdr *tx_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) size_t tx_msg_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) BUG_ON(i2400mu->tx_kthread != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) i2400mu->tx_kthread = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) d_printf(2, dev, "TX: waiting for messages\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) tx_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) wait_event_interruptible(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) i2400mu->tx_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) (kthread_should_stop() /* check this first! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) WARN_ON(tx_msg == NULL); /* should not happen...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) d_dump(5, dev, tx_msg, tx_msg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* Yeah, we ignore errors ... not much we can do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) i2400mu_tx(i2400mu, tx_msg, tx_msg_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) i2400mu->tx_kthread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) d_fnend(4, dev, "(i2400mu %p)\n", i2400mu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * i2400m TX engine notifies us that there is data in the FIFO ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * for TX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * If there is a URB in flight, don't do anything; when it finishes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * it will see there is data in the FIFO and send it. Else, just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * submit a write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) void i2400mu_bus_tx_kick(struct i2400m *i2400m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) wake_up_all(&i2400mu->tx_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int i2400mu_tx_setup(struct i2400mu *i2400mu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct i2400m *i2400m = &i2400mu->i2400m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct device *dev = &i2400mu->usb_iface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct task_struct *kthread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) wimax_dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* the kthread function sets i2400mu->tx_thread */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (IS_ERR(kthread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) result = PTR_ERR(kthread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) dev_err(dev, "TX: cannot start thread: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) void i2400mu_tx_release(struct i2400mu *i2400mu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct i2400m *i2400m = &i2400mu->i2400m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct task_struct *kthread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) spin_lock_irqsave(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) kthread = i2400mu->tx_kthread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) i2400mu->tx_kthread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) spin_unlock_irqrestore(&i2400m->tx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (kthread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) kthread_stop(kthread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) d_printf(1, dev, "TX: kthread had already exited\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }