diff options
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 1796b8c6c5b8..602392628e4e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -530,6 +530,8 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
530 | rx_status.noise = priv->noise; | 530 | rx_status.noise = priv->noise; |
531 | /* XX correct? */ | 531 | /* XX correct? */ |
532 | rx_status.qual = (100 * hdr->rssi) / 127; | 532 | rx_status.qual = (100 * hdr->rssi) / 127; |
533 | if (hdr->rate & 0x10) | ||
534 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
533 | rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? | 535 | rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? |
534 | hdr->rate : (hdr->rate - 4)) & 0xf; | 536 | hdr->rate : (hdr->rate - 4)) & 0xf; |
535 | rx_status.freq = freq; | 537 | rx_status.freq = freq; |
@@ -576,7 +578,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
576 | unsigned long flags; | 578 | unsigned long flags; |
577 | u32 freed = 0, last_addr = priv->rx_start; | 579 | u32 freed = 0, last_addr = priv->rx_start; |
578 | 580 | ||
579 | if (!skb || !dev) | 581 | if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) |
580 | return; | 582 | return; |
581 | 583 | ||
582 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 584 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
@@ -1058,6 +1060,7 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
1058 | break; | 1060 | break; |
1059 | case NL80211_IFTYPE_AP: | 1061 | case NL80211_IFTYPE_AP: |
1060 | case NL80211_IFTYPE_ADHOC: | 1062 | case NL80211_IFTYPE_ADHOC: |
1063 | case NL80211_IFTYPE_MESH_POINT: | ||
1061 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | 1064 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { |
1062 | *aid = 0; | 1065 | *aid = 0; |
1063 | *queue = 3; | 1066 | *queue = 3; |
@@ -1198,7 +1201,10 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1198 | txhdr->key_type = 0; | 1201 | txhdr->key_type = 0; |
1199 | txhdr->key_len = 0; | 1202 | txhdr->key_len = 0; |
1200 | txhdr->hw_queue = queue; | 1203 | txhdr->hw_queue = queue; |
1201 | txhdr->backlog = 32; | 1204 | if (current_queue) |
1205 | txhdr->backlog = current_queue->len; | ||
1206 | else | ||
1207 | txhdr->backlog = 0; | ||
1202 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 1208 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
1203 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? | 1209 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? |
1204 | 2 : info->antenna_sel_tx - 1; | 1210 | 2 : info->antenna_sel_tx - 1; |
@@ -1243,20 +1249,20 @@ static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid) | |||
1243 | setup->rx_antenna = priv->rx_antenna; | 1249 | setup->rx_antenna = priv->rx_antenna; |
1244 | setup->rx_align = 0; | 1250 | setup->rx_align = 0; |
1245 | if (priv->fw_var < 0x500) { | 1251 | if (priv->fw_var < 0x500) { |
1246 | setup->v1.basic_rate_mask = cpu_to_le32(0x15f); | 1252 | setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1247 | memset(setup->v1.rts_rates, 0, 8); | 1253 | memset(setup->v1.rts_rates, 0, 8); |
1248 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); | 1254 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); |
1249 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); | 1255 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); |
1250 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); | 1256 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); |
1251 | setup->v1.wakeup_timer = cpu_to_le16(500); | 1257 | setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer); |
1252 | setup->v1.unalloc0 = cpu_to_le16(0); | 1258 | setup->v1.unalloc0 = cpu_to_le16(0); |
1253 | } else { | 1259 | } else { |
1254 | setup->v2.rx_addr = cpu_to_le32(priv->rx_end); | 1260 | setup->v2.rx_addr = cpu_to_le32(priv->rx_end); |
1255 | setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); | 1261 | setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); |
1256 | setup->v2.rxhw = cpu_to_le16(priv->rxhw); | 1262 | setup->v2.rxhw = cpu_to_le16(priv->rxhw); |
1257 | setup->v2.timer = cpu_to_le16(1000); | 1263 | setup->v2.timer = cpu_to_le16(priv->wakeup_timer); |
1258 | setup->v2.truncate = cpu_to_le16(48896); | 1264 | setup->v2.truncate = cpu_to_le16(48896); |
1259 | setup->v2.basic_rate_mask = cpu_to_le32(0x15f); | 1265 | setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1260 | setup->v2.sbss_offset = 0; | 1266 | setup->v2.sbss_offset = 0; |
1261 | setup->v2.mcast_window = 0; | 1267 | setup->v2.mcast_window = 0; |
1262 | setup->v2.rx_rssi_threshold = 0; | 1268 | setup->v2.rx_rssi_threshold = 0; |
@@ -1342,7 +1348,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, u16 frequency) | |||
1342 | } else { | 1348 | } else { |
1343 | chan->v2.rssical_mul = cpu_to_le16(130); | 1349 | chan->v2.rssical_mul = cpu_to_le16(130); |
1344 | chan->v2.rssical_add = cpu_to_le16(0xfe70); | 1350 | chan->v2.rssical_add = cpu_to_le16(0xfe70); |
1345 | chan->v2.basic_rate_mask = cpu_to_le32(0x15f); | 1351 | chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1346 | memset(chan->v2.rts_rates, 0, 8); | 1352 | memset(chan->v2.rts_rates, 0, 8); |
1347 | } | 1353 | } |
1348 | priv->tx(dev, skb, 1); | 1354 | priv->tx(dev, skb, 1); |
@@ -1518,16 +1524,24 @@ static int p54_start(struct ieee80211_hw *dev) | |||
1518 | 1524 | ||
1519 | mutex_lock(&priv->conf_mutex); | 1525 | mutex_lock(&priv->conf_mutex); |
1520 | err = priv->open(dev); | 1526 | err = priv->open(dev); |
1521 | if (!err) | 1527 | if (err) |
1522 | priv->mode = NL80211_IFTYPE_MONITOR; | 1528 | goto out; |
1523 | P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); | 1529 | P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); |
1524 | P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); | 1530 | P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); |
1525 | P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); | 1531 | P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); |
1526 | P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); | 1532 | P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); |
1527 | err = p54_set_edcf(dev); | 1533 | err = p54_set_edcf(dev); |
1528 | if (!err) | 1534 | if (err) |
1529 | err = p54_init_stats(dev); | 1535 | goto out; |
1536 | err = p54_init_stats(dev); | ||
1537 | if (err) | ||
1538 | goto out; | ||
1539 | err = p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL); | ||
1540 | if (err) | ||
1541 | goto out; | ||
1542 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1530 | 1543 | ||
1544 | out: | ||
1531 | mutex_unlock(&priv->conf_mutex); | 1545 | mutex_unlock(&priv->conf_mutex); |
1532 | return err; | 1546 | return err; |
1533 | } | 1547 | } |
@@ -1547,7 +1561,6 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
1547 | while ((skb = skb_dequeue(&priv->tx_queue))) | 1561 | while ((skb = skb_dequeue(&priv->tx_queue))) |
1548 | kfree_skb(skb); | 1562 | kfree_skb(skb); |
1549 | 1563 | ||
1550 | kfree(priv->cached_beacon); | ||
1551 | priv->cached_beacon = NULL; | 1564 | priv->cached_beacon = NULL; |
1552 | priv->stop(dev); | 1565 | priv->stop(dev); |
1553 | priv->tsf_high32 = priv->tsf_low32 = 0; | 1566 | priv->tsf_high32 = priv->tsf_low32 = 0; |
@@ -1570,6 +1583,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
1570 | case NL80211_IFTYPE_STATION: | 1583 | case NL80211_IFTYPE_STATION: |
1571 | case NL80211_IFTYPE_ADHOC: | 1584 | case NL80211_IFTYPE_ADHOC: |
1572 | case NL80211_IFTYPE_AP: | 1585 | case NL80211_IFTYPE_AP: |
1586 | case NL80211_IFTYPE_MESH_POINT: | ||
1573 | priv->mode = conf->type; | 1587 | priv->mode = conf->type; |
1574 | break; | 1588 | break; |
1575 | default: | 1589 | default: |
@@ -1589,6 +1603,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
1589 | p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr); | 1603 | p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr); |
1590 | break; | 1604 | break; |
1591 | case NL80211_IFTYPE_ADHOC: | 1605 | case NL80211_IFTYPE_ADHOC: |
1606 | case NL80211_IFTYPE_MESH_POINT: | ||
1592 | p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL); | 1607 | p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL); |
1593 | break; | 1608 | break; |
1594 | default: | 1609 | default: |
@@ -1653,6 +1668,7 @@ static int p54_config_interface(struct ieee80211_hw *dev, | |||
1653 | break; | 1668 | break; |
1654 | case NL80211_IFTYPE_AP: | 1669 | case NL80211_IFTYPE_AP: |
1655 | case NL80211_IFTYPE_ADHOC: | 1670 | case NL80211_IFTYPE_ADHOC: |
1671 | case NL80211_IFTYPE_MESH_POINT: | ||
1656 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | 1672 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); |
1657 | ret = p54_set_freq(dev, dev->conf.channel->center_freq); | 1673 | ret = p54_set_freq(dev, dev->conf.channel->center_freq); |
1658 | if (ret) | 1674 | if (ret) |
@@ -1712,10 +1728,9 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
1712 | if ((params) && !(queue > 4)) { | 1728 | if ((params) && !(queue > 4)) { |
1713 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, | 1729 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, |
1714 | params->cw_min, params->cw_max, params->txop); | 1730 | params->cw_min, params->cw_max, params->txop); |
1731 | ret = p54_set_edcf(dev); | ||
1715 | } else | 1732 | } else |
1716 | ret = -EINVAL; | 1733 | ret = -EINVAL; |
1717 | if (!ret) | ||
1718 | ret = p54_set_edcf(dev); | ||
1719 | mutex_unlock(&priv->conf_mutex); | 1734 | mutex_unlock(&priv->conf_mutex); |
1720 | return ret; | 1735 | return ret; |
1721 | } | 1736 | } |
@@ -1792,6 +1807,24 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, | |||
1792 | priv->use_short_slot = info->use_short_slot; | 1807 | priv->use_short_slot = info->use_short_slot; |
1793 | p54_set_edcf(dev); | 1808 | p54_set_edcf(dev); |
1794 | } | 1809 | } |
1810 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1811 | if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) | ||
1812 | priv->basic_rate_mask = (info->basic_rates << 4); | ||
1813 | else | ||
1814 | priv->basic_rate_mask = info->basic_rates; | ||
1815 | p54_setup_mac(dev, priv->mac_mode, priv->bssid); | ||
1816 | if (priv->fw_var >= 0x500) | ||
1817 | p54_set_freq(dev, dev->conf.channel->center_freq); | ||
1818 | } | ||
1819 | if (changed & BSS_CHANGED_ASSOC) { | ||
1820 | if (info->assoc) { | ||
1821 | priv->aid = info->aid; | ||
1822 | priv->wakeup_timer = info->beacon_int * | ||
1823 | info->dtim_period * 5; | ||
1824 | p54_setup_mac(dev, priv->mac_mode, priv->bssid); | ||
1825 | } | ||
1826 | } | ||
1827 | |||
1795 | } | 1828 | } |
1796 | 1829 | ||
1797 | static const struct ieee80211_ops p54_ops = { | 1830 | static const struct ieee80211_ops p54_ops = { |
@@ -1821,14 +1854,16 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
1821 | 1854 | ||
1822 | priv = dev->priv; | 1855 | priv = dev->priv; |
1823 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1856 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
1857 | priv->basic_rate_mask = 0x15f; | ||
1824 | skb_queue_head_init(&priv->tx_queue); | 1858 | skb_queue_head_init(&priv->tx_queue); |
1825 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 1859 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1826 | IEEE80211_HW_SIGNAL_DBM | | 1860 | IEEE80211_HW_SIGNAL_DBM | |
1827 | IEEE80211_HW_NOISE_DBM; | 1861 | IEEE80211_HW_NOISE_DBM; |
1828 | 1862 | ||
1829 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION | | 1863 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1830 | NL80211_IFTYPE_ADHOC | | 1864 | BIT(NL80211_IFTYPE_ADHOC) | |
1831 | NL80211_IFTYPE_AP); | 1865 | BIT(NL80211_IFTYPE_AP) | |
1866 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
1832 | 1867 | ||
1833 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 1868 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
1834 | priv->tx_stats[0].limit = 1; /* Beacon queue */ | 1869 | priv->tx_stats[0].limit = 1; /* Beacon queue */ |