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