root/drivers/net/wireless/marvell/libertas/rx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lbs_process_rxed_packet
  2. convert_mv_rate_to_radiotap
  3. process_rxed_802_11_packet

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * This file contains the handling of RX in wlan driver.
   4  */
   5 
   6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   7 
   8 #include <linux/etherdevice.h>
   9 #include <linux/hardirq.h>
  10 #include <linux/slab.h>
  11 #include <linux/types.h>
  12 #include <linux/export.h>
  13 #include <net/cfg80211.h>
  14 
  15 #include "defs.h"
  16 #include "host.h"
  17 #include "radiotap.h"
  18 #include "decl.h"
  19 #include "dev.h"
  20 #include "mesh.h"
  21 
  22 struct eth803hdr {
  23         u8 dest_addr[6];
  24         u8 src_addr[6];
  25         u16 h803_len;
  26 } __packed;
  27 
  28 struct rfc1042hdr {
  29         u8 llc_dsap;
  30         u8 llc_ssap;
  31         u8 llc_ctrl;
  32         u8 snap_oui[3];
  33         u16 snap_type;
  34 } __packed;
  35 
  36 struct rxpackethdr {
  37         struct eth803hdr eth803_hdr;
  38         struct rfc1042hdr rfc1042_hdr;
  39 } __packed;
  40 
  41 struct rx80211packethdr {
  42         struct rxpd rx_pd;
  43         void *eth80211_hdr;
  44 } __packed;
  45 
  46 static int process_rxed_802_11_packet(struct lbs_private *priv,
  47         struct sk_buff *skb);
  48 
  49 /**
  50  * lbs_process_rxed_packet - processes received packet and forwards it
  51  * to kernel/upper layer
  52  *
  53  * @priv:       A pointer to &struct lbs_private
  54  * @skb:        A pointer to skb which includes the received packet
  55  * returns:     0 or -1
  56  */
  57 int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
  58 {
  59         int ret = 0;
  60         struct net_device *dev = priv->dev;
  61         struct rxpackethdr *p_rx_pkt;
  62         struct rxpd *p_rx_pd;
  63         int hdrchop;
  64         struct ethhdr *p_ethhdr;
  65         static const u8 rfc1042_eth_hdr[] = {
  66                 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
  67         };
  68 
  69         BUG_ON(!skb);
  70 
  71         skb->ip_summed = CHECKSUM_NONE;
  72 
  73         if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
  74                 ret = process_rxed_802_11_packet(priv, skb);
  75                 goto done;
  76         }
  77 
  78         p_rx_pd = (struct rxpd *) skb->data;
  79         p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
  80                 le32_to_cpu(p_rx_pd->pkt_ptr));
  81 
  82         dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
  83 
  84         lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
  85                  min_t(unsigned int, skb->len, 100));
  86 
  87         if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
  88                 lbs_deb_rx("rx err: frame received with bad length\n");
  89                 dev->stats.rx_length_errors++;
  90                 ret = -EINVAL;
  91                 dev_kfree_skb(skb);
  92                 goto done;
  93         }
  94 
  95         lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n",
  96                 skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr),
  97                 skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr));
  98 
  99         lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
 100                 sizeof(p_rx_pkt->eth803_hdr.dest_addr));
 101         lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
 102                 sizeof(p_rx_pkt->eth803_hdr.src_addr));
 103 
 104         if (memcmp(&p_rx_pkt->rfc1042_hdr,
 105                    rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
 106                 /*
 107                  *  Replace the 803 header and rfc1042 header (llc/snap) with an
 108                  *    EthernetII header, keep the src/dst and snap_type (ethertype)
 109                  *
 110                  *  The firmware only passes up SNAP frames converting
 111                  *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
 112                  *
 113                  *  To create the Ethernet II, just move the src, dst address right
 114                  *    before the snap_type.
 115                  */
 116                 p_ethhdr = (struct ethhdr *)
 117                     ((u8 *) &p_rx_pkt->eth803_hdr
 118                      + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
 119                      - sizeof(p_rx_pkt->eth803_hdr.dest_addr)
 120                      - sizeof(p_rx_pkt->eth803_hdr.src_addr)
 121                      - sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
 122 
 123                 memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
 124                        sizeof(p_ethhdr->h_source));
 125                 memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
 126                        sizeof(p_ethhdr->h_dest));
 127 
 128                 /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
 129                  *   that was removed
 130                  */
 131                 hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
 132         } else {
 133                 lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
 134                         (u8 *) &p_rx_pkt->rfc1042_hdr,
 135                         sizeof(p_rx_pkt->rfc1042_hdr));
 136 
 137                 /* Chop off the rxpd */
 138                 hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd;
 139         }
 140 
 141         /* Chop off the leading header bytes so the skb points to the start of
 142          *   either the reconstructed EthII frame or the 802.2/llc/snap frame
 143          */
 144         skb_pull(skb, hdrchop);
 145 
 146         priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
 147 
 148         lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 149         dev->stats.rx_bytes += skb->len;
 150         dev->stats.rx_packets++;
 151 
 152         skb->protocol = eth_type_trans(skb, dev);
 153         if (in_interrupt())
 154                 netif_rx(skb);
 155         else
 156                 netif_rx_ni(skb);
 157 
 158         ret = 0;
 159 done:
 160         return ret;
 161 }
 162 EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
 163 
 164 /**
 165  * convert_mv_rate_to_radiotap - converts Tx/Rx rates from Marvell WLAN format
 166  * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
 167  *
 168  * @rate:       Input rate
 169  * returns:     Output Rate (0 if invalid)
 170  */
 171 static u8 convert_mv_rate_to_radiotap(u8 rate)
 172 {
 173         switch (rate) {
 174         case 0:         /*   1 Mbps */
 175                 return 2;
 176         case 1:         /*   2 Mbps */
 177                 return 4;
 178         case 2:         /* 5.5 Mbps */
 179                 return 11;
 180         case 3:         /*  11 Mbps */
 181                 return 22;
 182         /* case 4: reserved */
 183         case 5:         /*   6 Mbps */
 184                 return 12;
 185         case 6:         /*   9 Mbps */
 186                 return 18;
 187         case 7:         /*  12 Mbps */
 188                 return 24;
 189         case 8:         /*  18 Mbps */
 190                 return 36;
 191         case 9:         /*  24 Mbps */
 192                 return 48;
 193         case 10:                /*  36 Mbps */
 194                 return 72;
 195         case 11:                /*  48 Mbps */
 196                 return 96;
 197         case 12:                /*  54 Mbps */
 198                 return 108;
 199         }
 200         pr_alert("Invalid Marvell WLAN rate %i\n", rate);
 201         return 0;
 202 }
 203 
 204 /**
 205  * process_rxed_802_11_packet - processes a received 802.11 packet and forwards
 206  * it to kernel/upper layer
 207  *
 208  * @priv:       A pointer to &struct lbs_private
 209  * @skb:        A pointer to skb which includes the received packet
 210  * returns:     0 or -1
 211  */
 212 static int process_rxed_802_11_packet(struct lbs_private *priv,
 213         struct sk_buff *skb)
 214 {
 215         int ret = 0;
 216         struct net_device *dev = priv->dev;
 217         struct rx80211packethdr *p_rx_pkt;
 218         struct rxpd *prxpd;
 219         struct rx_radiotap_hdr radiotap_hdr;
 220         struct rx_radiotap_hdr *pradiotap_hdr;
 221 
 222         p_rx_pkt = (struct rx80211packethdr *) skb->data;
 223         prxpd = &p_rx_pkt->rx_pd;
 224 
 225         /* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */
 226 
 227         if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
 228                 lbs_deb_rx("rx err: frame received with bad length\n");
 229                 dev->stats.rx_length_errors++;
 230                 ret = -EINVAL;
 231                 kfree_skb(skb);
 232                 goto done;
 233         }
 234 
 235         lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
 236                skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
 237 
 238         /* create the exported radio header */
 239 
 240         /* radiotap header */
 241         memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
 242         /* XXX must check radiotap_hdr.hdr.it_pad for pad */
 243         radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
 244         radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
 245         radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
 246         /* XXX must check no carryout */
 247         radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
 248 
 249         /* chop the rxpd */
 250         skb_pull(skb, sizeof(struct rxpd));
 251 
 252         /* add space for the new radio header */
 253         if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
 254             pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
 255                 netdev_alert(dev, "%s: couldn't pskb_expand_head\n", __func__);
 256                 ret = -ENOMEM;
 257                 kfree_skb(skb);
 258                 goto done;
 259         }
 260 
 261         pradiotap_hdr = skb_push(skb, sizeof(struct rx_radiotap_hdr));
 262         memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
 263 
 264         priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
 265 
 266         lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 267         dev->stats.rx_bytes += skb->len;
 268         dev->stats.rx_packets++;
 269 
 270         skb->protocol = eth_type_trans(skb, priv->dev);
 271 
 272         if (in_interrupt())
 273                 netif_rx(skb);
 274         else
 275                 netif_rx_ni(skb);
 276 
 277         ret = 0;
 278 
 279 done:
 280         return ret;
 281 }

/* [<][>][^][v][top][bottom][index][help] */