]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/tx.c
hwmon: (lm90) Add support for the LM99 16 degree offset
[linux-2.6-omap-h63xx.git] / net / mac80211 / tx.c
index 20d683641b4240d13af738d47a11bdbbeb2dad8c..1460537faf3335c64824ddd61704a212a43655de 100644 (file)
@@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
        return cpu_to_le16(dur);
 }
 
-static int inline is_ieee80211_device(struct net_device *dev,
-                                     struct net_device *master)
+static int inline is_ieee80211_device(struct ieee80211_local *local,
+                                     struct net_device *dev)
 {
-       return (wdev_priv(dev->ieee80211_ptr) ==
-               wdev_priv(master->ieee80211_ptr));
+       return local == wdev_priv(dev->ieee80211_ptr);
 }
 
 /* tx handlers */
@@ -447,22 +446,24 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
        if (likely(tx->rate_idx < 0)) {
-               rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
+               rate_control_get_rate(tx->sdata, sband, tx->sta,
+                                     tx->skb, &rsel);
                if (tx->sta)
                        tx->sta->last_txrate_idx = rsel.rate_idx;
                tx->rate_idx = rsel.rate_idx;
                if (unlikely(rsel.probe_idx >= 0)) {
                        info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
                        tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-                       info->control.alt_retry_rate_idx = tx->rate_idx;
+                       info->control.retries[0].rate_idx = tx->rate_idx;
+                       info->control.retries[0].limit = tx->local->hw.max_altrate_tries;
                        tx->rate_idx = rsel.probe_idx;
-               } else
-                       info->control.alt_retry_rate_idx = -1;
+               } else if (info->control.retries[0].limit == 0)
+                       info->control.retries[0].rate_idx = -1;
 
                if (unlikely(tx->rate_idx < 0))
                        return TX_DROP;
        } else
-               info->control.alt_retry_rate_idx = -1;
+               info->control.retries[0].rate_idx = -1;
 
        if (tx->sdata->bss_conf.use_cts_prot &&
            (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
@@ -521,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
                 * frames.
                 * TODO: The last fragment could still use multiple retry
                 * rates. */
-               info->control.alt_retry_rate_idx = -1;
+               info->control.retries[0].rate_idx = -1;
        }
 
        /* Use CTS protection for unicast frames sent using extended rates if
@@ -551,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
                int idx;
 
                /* Do not use multiple retry rates when using RTS/CTS */
-               info->control.alt_retry_rate_idx = -1;
+               info->control.retries[0].rate_idx = -1;
 
                /* Use min(data rate, max base rate) as CTS/RTS rate */
                rate = &sband->bitrates[tx->rate_idx];
@@ -1001,14 +1002,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
 /*
  * NB: @tx is uninitialised when passed in here
  */
-static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
-                               struct sk_buff *skb,
-                               struct net_device *mdev)
+static int ieee80211_tx_prepare(struct ieee80211_local *local,
+                               struct ieee80211_tx_data *tx,
+                               struct sk_buff *skb)
 {
        struct net_device *dev;
 
        dev = dev_get_by_index(&init_net, skb->iif);
-       if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
+       if (unlikely(dev && !is_ieee80211_device(local, dev))) {
                dev_put(dev);
                dev = NULL;
        }
@@ -1255,9 +1256,10 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
        return 0;
 }
 
-int ieee80211_master_start_xmit(struct sk_buff *skb,
-                               struct net_device *dev)
+int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       struct ieee80211_master_priv *mpriv = netdev_priv(dev);
+       struct ieee80211_local *local = mpriv->local;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct net_device *odev = NULL;
@@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
 
        if (skb->iif)
                odev = dev_get_by_index(&init_net, skb->iif);
-       if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
+       if (unlikely(odev && !is_ieee80211_device(local, odev))) {
                dev_put(odev);
                odev = NULL;
        }
@@ -1294,20 +1296,16 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
 
        if (ieee80211_vif_is_mesh(&osdata->vif) &&
            ieee80211_is_data(hdr->frame_control)) {
-               if (ieee80211_is_data(hdr->frame_control)) {
-                       if (is_multicast_ether_addr(hdr->addr3))
-                               memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
-                       else
-                               if (mesh_nexthop_lookup(skb, osdata))
-                                       return  0;
-                       if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
-                               IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
-                                                            fwded_frames);
-               }
+               if (is_multicast_ether_addr(hdr->addr3))
+                       memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
+               else
+                       if (mesh_nexthop_lookup(skb, osdata))
+                               return  0;
+               if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
+                       IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
+                                                           fwded_frames);
        } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
                struct ieee80211_sub_if_data *sdata;
-               struct ieee80211_local *local = osdata->local;
-               struct ieee80211_hdr *hdr;
                int hdrlen;
                u16 len_rthdr;
 
@@ -1449,8 +1447,8 @@ fail:
 int ieee80211_subif_start_xmit(struct sk_buff *skb,
                               struct net_device *dev)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        int ret = 1, head_need;
        u16 ethertype, hdrlen,  meshhdrlen = 0;
        __le16 fc;
@@ -1462,7 +1460,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
        struct sta_info *sta;
        u32 sta_flags = 0;
 
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        if (unlikely(skb->len < ETH_HLEN)) {
                ret = 0;
                goto fail;
@@ -1498,18 +1495,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
 #ifdef CONFIG_MAC80211_MESH
        case NL80211_IFTYPE_MESH_POINT:
                fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
-               /* RA TA DA SA */
-               memset(hdr.addr1, 0, ETH_ALEN);
-               memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
                        /* Do not send frames with mesh_ttl == 0 */
                        sdata->u.mesh.mshstats.dropped_frames_ttl++;
                        ret = 0;
                        goto fail;
                }
-               meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
+               memset(&mesh_hdr, 0, sizeof(mesh_hdr));
+
+               if (compare_ether_addr(dev->dev_addr,
+                                         skb->data + ETH_ALEN) == 0) {
+                       /* RA TA DA SA */
+                       memset(hdr.addr1, 0, ETH_ALEN);
+                       memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+                       memcpy(hdr.addr3, skb->data, ETH_ALEN);
+                       memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+                       meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
+               } else {
+                       /* packet from other interface */
+                       struct mesh_path *mppath;
+
+                       memset(hdr.addr1, 0, ETH_ALEN);
+                       memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+                       memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
+
+                       if (is_multicast_ether_addr(skb->data))
+                               memcpy(hdr.addr3, skb->data, ETH_ALEN);
+                       else {
+                               rcu_read_lock();
+                               mppath = mpp_path_lookup(skb->data, sdata);
+                               if (mppath)
+                                       memcpy(hdr.addr3, mppath->mpp, ETH_ALEN);
+                               else
+                                       memset(hdr.addr3, 0xff, ETH_ALEN);
+                               rcu_read_unlock();
+                       }
+
+                       mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
+                       mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
+                       put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
+                       memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
+                       memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
+                       sdata->u.mesh.mesh_seqnum++;
+                       meshhdrlen = 18;
+               }
                hdrlen = 30;
                break;
 #endif
@@ -1923,7 +1952,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
        skb->do_not_encrypt = 1;
 
        info->band = band;
-       rate_control_get_rate(local->mdev, sband, skb, &rsel);
+       rate_control_get_rate(sdata, sband, NULL, skb, &rsel);
 
        if (unlikely(rsel.rate_idx < 0)) {
                if (net_ratelimit()) {
@@ -2032,7 +2061,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
                                cpu_to_le16(IEEE80211_FCTL_MOREDATA);
                }
 
-               if (!ieee80211_tx_prepare(&tx, skb, local->mdev))
+               if (!ieee80211_tx_prepare(local, &tx, skb))
                        break;
                dev_kfree_skb_any(skb);
        }