linux/drivers/staging/rtl8712/xmit_linux.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 * xmit_linux.c
   4 *
   5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6 * Linux device driver for RTL8192SU
   7 *
   8 * Modifications for inclusion into the Linux staging tree are
   9 * Copyright(c) 2010 Larry Finger. All rights reserved.
  10 *
  11 * Contact information:
  12 * WLAN FAE <wlanfae@realtek.com>
  13 * Larry Finger <Larry.Finger@lwfinger.net>
  14 *
  15 ******************************************************************************/
  16
  17#define _XMIT_OSDEP_C_
  18
  19#include <linux/usb.h>
  20#include <linux/ip.h>
  21#include <linux/if_ether.h>
  22#include <linux/kmemleak.h>
  23
  24#include "osdep_service.h"
  25#include "drv_types.h"
  26
  27#include "wifi.h"
  28#include "mlme_osdep.h"
  29#include "xmit_osdep.h"
  30#include "osdep_intf.h"
  31
  32static uint remainder_len(struct pkt_file *pfile)
  33{
  34        return (uint)(pfile->buf_len - ((addr_t)(pfile->cur_addr) -
  35               (addr_t)(pfile->buf_start)));
  36}
  37
  38void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile)
  39{
  40        pfile->pkt = pktptr;
  41        pfile->cur_addr = pfile->buf_start = pktptr->data;
  42        pfile->pkt_len = pfile->buf_len = pktptr->len;
  43        pfile->cur_buffer = pfile->buf_start;
  44}
  45
  46uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
  47{
  48        uint len;
  49
  50        len = remainder_len(pfile);
  51        len = (rlen > len) ? len : rlen;
  52        if (rmem)
  53                skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len,
  54                              rmem, len);
  55        pfile->cur_addr += len;
  56        pfile->pkt_len -= len;
  57        return len;
  58}
  59
  60sint r8712_endofpktfile(struct pkt_file *pfile)
  61{
  62        return (pfile->pkt_len == 0);
  63}
  64
  65
  66void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
  67{
  68        struct ethhdr etherhdr;
  69        struct iphdr ip_hdr;
  70        u16 UserPriority = 0;
  71
  72        _r8712_open_pktfile(ppktfile->pkt, ppktfile);
  73        _r8712_pktfile_read(ppktfile, (unsigned char *)&etherhdr, ETH_HLEN);
  74
  75        /* get UserPriority from IP hdr*/
  76        if (pattrib->ether_type == 0x0800) {
  77                _r8712_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));
  78                /*UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3 ;*/
  79                UserPriority = ip_hdr.tos >> 5;
  80        } else {
  81                /* "When priority processing of data frames is supported,
  82                 * a STA's SME should send EAPOL-Key frames at the highest
  83                 * priority."
  84                 */
  85
  86                if (pattrib->ether_type == 0x888e)
  87                        UserPriority = 7;
  88        }
  89        pattrib->priority = UserPriority;
  90        pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
  91        pattrib->subtype = WIFI_QOS_DATA_TYPE;
  92}
  93
  94void r8712_SetFilter(struct work_struct *work)
  95{
  96        struct _adapter *adapter = container_of(work, struct _adapter,
  97                                                wk_filter_rx_ff0);
  98        u8  oldvalue = 0x00, newvalue = 0x00;
  99        unsigned long irqL;
 100
 101        oldvalue = r8712_read8(adapter, 0x117);
 102        newvalue = oldvalue & 0xfe;
 103        r8712_write8(adapter, 0x117, newvalue);
 104
 105        spin_lock_irqsave(&adapter->lock_rx_ff0_filter, irqL);
 106        adapter->blnEnableRxFF0Filter = 1;
 107        spin_unlock_irqrestore(&adapter->lock_rx_ff0_filter, irqL);
 108        do {
 109                msleep(100);
 110        } while (adapter->blnEnableRxFF0Filter == 1);
 111        r8712_write8(adapter, 0x117, oldvalue);
 112}
 113
 114int r8712_xmit_resource_alloc(struct _adapter *padapter,
 115                              struct xmit_buf *pxmitbuf)
 116{
 117        int i;
 118
 119        for (i = 0; i < 8; i++) {
 120                pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
 121                if (!pxmitbuf->pxmit_urb[i]) {
 122                        netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n");
 123                        return -ENOMEM;
 124                }
 125                kmemleak_not_leak(pxmitbuf->pxmit_urb[i]);
 126        }
 127        return 0;
 128}
 129
 130void r8712_xmit_resource_free(struct _adapter *padapter,
 131                              struct xmit_buf *pxmitbuf)
 132{
 133        int i;
 134
 135        for (i = 0; i < 8; i++) {
 136                if (pxmitbuf->pxmit_urb[i]) {
 137                        usb_kill_urb(pxmitbuf->pxmit_urb[i]);
 138                        usb_free_urb(pxmitbuf->pxmit_urb[i]);
 139                }
 140        }
 141}
 142
 143void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe)
 144{
 145        if (pxframe->pkt)
 146                dev_kfree_skb_any(pxframe->pkt);
 147        pxframe->pkt = NULL;
 148}
 149
 150int r8712_xmit_entry(_pkt *pkt, struct  net_device *netdev)
 151{
 152        struct xmit_frame *xmitframe = NULL;
 153        struct _adapter *adapter = netdev_priv(netdev);
 154        struct xmit_priv *xmitpriv = &(adapter->xmitpriv);
 155
 156        if (!r8712_if_up(adapter))
 157                goto _xmit_entry_drop;
 158
 159        xmitframe = r8712_alloc_xmitframe(xmitpriv);
 160        if (!xmitframe)
 161                goto _xmit_entry_drop;
 162
 163        if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib))
 164                goto _xmit_entry_drop;
 165
 166        adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX);
 167        xmitframe->pkt = pkt;
 168        if (r8712_pre_xmit(adapter, xmitframe)) {
 169                /*dump xmitframe directly or drop xframe*/
 170                dev_kfree_skb_any(pkt);
 171                xmitframe->pkt = NULL;
 172        }
 173        xmitpriv->tx_pkts++;
 174        xmitpriv->tx_bytes += xmitframe->attrib.last_txcmdsz;
 175        return 0;
 176_xmit_entry_drop:
 177        if (xmitframe)
 178                r8712_free_xmitframe(xmitpriv, xmitframe);
 179        xmitpriv->tx_drop++;
 180        dev_kfree_skb_any(pkt);
 181        return 0;
 182}
 183