Merge branches 'x86/urgent', 'x86/amd-iommu', 'x86/apic', 'x86/cleanups', 'x86/core...
[sfrench/cifs-2.6.git] / drivers / net / wireless / zd1211rw / zd_mac.c
index 6d86b365f15078b2f8ae0eb338777ccfed76259a..fcc532bb6a7efe0a13482458ff9572c854ca37aa 100644 (file)
@@ -376,8 +376,6 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
 static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
                           struct ieee80211_hdr *header, u32 flags)
 {
-       u16 fctl = le16_to_cpu(header->frame_control);
-
        /*
         * CONTROL TODO:
         * - if backoff needed, enable bit 0
@@ -395,8 +393,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
                cs->control |= ZD_CS_MULTICAST;
 
        /* PS-POLL */
-       if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) ==
-           (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
+       if (ieee80211_is_pspoll(header->frame_control))
                cs->control |= ZD_CS_PS_POLL_FRAME;
 
        if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
@@ -408,43 +405,66 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
        /* FIXME: Management frame? */
 }
 
-void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
+       int r;
        u32 tmp, j = 0;
        /* 4 more bytes for tail CRC */
        u32 full_len = beacon->len + 4;
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
-       zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
+       if (r < 0)
+               return r;
+       r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+       if (r < 0)
+               return r;
+
        while (tmp & 0x2) {
-               zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+               r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+               if (r < 0)
+                       return r;
                if ((++j % 100) == 0) {
                        printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
                        if (j >= 500)  {
                                printk(KERN_ERR "Giving up beacon config.\n");
-                               return;
+                               return -ETIMEDOUT;
                        }
                }
                msleep(1);
        }
 
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
-       if (zd_chip_is_zd1211b(&mac->chip))
-               zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
+       if (r < 0)
+               return r;
+       if (zd_chip_is_zd1211b(&mac->chip)) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
+               if (r < 0)
+                       return r;
+       }
 
-       for (j = 0 ; j < beacon->len; j++)
-               zd_iowrite32(&mac->chip, CR_BCN_FIFO,
+       for (j = 0 ; j < beacon->len; j++) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
                                *((u8 *)(beacon->data + j)));
+               if (r < 0)
+                       return r;
+       }
 
-       for (j = 0; j < 4; j++)
-               zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
+       for (j = 0; j < 4; j++) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
+               if (r < 0)
+                       return r;
+       }
+
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
+       if (r < 0)
+               return r;
 
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
        /* 802.11b/g 2.4G CCK 1Mb
         * 802.11a, not yet implemented, uses different values (see GPL vendor
         * driver)
         */
-       zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
+       return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
                        (full_len << 19));
 }
 
@@ -550,13 +570,11 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
                      struct ieee80211_rx_status *stats)
 {
-       u16 fc = le16_to_cpu(rx_hdr->frame_control);
        struct sk_buff *skb;
        struct sk_buff_head *q;
        unsigned long flags;
 
-       if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
-           (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
+       if (!ieee80211_is_ack(rx_hdr->frame_control))
                return 0;
 
        q = &zd_hw_mac(hw)->ack_wait_queue;
@@ -584,8 +602,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
        const struct rx_status *status;
        struct sk_buff *skb;
        int bad_frame = 0;
-       u16 fc;
-       bool is_qos, is_4addr, need_padding;
+       __le16 fc;
+       int need_padding;
        int i;
        u8 rate;
 
@@ -644,13 +662,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
                        && !mac->pass_ctrl)
                return 0;
 
-       fc = le16_to_cpu(*((__le16 *) buffer));
-
-       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);
-       need_padding = is_qos ^ is_4addr;
+       fc = *(__le16 *)buffer;
+       need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
 
        skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
        if (skb == NULL)
@@ -694,6 +707,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        mac->type = IEEE80211_IF_TYPE_INVALID;
+       zd_set_beacon_interval(&mac->chip, 0);
        zd_write_mac_addr(&mac->chip, NULL);
 }
 
@@ -709,15 +723,24 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        int associated;
+       int r;
 
        if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
            mac->type == IEEE80211_IF_TYPE_IBSS) {
                associated = true;
-               if (conf->beacon) {
-                       zd_mac_config_beacon(hw, conf->beacon);
-                       kfree_skb(conf->beacon);
-                       zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
+               if (conf->changed & IEEE80211_IFCC_BEACON) {
+                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+
+                       if (!beacon)
+                               return -ENOMEM;
+                       r = zd_mac_config_beacon(hw, beacon);
+                       if (r < 0)
+                               return r;
+                       r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
                                        hw->conf.beacon_int);
+                       if (r < 0)
+                               return r;
+                       kfree_skb(beacon);
                }
        } else
                associated = is_valid_ether_addr(conf->bssid);
@@ -871,17 +894,6 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 }
 
-static int zd_op_beacon_update(struct ieee80211_hw *hw,
-                              struct sk_buff *skb)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       zd_mac_config_beacon(hw, skb);
-       kfree_skb(skb);
-       zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
-                                       hw->conf.beacon_int);
-       return 0;
-}
-
 static const struct ieee80211_ops zd_ops = {
        .tx                     = zd_op_tx,
        .start                  = zd_op_start,
@@ -892,7 +904,6 @@ static const struct ieee80211_ops zd_ops = {
        .config_interface       = zd_op_config_interface,
        .configure_filter       = zd_op_configure_filter,
        .bss_info_changed       = zd_op_bss_info_changed,
-       .beacon_update          = zd_op_beacon_update,
 };
 
 struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)