diff --git a/[refs] b/[refs] index 0c4e9595d74c..22102bbe49de 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5423b2ed25993e13009ce39f55d742c3c6d03edb +refs/heads/master: 7d283aee50351ec19eaf654a8690d77c4e1dff50 diff --git a/trunk/drivers/dma/ioat_dma.c b/trunk/drivers/dma/ioat_dma.c index a52156e56886..bc8c6e3470ca 100644 --- a/trunk/drivers/dma/ioat_dma.c +++ b/trunk/drivers/dma/ioat_dma.c @@ -551,7 +551,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) /* write address into NextDescriptor field of last desc in chain */ to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->async_tx.phys; - __list_splice(&new_chain, ioat_chan->used_desc.prev); + list_splice_tail(&new_chain, &ioat_chan->used_desc); ioat_chan->dmacount += desc_count; ioat_chan->pending += desc_count; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index ed09e48b1b61..b8407d5704a1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2719,7 +2719,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MACDUMP("enter\n"); + IWL_DEBUG_MAC80211("enter\n"); if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { IWL_DEBUG_MAC80211("leave - monitor\n"); @@ -2733,7 +2733,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (iwl_tx_skb(priv, skb)) dev_kfree_skb_any(skb); - IWL_DEBUG_MACDUMP("leave\n"); + IWL_DEBUG_MAC80211("leave\n"); return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h index d2daa174df22..b4ffd33ef98c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -114,7 +114,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_MAC80211 (1 << 1) #define IWL_DL_HOST_COMMAND (1 << 2) #define IWL_DL_STATE (1 << 3) -#define IWL_DL_MACDUMP (1 << 4) + #define IWL_DL_RADIO (1 << 7) #define IWL_DL_POWER (1 << 8) #define IWL_DL_TEMP (1 << 9) @@ -154,7 +154,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) #define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) #define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) #define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c index 4108c7c8f00f..aa98c76d8195 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -764,19 +764,20 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_tfd_frame *tfd; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_cmd *out_cmd; - struct iwl_tx_cmd *tx_cmd; - int swq_id, txq_id; + u32 *control_flags; + int txq_id = skb_get_queue_mapping(skb); + struct iwl_tx_queue *txq = NULL; + struct iwl_queue *q = NULL; dma_addr_t phys_addr; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; + struct iwl_cmd *out_cmd = NULL; + struct iwl_tx_cmd *tx_cmd; u16 len, idx, len_org; u16 seq_number = 0; - __le16 fc; - u8 hdr_len, unicast; + u8 id, hdr_len, unicast; u8 sta_id; + __le16 fc; u8 wait_write_ptr = 0; u8 tid = 0; u8 *qc = NULL; @@ -801,6 +802,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } unicast = !is_multicast_ether_addr(hdr->addr1); + id = 0; fc = hdr->frame_control; @@ -838,16 +840,14 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX("station Id %d\n", sta_id); - swq_id = skb_get_queue_mapping(skb); - txq_id = swq_id; if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; - seq_number = priv->stations[sta_id].tid[tid].seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - __constant_cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number = priv->stations[sta_id].tid[tid].seq_number & + IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = cpu_to_le16(seq_number) | + (hdr->seq_ctrl & + __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); seq_number += 0x10; /* aggregation is on for this */ if (info->flags & IEEE80211_TX_CTL_AMPDU) @@ -864,6 +864,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Set up first empty TFD within this queue's circular TFD buffer */ tfd = &txq->bd[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); + control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, 0); /* Set up driver data for this TFD */ @@ -982,7 +983,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); } else { - ieee80211_stop_queue(priv->hw, swq_id); + ieee80211_stop_queue(priv->hw, + skb_get_queue_mapping(skb)); } } @@ -1011,12 +1013,13 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; struct iwl_tfd_frame *tfd; + u32 *control_flags; struct iwl_cmd *out_cmd; - dma_addr_t phys_addr; - unsigned long flags; - int len, ret; u32 idx; u16 fix_size; + dma_addr_t phys_addr; + int len, ret; + unsigned long flags; cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); @@ -1042,6 +1045,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) tfd = &txq->bd[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); + control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; diff --git a/trunk/drivers/net/wireless/p54/p54.h b/trunk/drivers/net/wireless/p54/p54.h index 4801a363507b..cac9a515b82d 100644 --- a/trunk/drivers/net/wireless/p54/p54.h +++ b/trunk/drivers/net/wireless/p54/p54.h @@ -52,7 +52,6 @@ struct p54_common { int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); int mode; - u16 seqno; struct mutex conf_mutex; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; diff --git a/trunk/drivers/net/wireless/p54/p54common.c b/trunk/drivers/net/wireless/p54/p54common.c index 83cd85e1f847..4da89ea9b561 100644 --- a/trunk/drivers/net/wireless/p54/p54common.c +++ b/trunk/drivers/net/wireless/p54/p54common.c @@ -553,7 +553,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_queue_stats *current_queue; struct p54_common *priv = dev->priv; struct p54_control_hdr *hdr; - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; struct p54_tx_control_allocdata *txhdr; size_t padding, len; u8 rate; @@ -606,19 +605,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) if (padding) txhdr->align[0] = padding; - /* FIXME: The sequence that follows is needed for this driver to - * work with mac80211 since "mac80211: fix TX sequence numbers". - * As with the temporary code in rt2x00, changes will be needed - * to get proper sequence numbers on beacons. In addition, this - * patch places the sequence number in the hardware state, which - * limits us to a single virtual state. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } /* modifies skb->cb and with it info, so must be last! */ p54_assign_address(dev, skb, hdr, skb->len); @@ -817,8 +803,8 @@ static void p54_set_vdcf(struct ieee80211_hw *dev) if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) { vdcf->slottime = 9; - vdcf->magic1 = 0x10; - vdcf->magic2 = 0x00; + vdcf->magic1 = 0x00; + vdcf->magic2 = 0x10; } else { vdcf->slottime = 20; vdcf->magic1 = 0x0a; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index d06507388635..bd422fd6a894 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -203,43 +203,23 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, !test_bit(DEVICE_STARTED, &rt2x00dev->flags)) return -ENODEV; - switch (conf->type) { - case IEEE80211_IF_TYPE_AP: - /* - * We don't support mixed combinations of - * sta and ap interfaces. - */ - if (rt2x00dev->intf_sta_count) - return -ENOBUFS; - - /* - * Check if we exceeded the maximum amount - * of supported interfaces. - */ - if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) - return -ENOBUFS; - - break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - /* - * We don't support mixed combinations of - * sta and ap interfaces. - */ - if (rt2x00dev->intf_ap_count) - return -ENOBUFS; - - /* - * Check if we exceeded the maximum amount - * of supported interfaces. - */ - if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) - return -ENOBUFS; - - break; - default: - return -EINVAL; - } + /* + * We don't support mixed combinations of sta and ap virtual + * interfaces. We can only add this interface when the rival + * interface count is 0. + */ + if ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) || + (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount of supported interfaces. + */ + if ((conf->type == IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) || + (conf->type != IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf)) + return -ENOBUFS; /* * Loop through all beacon queues to find a free diff --git a/trunk/drivers/usb/host/ehci-q.c b/trunk/drivers/usb/host/ehci-q.c index 2622b6596d7c..3712b925b315 100644 --- a/trunk/drivers/usb/host/ehci-q.c +++ b/trunk/drivers/usb/host/ehci-q.c @@ -932,7 +932,7 @@ static struct ehci_qh *qh_append_tds ( list_del (&qtd->qtd_list); list_add (&dummy->qtd_list, qtd_list); - __list_splice (qtd_list, qh->qtd_list.prev); + list_splice_tail(qtd_list, &qh->qtd_list); ehci_qtd_init(ehci, qtd, qtd->qtd_dma); qh->dummy = qtd; diff --git a/trunk/include/linux/list.h b/trunk/include/linux/list.h index 453916bc0412..a886f27a1181 100644 --- a/trunk/include/linux/list.h +++ b/trunk/include/linux/list.h @@ -215,21 +215,21 @@ static inline int list_is_singular(const struct list_head *head) } static inline void __list_splice(const struct list_head *list, - struct list_head *head) + struct list_head *prev, + struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; - struct list_head *at = head->next; - first->prev = head; - head->next = first; + first->prev = prev; + prev->next = first; - last->next = at; - at->prev = last; + last->next = next; + next->prev = last; } /** - * list_splice - join two lists + * list_splice - join two lists, this is designed for stacks * @list: the new list to add. * @head: the place to add it in the first list. */ @@ -237,7 +237,19 @@ static inline void list_splice(const struct list_head *list, struct list_head *head) { if (!list_empty(list)) - __list_splice(list, head); + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); } /** @@ -251,7 +263,24 @@ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { - __list_splice(list, head); + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists, each list being a queue, and + * reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); INIT_LIST_HEAD(list); } } diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index aa5a191598c9..0c02c471bca2 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -245,13 +245,10 @@ static int ieee80211_open(struct net_device *dev) case IEEE80211_IF_TYPE_AP: sdata->bss = &sdata->u.ap; break; - case IEEE80211_IF_TYPE_MESH_POINT: - /* mesh ifaces must set allmulti to forward mcast traffic */ - atomic_inc(&local->iff_allmultis); - break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_MNTR: case IEEE80211_IF_TYPE_IBSS: + case IEEE80211_IF_TYPE_MESH_POINT: /* no special treatment */ break; case IEEE80211_IF_TYPE_INVALID: @@ -498,9 +495,6 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_unlock_bh(local->mdev); break; case IEEE80211_IF_TYPE_MESH_POINT: - /* allmulti is always set on mesh ifaces */ - atomic_dec(&local->iff_allmultis); - /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata->u.sta.state = IEEE80211_DISABLED; diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 7495fbb0d211..669eafafe497 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -214,7 +214,8 @@ void ieee80211s_stop(void); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); +int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, + struct net_device *dev); void mesh_path_start_discovery(struct net_device *dev); struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); @@ -285,4 +286,6 @@ static inline void mesh_path_activate(struct mesh_path *mpath) #define mesh_allocated 0 #endif +#define MESH_PREQ(skb) (skb->cb + 30) + #endif /* IEEE80211S_H */ diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index 08aca446ca01..7fa149e230e6 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -758,30 +758,29 @@ void mesh_path_start_discovery(struct net_device *dev) /** * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame * - * @skb: 802.11 frame to be sent + * @next_hop: output argument for next hop address + * @skb: frame to be sent * @dev: network device the frame will be sent through - * @fwd_frame: true if this frame was originally from a different host * * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is * found, the function will start a path discovery and queue the frame so it is * sent when the path is resolved. This means the caller must not free the skb * in this case. */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) +int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, + struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 *dst_addr = hdr->addr3; int err = 0; rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(skb->data, dev); if (!mpath) { - mesh_path_add(dst_addr, dev); - mpath = mesh_path_lookup(dst_addr, dev); + mesh_path_add(skb->data, dev); + mpath = mesh_path_lookup(skb->data, dev); if (!mpath) { dev_kfree_skb(skb); sdata->u.sta.mshstats.dropped_frames_no_route++; @@ -793,13 +792,13 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) - && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) + && skb->pkt_type != PACKET_OTHERHOST && !(mpath->flags & MESH_PATH_RESOLVING) && !(mpath->flags & MESH_PATH_FIXED)) { mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - memcpy(hdr->addr1, mpath->next_hop->addr, + memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); } else { if (!(mpath->flags & MESH_PATH_RESOLVING)) { diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index 838ee60492ad..5f88a2e6ee50 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -388,15 +388,18 @@ void mesh_path_tx_pending(struct mesh_path *mpath) void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct mesh_path *mpath; u32 dsn = 0; - if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { + if (skb->pkt_type == PACKET_OTHERHOST) { + struct ieee80211s_hdr *prev_meshhdr; + int mshhdrlen; u8 *ra, *da; - da = hdr->addr3; - ra = hdr->addr2; + prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); + mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); + da = skb->data; + ra = MESH_PREQ(skb); mpath = mesh_path_lookup(da, dev); if (mpath) dsn = ++mpath->dsn; diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 6db854505193..6d9ae67c27ca 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -1109,9 +1109,20 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) hdrlen = ieee80211_get_hdrlen(fc); - if (ieee80211_vif_is_mesh(&sdata->vif)) - hdrlen += ieee80211_get_mesh_hdrlen( + if (ieee80211_vif_is_mesh(&sdata->vif)) { + int meshhdrlen = ieee80211_get_mesh_hdrlen( (struct ieee80211s_hdr *) (skb->data + hdrlen)); + /* Copy on cb: + * - mesh header: to be used for mesh forwarding + * decision. It will also be used as mesh header template at + * tx.c:ieee80211_subif_start_xmit() if interface + * type is mesh and skb->pkt_type == PACKET_OTHERHOST + * - ta: to be used if a RERR needs to be sent. + */ + memcpy(skb->cb, skb->data + hdrlen, meshhdrlen); + memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN); + hdrlen += meshhdrlen; + } /* convert IEEE 802.11 header + possible LLC headers into Ethernet * header @@ -1258,6 +1269,38 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) } } + /* Mesh forwarding */ + if (ieee80211_vif_is_mesh(&sdata->vif)) { + u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl; + (*mesh_ttl)--; + + if (is_multicast_ether_addr(skb->data)) { + if (*mesh_ttl > 0) { + xmit_skb = skb_copy(skb, GFP_ATOMIC); + if (xmit_skb) + xmit_skb->pkt_type = PACKET_OTHERHOST; + else if (net_ratelimit()) + printk(KERN_DEBUG "%s: failed to clone " + "multicast frame\n", dev->name); + } else + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, + dropped_frames_ttl); + } else if (skb->pkt_type != PACKET_OTHERHOST && + compare_ether_addr(dev->dev_addr, skb->data) != 0) { + if (*mesh_ttl == 0) { + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, + dropped_frames_ttl); + dev_kfree_skb(skb); + skb = NULL; + } else { + xmit_skb = skb; + xmit_skb->pkt_type = PACKET_OTHERHOST; + if (!(dev->flags & IFF_PROMISC)) + skb = NULL; + } + } + } + if (skb) { /* deliver to local stack */ skb->protocol = eth_type_trans(skb, dev); @@ -1387,63 +1430,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) return RX_QUEUED; } -static ieee80211_rx_result debug_noinline -ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) -{ - struct ieee80211_hdr *hdr; - struct ieee80211s_hdr *mesh_hdr; - unsigned int hdrlen; - struct sk_buff *skb = rx->skb, *fwd_skb; - - hdr = (struct ieee80211_hdr *) skb->data; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - - if (!ieee80211_is_data(hdr->frame_control)) - return RX_CONTINUE; - - if (!mesh_hdr->ttl) - /* illegal frame */ - return RX_DROP_MONITOR; - - if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) - return RX_CONTINUE; - - mesh_hdr->ttl--; - - if (rx->flags & IEEE80211_RX_RA_MATCH) { - if (!mesh_hdr->ttl) - IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, - dropped_frames_ttl); - else { - struct ieee80211_hdr *fwd_hdr; - fwd_skb = skb_copy(skb, GFP_ATOMIC); - - if (!fwd_skb && net_ratelimit()) - printk(KERN_DEBUG "%s: failed to clone mesh frame\n", - rx->dev->name); - - fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; - /* - * Save TA to addr1 to send TA a path error if a - * suitable next hop is not found - */ - memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); - memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); - fwd_skb->dev = rx->local->mdev; - fwd_skb->iif = rx->dev->ifindex; - dev_queue_xmit(fwd_skb); - } - } - - if (is_multicast_ether_addr(hdr->addr3) || - rx->dev->flags & IFF_PROMISC) - return RX_CONTINUE; - else - return RX_DROP_MONITOR; -} - - static ieee80211_rx_result debug_noinline ieee80211_rx_h_data(struct ieee80211_rx_data *rx) { @@ -1677,12 +1663,10 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, rx->sdata = sdata; rx->dev = sdata->dev; -#define CALL_RXH(rxh) \ - do { \ - res = rxh(rx); \ - if (res != RX_CONTINUE) \ - goto rxh_done; \ - } while (0); +#define CALL_RXH(rxh) \ + res = rxh(rx); \ + if (res != RX_CONTINUE) \ + goto rxh_done; CALL_RXH(ieee80211_rx_h_passive_scan) CALL_RXH(ieee80211_rx_h_check) @@ -1694,8 +1678,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, /* must be after MMIC verify so header is counted in MPDU mic */ CALL_RXH(ieee80211_rx_h_remove_qos_control) CALL_RXH(ieee80211_rx_h_amsdu) - if (ieee80211_vif_is_mesh(&sdata->vif)) - CALL_RXH(ieee80211_rx_h_mesh_fwding); CALL_RXH(ieee80211_rx_h_data) CALL_RXH(ieee80211_rx_h_ctrl) CALL_RXH(ieee80211_rx_h_mgmt) diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 4788f7b91f49..771ec68b848d 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1301,7 +1301,6 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct net_device *odev = NULL; struct ieee80211_sub_if_data *osdata; int headroom; @@ -1329,20 +1328,6 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, osdata = IEEE80211_DEV_TO_SUB_IF(odev); - 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, odev)) - return 0; - if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) - IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, - fwded_frames); - } - } - may_encrypt = !skb->do_not_encrypt; headroom = osdata->local->tx_headroom; @@ -1487,17 +1472,30 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, case IEEE80211_IF_TYPE_MESH_POINT: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ - memset(hdr.addr1, 0, ETH_ALEN); + if (is_multicast_ether_addr(skb->data)) + memcpy(hdr.addr1, skb->data, ETH_ALEN); + else if (mesh_nexthop_lookup(hdr.addr1, skb, dev)) + return 0; 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.sta.mshcfg.dot11MeshTTL) { - /* Do not send frames with mesh_ttl == 0 */ - sdata->u.sta.mshstats.dropped_frames_ttl++; - ret = 0; - goto fail; + if (skb->pkt_type == PACKET_OTHERHOST) { + /* Forwarded frame, keep mesh ttl and seqnum */ + struct ieee80211s_hdr *prev_meshhdr; + prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); + meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); + memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen); + sdata->u.sta.mshstats.fwded_frames++; + } else { + if (!sdata->u.sta.mshcfg.dot11MeshTTL) { + /* Do not send frames with mesh_ttl == 0 */ + sdata->u.sta.mshstats.dropped_frames_ttl++; + ret = 0; + goto fail; + } + meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, + sdata); } - meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); hdrlen = 30; break; #endif @@ -1545,8 +1543,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, * Drop unicast frames to unauthorised stations unless they are * EAPOL frames from the local station. */ - if (!ieee80211_vif_is_mesh(&sdata->vif) && - unlikely(!is_multicast_ether_addr(hdr.addr1) && + if (unlikely(!is_multicast_ether_addr(hdr.addr1) && !(sta_flags & WLAN_STA_AUTHORIZED) && !(ethertype == ETH_P_PAE && compare_ether_addr(dev->dev_addr,