Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
[safe/jmp/linux-2.6] / drivers / net / wireless / libertas_tf / main.c
index 2c1d680..ba3eb01 100644 (file)
@@ -206,7 +206,7 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
         * there are no buffered multicast frames to send
         */
        ieee80211_stop_queues(priv->hw);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void lbtf_tx_work(struct work_struct *work)
@@ -219,7 +219,7 @@ static void lbtf_tx_work(struct work_struct *work)
        struct sk_buff *skb = NULL;
        int err;
 
-       if ((priv->vif->type == IEEE80211_IF_TYPE_AP) &&
+       if ((priv->vif->type == NL80211_IFTYPE_AP) &&
            (!skb_queue_empty(&priv->bc_ps_buf)))
                skb = skb_dequeue(&priv->bc_ps_buf);
        else if (priv->skb_to_tx) {
@@ -318,45 +318,47 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
 }
 
 static int lbtf_op_add_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_if_init_conf *conf)
+                       struct ieee80211_vif *vif)
 {
        struct lbtf_private *priv = hw->priv;
        if (priv->vif != NULL)
                return -EOPNOTSUPP;
 
-       priv->vif = conf->vif;
-       switch (conf->type) {
-       case IEEE80211_IF_TYPE_MESH_POINT:
-       case IEEE80211_IF_TYPE_AP:
+       priv->vif = vif;
+       switch (vif->type) {
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_AP:
                lbtf_set_mode(priv, LBTF_AP_MODE);
                break;
-       case IEEE80211_IF_TYPE_STA:
+       case NL80211_IFTYPE_STATION:
                lbtf_set_mode(priv, LBTF_STA_MODE);
                break;
        default:
                priv->vif = NULL;
                return -EOPNOTSUPP;
        }
-       lbtf_set_mac_address(priv, (u8 *) conf->mac_addr);
+       lbtf_set_mac_address(priv, (u8 *) vif->addr);
        return 0;
 }
 
 static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_if_init_conf *conf)
+                       struct ieee80211_vif *vif)
 {
        struct lbtf_private *priv = hw->priv;
 
-       if (priv->vif->type == IEEE80211_IF_TYPE_AP ||
-           priv->vif->type == IEEE80211_IF_TYPE_MESH_POINT)
+       if (priv->vif->type == NL80211_IFTYPE_AP ||
+           priv->vif->type == NL80211_IFTYPE_MESH_POINT)
                lbtf_beacon_ctrl(priv, 0, 0);
        lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
        lbtf_set_bssid(priv, 0, NULL);
        priv->vif = NULL;
 }
 
-static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct lbtf_private *priv = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+
        if (conf->channel->center_freq != priv->cur_freq) {
                priv->cur_freq = conf->channel->center_freq;
                lbtf_set_channel(priv, conf->channel->hw_value);
@@ -364,45 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
        return 0;
 }
 
-static int lbtf_op_config_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif,
-                       struct ieee80211_if_conf *conf)
+static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
+                                    int mc_count, struct dev_addr_list *mclist)
 {
        struct lbtf_private *priv = hw->priv;
-       struct sk_buff *beacon;
+       int i;
 
-       switch (priv->vif->type) {
-       case IEEE80211_IF_TYPE_AP:
-       case IEEE80211_IF_TYPE_MESH_POINT:
-               beacon = ieee80211_beacon_get(hw, vif);
-               if (beacon) {
-                       lbtf_beacon_set(priv, beacon);
-                       kfree_skb(beacon);
-                       lbtf_beacon_ctrl(priv, 1, hw->conf.beacon_int);
-               }
-               break;
-       default:
-               break;
-       }
+       if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
+               return mc_count;
 
-       if (conf->bssid) {
-               u8 null_bssid[ETH_ALEN] = {0};
-               bool activate = compare_ether_addr(conf->bssid, null_bssid);
-               lbtf_set_bssid(priv, activate, conf->bssid);
+       priv->nr_of_multicastmacaddr = mc_count;
+       for (i = 0; i < mc_count; i++) {
+               if (!mclist)
+                       break;
+               memcpy(&priv->multicastlist[i], mclist->da_addr,
+                               ETH_ALEN);
+               mclist = mclist->next;
        }
 
-       return 0;
+       return mc_count;
 }
 
 #define SUPPORTED_FIF_FLAGS  (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
 static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
                        unsigned int changed_flags,
                        unsigned int *new_flags,
-                       int mc_count, struct dev_mc_list *mclist)
+                       u64 multicast)
 {
        struct lbtf_private *priv = hw->priv;
        int old_mac_control = priv->mac_control;
-       int i;
        changed_flags &= SUPPORTED_FIF_FLAGS;
        *new_flags &= SUPPORTED_FIF_FLAGS;
 
@@ -414,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
        else
                priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
        if (*new_flags & (FIF_ALLMULTI) ||
-           mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+           multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
                priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
                priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
-       } else if (mc_count) {
+       } else if (multicast) {
                priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
                priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-               priv->nr_of_multicastmacaddr = mc_count;
-               for (i = 0; i < mc_count; i++) {
-                       if (!mclist)
-                               break;
-                       memcpy(&priv->multicastlist[i], mclist->da_addr,
-                                       ETH_ALEN);
-                       mclist = mclist->next;
-               }
                lbtf_cmd_set_mac_multicast_addr(priv);
        } else {
                priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
@@ -449,6 +433,29 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
                        u32 changes)
 {
        struct lbtf_private *priv = hw->priv;
+       struct sk_buff *beacon;
+
+       if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
+               switch (priv->vif->type) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_MESH_POINT:
+                       beacon = ieee80211_beacon_get(hw, vif);
+                       if (beacon) {
+                               lbtf_beacon_set(priv, beacon);
+                               kfree_skb(beacon);
+                               lbtf_beacon_ctrl(priv, 1,
+                                                bss_conf->beacon_int);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (changes & BSS_CHANGED_BSSID) {
+               bool activate = !is_zero_ether_addr(bss_conf->bssid);
+               lbtf_set_bssid(priv, activate, bss_conf->bssid);
+       }
 
        if (changes & BSS_CHANGED_ERP_PREAMBLE) {
                if (bss_conf->use_short_preamble)
@@ -457,8 +464,6 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
                        priv->preamble = CMD_TYPE_LONG_PREAMBLE;
                lbtf_set_radio_control(priv);
        }
-
-       return;
 }
 
 static const struct ieee80211_ops lbtf_ops = {
@@ -468,7 +473,7 @@ static const struct ieee80211_ops lbtf_ops = {
        .add_interface          = lbtf_op_add_interface,
        .remove_interface       = lbtf_op_remove_interface,
        .config                 = lbtf_op_config,
-       .config_interface       = lbtf_op_config_interface,
+       .prepare_multicast      = lbtf_op_prepare_multicast,
        .configure_filter       = lbtf_op_configure_filter,
        .bss_info_changed       = lbtf_op_bss_info_changed,
 };
@@ -477,9 +482,9 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 {
        struct ieee80211_rx_status stats;
        struct rxpd *prxpd;
-       bool is_qos, is_4addr, is_amsdu, need_padding;
+       int need_padding;
        unsigned int flags;
-       u16 fc, fc_le;
+       struct ieee80211_hdr *hdr;
 
        prxpd = (struct rxpd *) skb->data;
 
@@ -490,32 +495,28 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
        stats.band = IEEE80211_BAND_2GHZ;
        stats.signal = prxpd->snr;
        stats.noise = prxpd->nf;
-       stats.qual = prxpd->snr - prxpd->nf;
        /* Marvell rate index has a hole at value 4 */
        if (prxpd->rx_rate > 4)
                --prxpd->rx_rate;
        stats.rate_idx = prxpd->rx_rate;
        skb_pull(skb, sizeof(struct rxpd));
 
-       fc_le = *((__le16 *) skb->data);
-       fc = le16_to_cpu(fc_le);
+       hdr = (struct ieee80211_hdr *)skb->data;
        flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
 
-       is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
-                (fc & IEEE80211_STYPE_QOS_DATA);
-       is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
-                  (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
-       is_amsdu =  ((fc & 0x8C) == 0x88) &&
-                   (*(skb->data + ieee80211_hdrlen(fc_le) - QOS_CONTROL_LEN)
-                    & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+       need_padding = ieee80211_is_data_qos(hdr->frame_control);
+       need_padding ^= ieee80211_has_a4(hdr->frame_control);
+       need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
+                       (*ieee80211_get_qos_ctl(hdr) &
+                        IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
 
-       need_padding = is_qos ^ is_4addr ^ is_amsdu;
        if (need_padding) {
                memmove(skb->data + 2, skb->data, skb->len);
                skb_reserve(skb, 2);
        }
 
-       ieee80211_rx_irqsafe(priv->hw, skb, &stats);
+       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+       ieee80211_rx_irqsafe(priv->hw, skb);
        return 0;
 }
 EXPORT_SYMBOL_GPL(lbtf_rx);
@@ -594,14 +595,14 @@ EXPORT_SYMBOL_GPL(lbtf_remove_card);
 void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
-       memset(&info->status, 0, sizeof(info->status));
+
+       ieee80211_tx_info_clear_status(info);
        /*
         * Commented out, otherwise we never go beyond 1Mbit/s using mac80211
         * default pid rc algorithm.
         *
         * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
         */
-       info->status.excessive_retries = fail ? 1 : 0;
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
                info->flags |= IEEE80211_TX_STAT_ACK;
        skb_pull(priv->tx_skb, sizeof(struct txpd));
@@ -618,7 +619,7 @@ void lbtf_bcn_sent(struct lbtf_private *priv)
 {
        struct sk_buff *skb = NULL;
 
-       if (priv->vif->type != IEEE80211_IF_TYPE_AP)
+       if (priv->vif->type != NL80211_IFTYPE_AP)
                return;
 
        if (skb_queue_empty(&priv->bc_ps_buf)) {