firmware-utils/mktplinkfw: add support for the TL-MR3220 v1
[openwrt.git] / package / madwifi / patches / 370-wdsvap.patch
index f35e657..8a0e823 100644 (file)
  
        if (ic->ic_dev->flags & IFF_RUNNING) {
                /* needs to disable hardware too */
-@@ -1271,8 +1269,11 @@ ath_vap_create(struct ieee80211com *ic, 
+@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic,
                } else
                        ic_opmode = opmode;
                break;
 -      case IEEE80211_M_HOSTAP:
        case IEEE80211_M_WDS:
++              ic_opmode = ic->ic_opmode;
 +              if (!master)
 +                      return NULL;
 +              break;
@@ -57,7 +58,7 @@
                /* permit multiple APs and/or WDS links */
                /* XXX sta+ap for repeater/bridge application */
                if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))
-@@ -1304,7 +1305,7 @@ ath_vap_create(struct ieee80211com *ic, 
+@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic,
        }
  
        avp = dev->priv;
@@ -66,7 +67,7 @@
        /* override with driver methods */
        vap = &avp->av_vap;
        avp->av_newstate = vap->iv_newstate;
-@@ -4209,8 +4210,7 @@ ath_calcrxfilter(struct ath_softc *sc)
+@@ -4209,8 +4211,7 @@ ath_calcrxfilter(struct ath_softc *sc)
        if (ic->ic_opmode == IEEE80211_M_STA ||
            sc->sc_opmode == HAL_M_IBSS ||      /* NB: AHDEMO too */
            (sc->sc_nostabeacons) || sc->sc_scanning ||
@@ -76,7 +77,7 @@
                rfilt |= HAL_RX_FILTER_BEACON;
        if (sc->sc_nmonvaps > 0)
                rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
-@@ -9030,8 +9030,6 @@ ath_calibrate(unsigned long arg)
+@@ -9032,8 +9033,6 @@ ath_calibrate(unsigned long arg)
                 * set sc->beacons if we might need to restart
                   * them after ath_reset. */
                if (!sc->sc_beacons &&
  {
  #define       IEEE80211_C_OPMODE \
        (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \
-@@ -510,9 +525,18 @@ ieee80211_vap_setup(struct ieee80211com 
+@@ -510,9 +525,18 @@ ieee80211_vap_setup(struct ieee80211com
  
        vap->iv_monitor_crc_errors = 0;
        vap->iv_monitor_phy_errors = 0;
  
        switch (cmd) {
        case SIOCG80211STATS:
-@@ -5921,8 +5922,20 @@ ieee80211_ioctl(struct net_device *dev, 
+@@ -5921,8 +5922,20 @@ ieee80211_ioctl(struct net_device *dev,
        case SIOC80211IFDESTROY:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                        }
                        break;
                case IEEE80211_M_IBSS:
-@@ -540,16 +548,32 @@ ieee80211_input(struct ieee80211vap * va
+@@ -540,16 +548,28 @@ ieee80211_input(struct ieee80211vap * va
                                vap->iv_stats.is_rx_notassoc++;
                                goto err;
                        }
-+
-+                      /* subif isn't fully set up yet, drop the frame */
-+                      if (ni->ni_subif == ni->ni_vap)
-+                              goto err;
 +
                        /*
                         * If we're a 4 address packet, make sure we have an entry in
  
                                if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) {
                                        IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
-@@ -557,7 +581,6 @@ ieee80211_input(struct ieee80211vap * va
+@@ -557,7 +577,6 @@ ieee80211_input(struct ieee80211vap * va
                                        goto err;
                                }
                                wh4 = (struct ieee80211_frame_addr4 *)skb->data;
                                ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4);
                                /* Last call increments ref count if !NULL */
                                if ((ni_wds != NULL) && (ni_wds != ni)) {
-@@ -608,6 +631,11 @@ ieee80211_input(struct ieee80211vap * va
+@@ -608,6 +627,11 @@ ieee80211_input(struct ieee80211vap * va
                        goto out;
                }
  
                /*
                 * Handle privacy requirements.  Note that we
                 * must not be preempted from here until after
-@@ -680,8 +708,12 @@ ieee80211_input(struct ieee80211vap * va
+@@ -680,8 +704,12 @@ ieee80211_input(struct ieee80211vap * va
                if (! accept_data_frame(vap, ni, key, skb, eh))
                        goto out;
  
                IEEE80211_NODE_STAT(ni, rx_data);
                IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len);
                ic->ic_lastdata = jiffies;
-@@ -1114,6 +1146,13 @@ ieee80211_deliver_data(struct ieee80211_
+@@ -1114,6 +1142,18 @@ ieee80211_deliver_data(struct ieee80211_
                dev = vap->iv_xrvap->iv_dev;
  #endif
  
 +      /* if the node has a wds subif, move data frames there,
 +       * but keep EAP traffic on the master */
 +      if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE))) {
-+              vap = ni->ni_subif;
-+              dev = vap->iv_dev;
++              if (ni->ni_vap == ni->ni_subif) {
++                      ieee80211_dev_kfree_skb(&skb);
++                      return;
++              } else {
++                      vap = ni->ni_subif;
++                      dev = vap->iv_dev;
++              }
 +      }
 +
        /* perform as a bridge within the vap */
        /* XXX intra-vap bridging only */
        if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
-@@ -1139,7 +1178,16 @@ ieee80211_deliver_data(struct ieee80211_
+@@ -1139,7 +1179,16 @@ ieee80211_deliver_data(struct ieee80211_
                        if (ni1 != NULL) {
                                if (ni1->ni_vap == vap &&
                                    ieee80211_node_is_authorized(ni1) &&
                                        skb1 = skb;
                                        skb = NULL;
                                }
-@@ -3084,8 +3132,7 @@ ieee80211_recv_mgmt(struct ieee80211vap 
+@@ -3084,8 +3133,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
                    (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
                    (vap->iv_opmode == IEEE80211_M_IBSS) ||
                        ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
                        vap->iv_stats.is_rx_mgtdiscard++;
                        return;
                }
-@@ -3471,13 +3518,54 @@ ieee80211_recv_mgmt(struct ieee80211vap 
+@@ -3471,13 +3519,56 @@ ieee80211_recv_mgmt(struct ieee80211vap
                 */
                if (ic->ic_flags & IEEE80211_F_SCAN) {
                        ieee80211_add_scan(vap, &scan, wh, subtype, rssi, rtsf);
 +                               (vap->iv_opmode == IEEE80211_M_WDS)) &&
 +                              (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
 +                      struct ieee80211vap *avp = NULL;
++                      int found = 0;
 +
 +                      IEEE80211_LOCK_IRQ(vap->iv_ic);
 +                      if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
-+                              int found = 0;
-+
 +                              TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
 +                                      if (!memcmp(avp->wds_mac, wh->i_addr2, IEEE80211_ADDR_LEN)) {
 +                                              if (avp->iv_state != IEEE80211_S_RUN)
 +                                                      continue;
++                                              if (!avp->iv_wdsnode)
++                                                      continue;
 +                                              found = 1;
 +                                              break;
 +                                      }
 +                              }
-+                              if (!found)
-+                                      break;
-+
-+                              ni = ni_or_null = avp->iv_wdsnode;
-+                      } else if (vap->iv_opmode == IEEE80211_M_WDS) {
++                              if (found)
++                                      ni = ni_or_null = avp->iv_wdsnode;
++                      } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
++                              found = 1;
 +                              ni = ni_or_null = vap->iv_wdsnode;
 +                      }
 +                      IEEE80211_UNLOCK_IRQ(vap->iv_ic);
 +
++                      if (!found)
++                              break;
 +
                        if (ni_or_null == NULL) {
 -                              /* Create a new entry in the neighbor table. */
                        } else {
                                /*
                                 * Copy data from beacon to neighbor table.
-@@ -3490,6 +3578,7 @@ ieee80211_recv_mgmt(struct ieee80211vap 
+@@ -3490,6 +3581,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
                                IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
                                memcpy(ni->ni_tstamp.data, scan.tstamp,
                                        sizeof(ni->ni_tstamp));
        ieee80211_node_table_reset(&ic->ic_sta, vap);
        if (vap->iv_bss != NULL) {
                ieee80211_unref_node(&vap->iv_bss);
+@@ -309,7 +314,7 @@ ieee80211_create_ibss(struct ieee80211va
+       /* Check to see if we already have a node for this mac
+        * NB: we gain a node reference here
+        */
+-      ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr);
++      ni = ieee80211_find_txnode(vap, vap->iv_myaddr);
+       if (ni == NULL) {
+               ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
+               IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
 @@ -831,12 +836,18 @@ node_table_leave_locked(struct ieee80211
                LIST_REMOVE(ni, ni_hash);
        }
  }
  
  /* This is overridden by ath_node_alloc in ath/if_ath.c, and so
-@@ -1134,6 +1145,62 @@ ieee80211_alloc_node(struct ieee80211vap
+@@ -1134,6 +1145,65 @@ ieee80211_alloc_node(struct ieee80211vap
        return ni;
  }
  
 +      if (ni->ni_subif)
 +              return;
 +
++      if (!ni->ni_table)
++              return;
++
 +      ieee80211_ref_node(ni);
 +      ni->ni_subif = ni->ni_vap;
 +      IEEE80211_INIT_WORK(&ni->ni_create, ieee80211_wds_do_addif);
  /* Add wds address to the node table */
  int
  #ifdef IEEE80211_DEBUG_REFCNT
-@@ -1553,22 +1620,39 @@ ieee80211_find_rxnode(struct ieee80211co
+@@ -1553,22 +1623,39 @@ ieee80211_find_rxnode(struct ieee80211co
        ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
        struct ieee80211_node_table *nt;
        struct ieee80211_node *ni;
  #endif
        IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
  
-@@ -1596,9 +1680,19 @@ ieee80211_find_txnode_debug(struct ieee8
+@@ -1596,9 +1683,19 @@ ieee80211_find_txnode_debug(struct ieee8
  ieee80211_find_txnode(struct ieee80211vap *vap, const u_int8_t *mac)
  #endif
  {
        /*
         * The destination address should be in the node table
         * unless we are operating in station mode or this is a
-@@ -1669,6 +1763,11 @@ ieee80211_free_node(struct ieee80211_nod
+@@ -1669,6 +1766,11 @@ ieee80211_free_node(struct ieee80211_nod
  {
        struct ieee80211vap *vap = ni->ni_vap;
  
        atomic_dec(&ni->ni_ic->ic_node_counter);
        node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF,
                           1 /* show counter */, 
-@@ -1781,22 +1880,6 @@ restart:
+@@ -1781,22 +1883,6 @@ restart:
                    jiffies > ni->ni_rxfragstamp + HZ) {
                        ieee80211_dev_kfree_skb(&ni->ni_rxfrag);
                }
                ni->ni_inact--;
                if (ni->ni_associd != 0 || isadhoc) {
                        struct ieee80211vap *vap = ni->ni_vap;
-@@ -2263,6 +2346,36 @@ ieee80211_node_leave_11g(struct ieee8021
+@@ -2263,6 +2349,35 @@ ieee80211_node_leave_11g(struct ieee8021
        }
  }
  
 +      struct ieee80211vap *vap;
 +      struct ieee80211com *ic;
 +
++      /* wait for full initialization before we start the teardown
++       * otherwise we could leak interfaces */
++      while (ni->ni_subif == ni->ni_vap)
++              schedule();
++
 +      rtnl_lock();
 +      vap = ni->ni_subif;
 +
-+      /* if addif is waiting for the timer to fire, cancel! */
-+      if (vap == ni->ni_vap) {
-+              ni->ni_subif = NULL;
-+              goto done;
-+      }
-+
 +      if (!vap)
 +              goto done;
 +
  /*
   * Handle bookkeeping for a station/neighbor leaving
   * the bss when operating in ap or adhoc modes.
-@@ -2279,6 +2392,12 @@ ieee80211_node_leave(struct ieee80211_no
+@@ -2279,6 +2394,12 @@ ieee80211_node_leave(struct ieee80211_no
                        ni, "station with aid %d leaves (refcnt %u)",
                        IEEE80211_NODE_AID(ni), atomic_read(&ni->ni_refcnt));
  
        /* calculate priority so drivers can find the TX queue */
        if (ieee80211_classify(ni, skb)) {
                IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
-@@ -334,20 +335,33 @@ void ieee80211_parent_queue_xmit(struct 
+@@ -334,20 +335,33 @@ void ieee80211_parent_queue_xmit(struct
   * constructing a frame as it sets i_fc[1]; other bits can
   * then be or'd in.
   */
 +      struct ieee80211_frame *wh;
 +      int len = sizeof(struct ieee80211_frame);
 +      int opmode = vap->iv_opmode;
++
 +      if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
 +              if ((opmode == IEEE80211_M_STA) &&
 +                      (vap->iv_flags_ext & IEEE80211_FEXT_WDS))
 +                      opmode = IEEE80211_M_WDS;
-+
 +              if (opmode == IEEE80211_M_WDS)
 +                      len = sizeof(struct ieee80211_frame_addr4);
 +      }
                };
 --- a/net80211/ieee80211_proto.c
 +++ b/net80211/ieee80211_proto.c
-@@ -1081,6 +1081,8 @@ ieee80211_init(struct net_device *dev, i
+@@ -979,6 +979,12 @@ ieee80211_init(struct net_device *dev, i
+               "start running (state=%d)\n", vap->iv_state);
++      if (vap->iv_master && vap->iv_master->iv_state == IEEE80211_S_INIT) {
++              int ret = ieee80211_init(vap->iv_master->iv_dev, forcescan);
++              if (ret < 0)
++                      return ret;
++      }
++
+       if ((dev->flags & IFF_RUNNING) == 0) {
+               if (ic->ic_nopened++ == 0 &&
+                   (parent->flags & IFF_RUNNING) == 0)
+@@ -1081,6 +1087,8 @@ ieee80211_init(struct net_device *dev, i
  int
  ieee80211_open(struct net_device *dev)
  {
        return ieee80211_init(dev, 0);
  }
  
-@@ -1090,7 +1092,7 @@ ieee80211_open(struct net_device *dev)
+@@ -1090,7 +1098,7 @@ ieee80211_open(struct net_device *dev)
  void
  ieee80211_start_running(struct ieee80211com *ic)
  {
        struct net_device *dev;
  
        /* XXX locking */
-@@ -1099,6 +1101,16 @@ ieee80211_start_running(struct ieee80211
+@@ -1099,6 +1107,16 @@ ieee80211_start_running(struct ieee80211
                /* NB: avoid recursion */
                if ((dev->flags & IFF_UP) && !(dev->flags & IFF_RUNNING))
                        ieee80211_open(dev);
        }
  }
  EXPORT_SYMBOL(ieee80211_start_running);
-@@ -1116,11 +1128,43 @@ ieee80211_stop(struct net_device *dev)
+@@ -1116,11 +1134,43 @@ ieee80211_stop(struct net_device *dev)
        struct ieee80211vap *vap = dev->priv;
        struct ieee80211com *ic = vap->iv_ic;
        struct net_device *parent = ic->ic_dev;
        ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
        if (dev->flags & IFF_RUNNING) {
                dev->flags &= ~IFF_RUNNING;             /* mark us stopped */
-@@ -1148,7 +1192,7 @@ EXPORT_SYMBOL(ieee80211_stop);
+@@ -1148,7 +1198,7 @@ EXPORT_SYMBOL(ieee80211_stop);
  void
  ieee80211_stop_running(struct ieee80211com *ic)
  {
        struct net_device *dev;
  
        /* XXX locking */
-@@ -1156,6 +1200,12 @@ ieee80211_stop_running(struct ieee80211c
+@@ -1156,6 +1206,12 @@ ieee80211_stop_running(struct ieee80211c
                dev = vap->iv_dev;
                if (dev->flags & IFF_RUNNING)   /* NB: avoid recursion */
                        ieee80211_stop(dev);
        }
  }
  EXPORT_SYMBOL(ieee80211_stop_running);
-@@ -1342,9 +1392,9 @@ ieee80211_new_state(struct ieee80211vap 
+@@ -1342,9 +1398,9 @@ ieee80211_new_state(struct ieee80211vap
        struct ieee80211com *ic = vap->iv_ic;
        int rc;
  
        return rc;
  }
  
-@@ -1557,57 +1607,12 @@ __ieee80211_newstate(struct ieee80211vap
+@@ -1557,57 +1613,12 @@ __ieee80211_newstate(struct ieee80211vap
                switch (ostate) {
                case IEEE80211_S_INIT:
                        if (vap->iv_opmode == IEEE80211_M_MONITOR ||
                                break;
                        }
                        /* fall thru... */
-@@ -1675,6 +1680,7 @@ __ieee80211_newstate(struct ieee80211vap
+@@ -1675,6 +1686,7 @@ __ieee80211_newstate(struct ieee80211vap
                 */
                if (ni->ni_authmode != IEEE80211_AUTH_8021X)
                        ieee80211_node_authorize(ni);
  #ifdef ATH_SUPERG_XR
                /*
                 * fire a timer to bring up XR vap if configured.
-@@ -1808,6 +1814,11 @@ ieee80211_newstate(struct ieee80211vap *
+@@ -1808,6 +1820,11 @@ ieee80211_newstate(struct ieee80211vap *
                          ieee80211_state_name[dstate]);
  
        ieee80211_update_link_status(vap, nstate, ostate);
        switch (nstate) {
        case IEEE80211_S_AUTH:
        case IEEE80211_S_ASSOC:
-@@ -1930,8 +1941,15 @@ ieee80211_newstate(struct ieee80211vap *
+@@ -1930,8 +1947,15 @@ ieee80211_newstate(struct ieee80211vap *
                if (ostate == IEEE80211_S_SCAN || 
                    ostate == IEEE80211_S_AUTH ||
                    ostate == IEEE80211_S_ASSOC) {
This page took 0.042407 seconds and 4 git commands to generate.