linux/drivers/net/wireless/wl12xx/wl1271_tx.c
<<
>>
Prefs
   1/*
   2 * This file is part of wl1271
   3 *
   4 * Copyright (C) 2009 Nokia Corporation
   5 *
   6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20 * 02110-1301 USA
  21 *
  22 */
  23
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26
  27#include "wl1271.h"
  28#include "wl1271_spi.h"
  29#include "wl1271_reg.h"
  30#include "wl1271_ps.h"
  31#include "wl1271_tx.h"
  32
  33static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
  34{
  35        int i;
  36
  37        for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
  38                if (wl->tx_frames[i] == NULL) {
  39                        wl->tx_frames[i] = skb;
  40                        return i;
  41                }
  42
  43        return -EBUSY;
  44}
  45
  46static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
  47{
  48        struct wl1271_tx_hw_descr *desc;
  49        u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
  50        u32 total_blocks, excluded;
  51        int id, ret = -EBUSY;
  52
  53        /* allocate free identifier for the packet */
  54        id = wl1271_tx_id(wl, skb);
  55        if (id < 0)
  56                return id;
  57
  58        /* approximate the number of blocks required for this packet
  59           in the firmware */
  60        /* FIXME: try to figure out what is done here and make it cleaner */
  61        total_blocks = (skb->len) >> TX_HW_BLOCK_SHIFT_DIV;
  62        excluded = (total_blocks << 2) + (skb->len & 0xff) + 34;
  63        total_blocks += (excluded > 252) ? 2 : 1;
  64        total_blocks += TX_HW_BLOCK_SPARE;
  65
  66        if (total_blocks <= wl->tx_blocks_available) {
  67                desc = (struct wl1271_tx_hw_descr *)skb_push(
  68                        skb, total_len - skb->len);
  69
  70                desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
  71                desc->total_mem_blocks = total_blocks;
  72                desc->id = id;
  73
  74                wl->tx_blocks_available -= total_blocks;
  75
  76                ret = 0;
  77
  78                wl1271_debug(DEBUG_TX,
  79                             "tx_allocate: size: %d, blocks: %d, id: %d",
  80                             total_len, total_blocks, id);
  81        } else
  82                wl->tx_frames[id] = NULL;
  83
  84        return ret;
  85}
  86
  87static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
  88                              u32 extra, struct ieee80211_tx_info *control)
  89{
  90        struct wl1271_tx_hw_descr *desc;
  91        int pad;
  92
  93        desc = (struct wl1271_tx_hw_descr *) skb->data;
  94
  95        /* configure packet life time */
  96        desc->start_time = jiffies_to_usecs(jiffies) - wl->time_offset;
  97        desc->life_time = TX_HW_MGMT_PKT_LIFETIME_TU;
  98
  99        /* configure the tx attributes */
 100        desc->tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
 101        /* FIXME: do we know the packet priority? can we identify mgmt
 102           packets, and use max prio for them at least? */
 103        desc->tid = 0;
 104        desc->aid = TX_HW_DEFAULT_AID;
 105        desc->reserved = 0;
 106
 107        /* align the length (and store in terms of words) */
 108        pad = WL1271_TX_ALIGN(skb->len);
 109        desc->length = pad >> 2;
 110
 111        /* calculate number of padding bytes */
 112        pad = pad - skb->len;
 113        desc->tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
 114
 115        wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
 116        return 0;
 117}
 118
 119static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
 120                                 struct ieee80211_tx_info *control)
 121{
 122
 123        struct wl1271_tx_hw_descr *desc;
 124        int len;
 125
 126        /* FIXME: This is a workaround for getting non-aligned packets.
 127           This happens at least with EAPOL packets from the user space.
 128           Our DMA requires packets to be aligned on a 4-byte boundary.
 129        */
 130        if (unlikely((long)skb->data & 0x03)) {
 131                int offset = (4 - (long)skb->data) & 0x03;
 132                wl1271_debug(DEBUG_TX, "skb offset %d", offset);
 133
 134                /* check whether the current skb can be used */
 135                if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
 136                        unsigned char *src = skb->data;
 137
 138                        /* align the buffer on a 4-byte boundary */
 139                        skb_reserve(skb, offset);
 140                        memmove(skb->data, src, skb->len);
 141                } else {
 142                        wl1271_info("No handler, fixme!");
 143                        return -EINVAL;
 144                }
 145        }
 146
 147        len = WL1271_TX_ALIGN(skb->len);
 148
 149        /* perform a fixed address block write with the packet */
 150        wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
 151
 152        /* write packet new counter into the write access register */
 153        wl->tx_packets_count++;
 154        wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
 155
 156        desc = (struct wl1271_tx_hw_descr *) skb->data;
 157        wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
 158                     desc->id, skb, len, desc->length);
 159
 160        return 0;
 161}
 162
 163/* caller must hold wl->mutex */
 164static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
 165{
 166        struct ieee80211_tx_info *info;
 167        u32 extra = 0;
 168        int ret = 0;
 169        u8 idx;
 170
 171        if (!skb)
 172                return -EINVAL;
 173
 174        info = IEEE80211_SKB_CB(skb);
 175
 176        if (info->control.hw_key &&
 177            info->control.hw_key->alg == ALG_TKIP)
 178                extra = WL1271_TKIP_IV_SPACE;
 179
 180        if (info->control.hw_key) {
 181                idx = info->control.hw_key->hw_key_idx;
 182
 183                /* FIXME: do we have to do this if we're not using WEP? */
 184                if (unlikely(wl->default_key != idx)) {
 185                        ret = wl1271_cmd_set_default_wep_key(wl, idx);
 186                        if (ret < 0)
 187                                return ret;
 188                }
 189        }
 190
 191        ret = wl1271_tx_allocate(wl, skb, extra);
 192        if (ret < 0)
 193                return ret;
 194
 195        ret = wl1271_tx_fill_hdr(wl, skb, extra, info);
 196        if (ret < 0)
 197                return ret;
 198
 199        ret = wl1271_tx_send_packet(wl, skb, info);
 200        if (ret < 0)
 201                return ret;
 202
 203        return ret;
 204}
 205
 206void wl1271_tx_work(struct work_struct *work)
 207{
 208        struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
 209        struct sk_buff *skb;
 210        bool woken_up = false;
 211        int ret;
 212
 213        mutex_lock(&wl->mutex);
 214
 215        if (unlikely(wl->state == WL1271_STATE_OFF))
 216                goto out;
 217
 218        while ((skb = skb_dequeue(&wl->tx_queue))) {
 219                if (!woken_up) {
 220                        ret = wl1271_ps_elp_wakeup(wl, false);
 221                        if (ret < 0)
 222                                goto out;
 223                        woken_up = true;
 224                }
 225
 226                ret = wl1271_tx_frame(wl, skb);
 227                if (ret == -EBUSY) {
 228                        /* firmware buffer is full, stop queues */
 229                        wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
 230                                     "stop queues");
 231                        ieee80211_stop_queues(wl->hw);
 232                        wl->tx_queue_stopped = true;
 233                        skb_queue_head(&wl->tx_queue, skb);
 234                        goto out;
 235                } else if (ret < 0) {
 236                        dev_kfree_skb(skb);
 237                        goto out;
 238                } else if (wl->tx_queue_stopped) {
 239                        /* firmware buffer has space, restart queues */
 240                        wl1271_debug(DEBUG_TX,
 241                                     "complete_packet: waking queues");
 242                        ieee80211_wake_queues(wl->hw);
 243                        wl->tx_queue_stopped = false;
 244                }
 245        }
 246
 247out:
 248        if (woken_up)
 249                wl1271_ps_elp_sleep(wl);
 250
 251        mutex_unlock(&wl->mutex);
 252}
 253
 254static void wl1271_tx_complete_packet(struct wl1271 *wl,
 255                                      struct wl1271_tx_hw_res_descr *result)
 256{
 257
 258        struct ieee80211_tx_info *info;
 259        struct sk_buff *skb;
 260        u32 header_len;
 261        int id = result->id;
 262
 263        /* check for id legality */
 264        if (id >= TX_HW_RESULT_QUEUE_LEN || wl->tx_frames[id] == NULL) {
 265                wl1271_warning("TX result illegal id: %d", id);
 266                return;
 267        }
 268
 269        skb = wl->tx_frames[id];
 270        info = IEEE80211_SKB_CB(skb);
 271
 272        /* update packet status */
 273        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 274                if (result->status == TX_SUCCESS)
 275                        info->flags |= IEEE80211_TX_STAT_ACK;
 276                if (result->status & TX_RETRY_EXCEEDED) {
 277                        /* FIXME */
 278                        /* info->status.excessive_retries = 1; */
 279                        wl->stats.excessive_retries++;
 280                }
 281        }
 282
 283        /* FIXME */
 284        /* info->status.retry_count = result->ack_failures; */
 285        wl->stats.retry_count += result->ack_failures;
 286
 287        /* get header len */
 288        if (info->control.hw_key &&
 289            info->control.hw_key->alg == ALG_TKIP)
 290                header_len = WL1271_TKIP_IV_SPACE +
 291                        sizeof(struct wl1271_tx_hw_descr);
 292        else
 293                header_len = sizeof(struct wl1271_tx_hw_descr);
 294
 295        wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
 296                     " status 0x%x",
 297                     result->id, skb, result->ack_failures,
 298                     result->rate_class_index, result->status);
 299
 300        /* remove private header from packet */
 301        skb_pull(skb, header_len);
 302
 303        /* return the packet to the stack */
 304        ieee80211_tx_status(wl->hw, skb);
 305        wl->tx_frames[result->id] = NULL;
 306}
 307
 308/* Called upon reception of a TX complete interrupt */
 309void wl1271_tx_complete(struct wl1271 *wl, u32 count)
 310{
 311        struct wl1271_acx_mem_map *memmap =
 312                (struct wl1271_acx_mem_map *)wl->target_mem_map;
 313        u32 i;
 314
 315        wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
 316
 317        /* read the tx results from the chipset */
 318        wl1271_spi_mem_read(wl, memmap->tx_result,
 319                            wl->tx_res_if, sizeof(*wl->tx_res_if));
 320
 321        /* verify that the result buffer is not getting overrun */
 322        if (count > TX_HW_RESULT_QUEUE_LEN) {
 323                wl1271_warning("TX result overflow from chipset: %d", count);
 324                count = TX_HW_RESULT_QUEUE_LEN;
 325        }
 326
 327        /* process the results */
 328        for (i = 0; i < count; i++) {
 329                struct wl1271_tx_hw_res_descr *result;
 330                u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK;
 331
 332                /* process the packet */
 333                result =  &(wl->tx_res_if->tx_results_queue[offset]);
 334                wl1271_tx_complete_packet(wl, result);
 335
 336                wl->tx_results_count++;
 337        }
 338
 339        /* write host counter to chipset (to ack) */
 340        wl1271_mem_write32(wl, memmap->tx_result +
 341                           offsetof(struct wl1271_tx_hw_res_if,
 342                                    tx_result_host_counter),
 343                           wl->tx_res_if->tx_result_fw_counter);
 344}
 345
 346/* caller must hold wl->mutex */
 347void wl1271_tx_flush(struct wl1271 *wl)
 348{
 349        int i;
 350        struct sk_buff *skb;
 351        struct ieee80211_tx_info *info;
 352
 353        /* TX failure */
 354/*      control->flags = 0; FIXME */
 355
 356        while ((skb = skb_dequeue(&wl->tx_queue))) {
 357                info = IEEE80211_SKB_CB(skb);
 358
 359                wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
 360
 361                if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
 362                                continue;
 363
 364                ieee80211_tx_status(wl->hw, skb);
 365        }
 366
 367        for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
 368                if (wl->tx_frames[i] != NULL) {
 369                        skb = wl->tx_frames[i];
 370                        info = IEEE80211_SKB_CB(skb);
 371
 372                        if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
 373                                continue;
 374
 375                        ieee80211_tx_status(wl->hw, skb);
 376                        wl->tx_frames[i] = NULL;
 377                }
 378}
 379