2 * carlu - userspace testing utility for ar9170 devices
4 * xmit - related functions
6 * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 #include "ieee80211.h"
42 struct frame *carlu_alloc_frame(struct carlu *ar, unsigned int size)
45 unsigned int total_len;
47 total_len = ar->extra_headroom + sizeof(struct _carl9170_tx_superframe) + size;
49 tmp = frame_alloc(total_len);
53 frame_reserve(tmp, sizeof(struct _carl9170_tx_superframe) + ar->extra_headroom);
60 static int carlu_alloc_dev_mem(struct carlu *ar,
63 struct _carl9170_tx_superframe *txp = (void *)frame->data;
64 unsigned int len, chunks;
66 len = roundup(frame->len, ar->dma_chunk_size);
67 chunks = len / ar->dma_chunk_size;
69 SDL_mutexP(ar->mem_lock);
70 if (ar->tx_pending >= ar->dma_chunks ||
71 ar->used_dma_chunks + chunks >= ar->dma_chunks) {
72 SDL_mutexV(ar->mem_lock);
76 ar->used_dma_chunks += chunks;
78 txp->s.cookie = ar->cookie++;
79 SDL_mutexV(ar->mem_lock);
84 static void carlu_free_dev_mem(struct carlu *ar,
87 struct _carl9170_tx_superframe *txp = (void *)frame->data;
88 unsigned int len, chunks;
90 len = roundup(frame->len, ar->dma_chunk_size);
91 chunks = len / ar->dma_chunk_size;
93 SDL_mutexP(ar->mem_lock);
94 ar->used_dma_chunks -= chunks;
96 SDL_mutexV(ar->mem_lock);
99 void carlu_free_frame(struct carlu *ar __unused,
105 static struct frame *carlu_find_frame(struct carlu *ar,
106 unsigned int queue, uint8_t cookie)
108 struct frame *frame = NULL;
110 BUG_ON(queue >= __AR9170_NUM_TXQ);
111 BUG_ON(SDL_mutexP(ar->tx_sent_queue[queue].lock) != 0);
112 FRAME_WALK(frame, &ar->tx_sent_queue[queue]) {
113 struct _carl9170_tx_superframe *super;
115 super = (void *) frame->data;
116 if (super->s.cookie == cookie) {
117 __frame_unlink(&ar->tx_sent_queue[queue], frame);
118 SDL_mutexV(ar->tx_sent_queue[queue].lock);
122 SDL_mutexV(ar->tx_sent_queue[queue].lock);
127 static void carlu_tx_fb_cb(struct carlu *ar,
131 ar->tx_fb_cb(ar, frame);
133 carlu_free_frame(ar, frame);
137 void carlu_tx_feedback(struct carlu *ar,
138 struct carl9170_rsp *cmd)
140 unsigned int i, n, k, q;
142 struct carlu_tx_info *tx_info;
146 for (i = 0; i < n; i++) {
147 q = (cmd->_tx_status[i].info >> CARL9170_TX_STATUS_QUEUE_S) &
148 CARL9170_TX_STATUS_QUEUE;
149 frame = carlu_find_frame(ar, q, cmd->_tx_status[i].cookie);
151 carlu_free_dev_mem(ar, frame);
152 tx_info = get_tx_info(frame);
154 k = (cmd->_tx_status[i].info >> CARL9170_TX_STATUS_RIX)
155 & CARL9170_TX_STATUS_RIX_S;
156 tx_info->rates[k].cnt = (cmd->_tx_status[i].info >>
157 CARL9170_TX_STATUS_TRIES_S) &
158 CARL9170_TX_STATUS_TRIES;
159 for (k++; k < CARL9170_TX_MAX_RATES; k++) {
160 tx_info->rates[k].rix = -1;
161 tx_info->rates[k].cnt = -1;
164 carlu_tx_fb_cb(ar, frame);
166 err("Found no frame for cookie %d.\n",
167 cmd->_tx_status[i].cookie);
172 int carlu_tx(struct carlu *ar, struct frame *frame)
174 struct _carl9170_tx_superframe *txp;
175 unsigned int len, queue;
180 txp = (void *) frame_push(frame, sizeof(struct _carl9170_tx_superframe));
185 err = carlu_alloc_dev_mem(ar, frame);
189 txp->s.len = cpu_to_le16(frame->len);
191 queue = (frame->queue % __AR9170_NUM_TXQ);
193 SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txp->s.misc, queue);
195 txp->f.length = len + FCS_LEN; /* + I(C)V_LEN */
197 txp->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
198 AR9170_TX_MAC_BACKOFF);
199 txp->f.mac_control |= cpu_to_le16(queue << AR9170_TX_MAC_QOS_S);
201 txp->f.phy_control = cpu_to_le32(AR9170_TX_PHY_MOD_CCK | AR9170_TX_PHY_BW_20MHZ |
202 ((17 * 2) << AR9170_TX_PHY_TX_PWR_S) |
203 (AR9170_TX_PHY_TXCHAIN_1 << AR9170_TX_PHY_TXCHAIN_S) |
204 (11 << AR9170_TX_PHY_MCS_S));
206 frame_queue_tail(&ar->tx_sent_queue[queue], frame);
207 carlusb_tx(ar, frame);
211 frame_pull(frame, sizeof(struct _carl9170_tx_superframe));