Orange Pi5 kernel

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

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Intel Wireless WiMAX Connection 2400m
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * 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) }