1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 5 * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> 6 * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/cdefs.h> 22 #include "opt_wlan.h" 23 24 #include <sys/param.h> 25 #include <sys/lock.h> 26 #include <sys/mutex.h> 27 #include <sys/mbuf.h> 28 #include <sys/kernel.h> 29 #include <sys/socket.h> 30 #include <sys/systm.h> 31 #include <sys/malloc.h> 32 #include <sys/queue.h> 33 #include <sys/taskqueue.h> 34 #include <sys/bus.h> 35 #include <sys/endian.h> 36 37 #include <net/if.h> 38 #include <net/if_var.h> 39 #include <net/ethernet.h> 40 #include <net/if_media.h> 41 42 #include <net80211/ieee80211_var.h> 43 #include <net80211/ieee80211_radiotap.h> 44 #include <net80211/ieee80211_ratectl.h> 45 46 #include <dev/usb/usb.h> 47 #include <dev/usb/usbdi.h> 48 49 #include <dev/rtwn/if_rtwnreg.h> 50 #include <dev/rtwn/if_rtwnvar.h> 51 52 #include <dev/rtwn/if_rtwn_beacon.h> 53 #include <dev/rtwn/if_rtwn_debug.h> 54 #include <dev/rtwn/if_rtwn_ridx.h> 55 #include <dev/rtwn/if_rtwn_task.h> 56 #include <dev/rtwn/if_rtwn_tx.h> 57 58 #include <dev/rtwn/usb/rtwn_usb_var.h> 59 60 #include <dev/rtwn/usb/rtwn_usb_reg.h> 61 #include <dev/rtwn/usb/rtwn_usb_tx.h> 62 63 static struct rtwn_data * _rtwn_usb_getbuf(struct rtwn_usb_softc *); 64 static struct rtwn_data * rtwn_usb_getbuf(struct rtwn_usb_softc *); 65 static void rtwn_usb_txeof(struct rtwn_usb_softc *, 66 struct rtwn_data *, int); 67 68 static struct rtwn_data * 69 _rtwn_usb_getbuf(struct rtwn_usb_softc *uc) 70 { 71 struct rtwn_softc *sc = &uc->uc_sc; 72 struct rtwn_data *bf; 73 74 bf = STAILQ_FIRST(&uc->uc_tx_inactive); 75 if (bf != NULL) 76 STAILQ_REMOVE_HEAD(&uc->uc_tx_inactive, next); 77 else { 78 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, 79 "%s: out of xmit buffers\n", __func__); 80 } 81 return (bf); 82 } 83 84 static struct rtwn_data * 85 rtwn_usb_getbuf(struct rtwn_usb_softc *uc) 86 { 87 struct rtwn_softc *sc = &uc->uc_sc; 88 struct rtwn_data *bf; 89 90 RTWN_ASSERT_LOCKED(sc); 91 92 bf = _rtwn_usb_getbuf(uc); 93 if (bf == NULL) { 94 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: stop queue\n", 95 __func__); 96 } 97 return (bf); 98 } 99 100 static void 101 rtwn_usb_txeof(struct rtwn_usb_softc *uc, struct rtwn_data *data, int status) 102 { 103 struct rtwn_softc *sc = &uc->uc_sc; 104 bool is_empty = true; 105 106 RTWN_ASSERT_LOCKED(sc); 107 108 if (data->ni != NULL) /* not a beacon frame */ 109 ieee80211_tx_complete(data->ni, data->m, status); 110 111 if (sc->sc_ratectl != RTWN_RATECTL_NET80211) 112 if (sc->sc_tx_n_active > 0) 113 sc->sc_tx_n_active--; 114 115 data->ni = NULL; 116 data->m = NULL; 117 118 STAILQ_INSERT_TAIL(&uc->uc_tx_inactive, data, next); 119 sc->qfullmsk = 0; 120 121 #ifndef D4054 122 for (int i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) { 123 if (!STAILQ_EMPTY(&uc->uc_tx_active[i]) || 124 !STAILQ_EMPTY(&uc->uc_tx_pending[i])) 125 is_empty = false; 126 } 127 128 if (is_empty) 129 sc->sc_tx_timer = 0; 130 else 131 sc->sc_tx_timer = 5; 132 #endif 133 } 134 135 static void 136 rtwn_bulk_tx_callback_qid(struct usb_xfer *xfer, usb_error_t error, int qid) 137 { 138 struct rtwn_usb_softc *uc = usbd_xfer_softc(xfer); 139 struct rtwn_softc *sc = &uc->uc_sc; 140 struct rtwn_data *data; 141 bool do_is_empty_check = false; 142 int i; 143 144 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, 145 "%s: called, qid=%d\n", __func__, qid); 146 147 RTWN_ASSERT_LOCKED(sc); 148 149 switch (USB_GET_STATE(xfer)){ 150 case USB_ST_TRANSFERRED: 151 data = STAILQ_FIRST(&uc->uc_tx_active[qid]); 152 if (data == NULL) 153 goto tr_setup; 154 STAILQ_REMOVE_HEAD(&uc->uc_tx_active[qid], next); 155 rtwn_usb_txeof(uc, data, 0); 156 /* FALLTHROUGH */ 157 case USB_ST_SETUP: 158 tr_setup: 159 data = STAILQ_FIRST(&uc->uc_tx_pending[qid]); 160 if (data == NULL) { 161 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, 162 "%s: empty pending queue\n", __func__); 163 do_is_empty_check = true; 164 goto finish; 165 } 166 STAILQ_REMOVE_HEAD(&uc->uc_tx_pending[qid], next); 167 STAILQ_INSERT_TAIL(&uc->uc_tx_active[qid], data, next); 168 169 /* 170 * Note: if this is a beacon frame, ensure that it will go 171 * into appropriate queue. 172 */ 173 if (data->ni == NULL && RTWN_CHIP_HAS_BCNQ1(sc)) 174 rtwn_switch_bcnq(sc, data->id); 175 usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); 176 usbd_transfer_submit(xfer); 177 if (sc->sc_ratectl != RTWN_RATECTL_NET80211) 178 sc->sc_tx_n_active++; 179 break; 180 default: 181 data = STAILQ_FIRST(&uc->uc_tx_active[qid]); 182 if (data == NULL) 183 goto tr_setup; 184 STAILQ_REMOVE_HEAD(&uc->uc_tx_active[qid], next); 185 rtwn_usb_txeof(uc, data, 1); 186 if (error != 0) 187 device_printf(sc->sc_dev, 188 "%s: called; txeof qid=%d, error=%s\n", 189 __func__, 190 qid, 191 usbd_errstr(error)); 192 if (error != USB_ERR_CANCELLED) { 193 usbd_xfer_set_stall(xfer); 194 goto tr_setup; 195 } 196 break; 197 } 198 finish: 199 200 /* 201 * Clear sc_tx_n_active if all the pending transfers are 0. 202 * 203 * This is currently a crutch because net80211 doesn't provide 204 * a way to defer all the FF checks or one of the FF checks. 205 * Eventually this should just be tracked per-endpoint. 206 */ 207 for (i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) 208 if (STAILQ_FIRST(&uc->uc_tx_pending[i]) != NULL) 209 do_is_empty_check = false; 210 if (do_is_empty_check) 211 sc->sc_tx_n_active = 0; 212 #ifdef IEEE80211_SUPPORT_SUPERG 213 /* 214 * If the TX active queue drops below a certain 215 * threshold, ensure we age fast-frames out so they're 216 * transmitted. 217 */ 218 if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && 219 sc->sc_tx_n_active <= 1) { 220 /* XXX ew - net80211 should defer this for us! */ 221 222 /* 223 * Note: this sc_tx_n_active currently tracks 224 * the number of pending transmit submissions 225 * and not the actual depth of the TX frames 226 * pending to the hardware. That means that 227 * we're going to end up with some sub-optimal 228 * aggregation behaviour. 229 */ 230 /* 231 * XXX TODO: just make this a callout timer schedule so we can 232 * flush the FF staging queue if we're approaching idle. 233 */ 234 rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); 235 } 236 #endif 237 /* Kick-start more transmit */ 238 rtwn_start(sc); 239 } 240 241 void 242 rtwn_bulk_tx_callback_be(struct usb_xfer *xfer, usb_error_t error) 243 { 244 245 rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_BE); 246 } 247 248 void 249 rtwn_bulk_tx_callback_bk(struct usb_xfer *xfer, usb_error_t error) 250 { 251 252 rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_BK); 253 } 254 255 void 256 rtwn_bulk_tx_callback_vi(struct usb_xfer *xfer, usb_error_t error) 257 { 258 259 rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_VI); 260 } 261 262 void 263 rtwn_bulk_tx_callback_vo(struct usb_xfer *xfer, usb_error_t error) 264 { 265 266 rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_VO); 267 } 268 269 static void 270 rtwn_usb_tx_checksum(struct rtwn_tx_desc_common *txd) 271 { 272 txd->txdw7.usb_checksum = 0; 273 txd->txdw7.usb_checksum = rtwn_usb_calc_tx_checksum(txd); 274 } 275 276 int 277 rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni, 278 struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id) 279 { 280 struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 281 struct rtwn_tx_desc_common *txd; 282 struct rtwn_data *data; 283 struct usb_xfer *xfer; 284 uint16_t ac; 285 int qid = 0; 286 287 RTWN_ASSERT_LOCKED(sc); 288 289 if (m->m_pkthdr.len + sc->txdesc_len > RTWN_USB_TXBUFSZ) 290 return (EINVAL); 291 292 data = rtwn_usb_getbuf(uc); 293 if (data == NULL) 294 return (ENOBUFS); 295 296 /* TODO: should really get a consistent AC/TID, ath(4) style */ 297 ac = M_WME_GETAC(m); 298 299 switch (type) { 300 case IEEE80211_FC0_TYPE_CTL: 301 case IEEE80211_FC0_TYPE_MGT: 302 qid = RTWN_BULK_TX_VO; 303 break; 304 default: 305 qid = uc->wme2qid[ac]; 306 break; 307 } 308 xfer = uc->uc_xfer[qid]; 309 310 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, 311 "%s: called, ac=%d, qid=%d, xfer=%p\n", 312 __func__, ac, qid, xfer); 313 314 txd = (struct rtwn_tx_desc_common *)tx_desc; 315 txd->pktlen = htole16(m->m_pkthdr.len); 316 txd->offset = sc->txdesc_len; 317 txd->flags0 |= RTWN_FLAGS0_OWN; 318 rtwn_usb_tx_checksum(txd); 319 320 /* Dump Tx descriptor. */ 321 rtwn_dump_tx_desc(sc, tx_desc); 322 323 memcpy(data->buf, tx_desc, sc->txdesc_len); 324 m_copydata(m, 0, m->m_pkthdr.len, 325 (caddr_t)(data->buf + sc->txdesc_len)); 326 327 data->buflen = m->m_pkthdr.len + sc->txdesc_len; 328 data->id = id; 329 data->ni = ni; 330 data->qid = qid; 331 if (data->ni != NULL) { 332 data->m = m; 333 #ifndef D4054 334 sc->sc_tx_timer = 5; 335 #endif 336 } 337 338 STAILQ_INSERT_TAIL(&uc->uc_tx_pending[qid], data, next); 339 if (STAILQ_EMPTY(&uc->uc_tx_inactive)) 340 sc->qfullmsk = 1; 341 342 usbd_transfer_start(xfer); 343 344 return (0); 345 } 346