Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into wireless-next
This commit is contained in:
commit
96d28e00d5
|
@ -1411,7 +1411,7 @@ F: net/ax25/
|
|||
B43 WIRELESS DRIVER
|
||||
M: Stefano Brivio <stefano.brivio@polimi.it>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: b43-dev@lists.infradead.org (moderated for non-subscribers)
|
||||
L: b43-dev@lists.infradead.org
|
||||
W: http://linuxwireless.org/en/users/Drivers/b43
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/b43/
|
||||
|
@ -1420,6 +1420,7 @@ B43LEGACY WIRELESS DRIVER
|
|||
M: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
M: Stefano Brivio <stefano.brivio@polimi.it>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: b43-dev@lists.infradead.org
|
||||
W: http://linuxwireless.org/en/users/Drivers/b43
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/b43legacy/
|
||||
|
|
|
@ -968,8 +968,7 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
|
|||
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
|
||||
u32 drv_info)
|
||||
static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
int transfer, err;
|
||||
const void *data = hif_dev->firmware->data;
|
||||
|
@ -1000,7 +999,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
|
|||
}
|
||||
kfree(buf);
|
||||
|
||||
if (IS_AR7010_DEVICE(drv_info))
|
||||
if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
|
||||
firm_offset = AR7010_FIRMWARE_TEXT;
|
||||
else
|
||||
firm_offset = AR9271_FIRMWARE_TEXT;
|
||||
|
@ -1021,28 +1020,18 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
|
||||
static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
int ret, idx;
|
||||
struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
|
||||
struct usb_endpoint_descriptor *endp;
|
||||
int ret, idx;
|
||||
|
||||
/* Request firmware */
|
||||
ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
|
||||
&hif_dev->udev->dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name);
|
||||
goto err_fw_req;
|
||||
}
|
||||
|
||||
/* Download firmware */
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev, drv_info);
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s download failed\n",
|
||||
hif_dev->fw_name);
|
||||
goto err_fw_download;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* On downloading the firmware to the target, the USB descriptor of EP4
|
||||
|
@ -1064,23 +1053,84 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
|
|||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Unable to allocate URBs\n");
|
||||
goto err_fw_download;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_fw_download:
|
||||
release_firmware(hif_dev->firmware);
|
||||
err_fw_req:
|
||||
hif_dev->firmware = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
ath9k_hif_usb_dealloc_urbs(hif_dev);
|
||||
if (hif_dev->firmware)
|
||||
release_firmware(hif_dev->firmware);
|
||||
}
|
||||
|
||||
/*
|
||||
* If initialization fails or the FW cannot be retrieved,
|
||||
* detach the device.
|
||||
*/
|
||||
static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
struct device *parent = hif_dev->udev->dev.parent;
|
||||
|
||||
complete(&hif_dev->fw_done);
|
||||
|
||||
if (parent)
|
||||
device_lock(parent);
|
||||
|
||||
device_release_driver(&hif_dev->udev->dev);
|
||||
|
||||
if (parent)
|
||||
device_unlock(parent);
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct hif_device_usb *hif_dev = context;
|
||||
int ret;
|
||||
|
||||
if (!fw) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Failed to get firmware %s\n",
|
||||
hif_dev->fw_name);
|
||||
goto err_fw;
|
||||
}
|
||||
|
||||
hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
|
||||
&hif_dev->udev->dev);
|
||||
if (hif_dev->htc_handle == NULL) {
|
||||
goto err_fw;
|
||||
}
|
||||
|
||||
hif_dev->firmware = fw;
|
||||
|
||||
/* Proceed with initialization */
|
||||
|
||||
ret = ath9k_hif_usb_dev_init(hif_dev);
|
||||
if (ret)
|
||||
goto err_dev_init;
|
||||
|
||||
ret = ath9k_htc_hw_init(hif_dev->htc_handle,
|
||||
&hif_dev->interface->dev,
|
||||
hif_dev->usb_device_id->idProduct,
|
||||
hif_dev->udev->product,
|
||||
hif_dev->usb_device_id->driver_info);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_htc_hw_init;
|
||||
}
|
||||
|
||||
complete(&hif_dev->fw_done);
|
||||
|
||||
return;
|
||||
|
||||
err_htc_hw_init:
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
err_dev_init:
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
release_firmware(fw);
|
||||
hif_dev->firmware = NULL;
|
||||
err_fw:
|
||||
ath9k_hif_usb_firmware_fail(hif_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1155,20 +1205,16 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
}
|
||||
|
||||
usb_get_dev(udev);
|
||||
|
||||
hif_dev->udev = udev;
|
||||
hif_dev->interface = interface;
|
||||
hif_dev->device_id = id->idProduct;
|
||||
hif_dev->usb_device_id = id;
|
||||
#ifdef CONFIG_PM
|
||||
udev->reset_resume = 1;
|
||||
#endif
|
||||
usb_set_intfdata(interface, hif_dev);
|
||||
|
||||
hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
|
||||
&hif_dev->udev->dev);
|
||||
if (hif_dev->htc_handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_htc_hw_alloc;
|
||||
}
|
||||
init_completion(&hif_dev->fw_done);
|
||||
|
||||
/* Find out which firmware to load */
|
||||
|
||||
|
@ -1177,29 +1223,22 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
else
|
||||
hif_dev->fw_name = FIRMWARE_AR9271;
|
||||
|
||||
ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info);
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
|
||||
&hif_dev->udev->dev, GFP_KERNEL,
|
||||
hif_dev, ath9k_hif_usb_firmware_cb);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_hif_init_usb;
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Async request for firmware %s failed\n",
|
||||
hif_dev->fw_name);
|
||||
goto err_fw_req;
|
||||
}
|
||||
|
||||
ret = ath9k_htc_hw_init(hif_dev->htc_handle,
|
||||
&interface->dev, hif_dev->device_id,
|
||||
hif_dev->udev->product, id->driver_info);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_htc_hw_init;
|
||||
}
|
||||
|
||||
dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n");
|
||||
dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
|
||||
hif_dev->fw_name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_htc_hw_init:
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
err_hif_init_usb:
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
err_htc_hw_alloc:
|
||||
err_fw_req:
|
||||
usb_set_intfdata(interface, NULL);
|
||||
kfree(hif_dev);
|
||||
usb_put_dev(udev);
|
||||
|
@ -1234,9 +1273,15 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
|
|||
if (!hif_dev)
|
||||
return;
|
||||
|
||||
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
wait_for_completion(&hif_dev->fw_done);
|
||||
|
||||
if (hif_dev->firmware) {
|
||||
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
release_firmware(hif_dev->firmware);
|
||||
}
|
||||
|
||||
usb_set_intfdata(interface, NULL);
|
||||
|
||||
if (!unplugged && (hif_dev->flags & HIF_USB_START))
|
||||
|
@ -1276,8 +1321,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
|
|||
return ret;
|
||||
|
||||
if (hif_dev->firmware) {
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev,
|
||||
htc_handle->drv_priv->ah->hw_version.usbdev);
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev);
|
||||
if (ret)
|
||||
goto fail_resume;
|
||||
} else {
|
||||
|
|
|
@ -87,10 +87,11 @@ struct cmd_buf {
|
|||
#define HIF_USB_START BIT(0)
|
||||
|
||||
struct hif_device_usb {
|
||||
u16 device_id;
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *interface;
|
||||
const struct usb_device_id *usb_device_id;
|
||||
const struct firmware *firmware;
|
||||
struct completion fw_done;
|
||||
struct htc_target *htc_handle;
|
||||
struct hif_usb_tx tx;
|
||||
struct usb_anchor regout_submitted;
|
||||
|
|
|
@ -340,9 +340,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
|
|||
fastcc = false;
|
||||
|
||||
ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
|
||||
hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
|
||||
CHANNEL_HT40PLUS)),
|
||||
fastcc);
|
||||
hchan->channel, IS_CHAN_HT40(hchan), fastcc);
|
||||
|
||||
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
||||
if (r) {
|
||||
|
|
|
@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
|
|||
return rate;
|
||||
|
||||
/* This should not happen */
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
rate = ath_rc_priv->valid_rate_index[0];
|
||||
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include "wifi.h"
|
||||
#include "rc.h"
|
||||
#include "base.h"
|
||||
|
@ -39,6 +35,9 @@
|
|||
#include "ps.h"
|
||||
#include "regd.h"
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/*
|
||||
*NOTICE!!!: This file will be very big, we hsould
|
||||
*keep it clear under follwing roles:
|
||||
|
@ -411,6 +410,7 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)
|
|||
|
||||
wiphy_rfkill_start_polling(hw->wiphy);
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_init_rfkill);
|
||||
|
||||
void rtl_deinit_rfkill(struct ieee80211_hw *hw)
|
||||
{
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/export.h>
|
||||
#include "wifi.h"
|
||||
#include "cam.h"
|
||||
|
|
|
@ -31,8 +31,50 @@
|
|||
#include "core.h"
|
||||
#include "cam.h"
|
||||
#include "base.h"
|
||||
#include "pci.h"
|
||||
#include "ps.h"
|
||||
|
||||
#include <linux/export.h>
|
||||
|
||||
void rtl_fw_cb(const struct firmware *firmware, void *context)
|
||||
{
|
||||
struct ieee80211_hw *hw = context;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
int err;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
|
||||
"Firmware callback routine entered!\n");
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
if (!firmware) {
|
||||
pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
|
||||
rtlpriv->max_fw_size = 0;
|
||||
return;
|
||||
}
|
||||
if (firmware->size > rtlpriv->max_fw_size) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return;
|
||||
}
|
||||
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
|
||||
rtlpriv->rtlhal.fwsize = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
err = ieee80211_register_hw(hw);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Can't register mac80211 hw\n");
|
||||
return;
|
||||
} else {
|
||||
rtlpriv->mac80211.mac80211_registered = 1;
|
||||
}
|
||||
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
|
||||
|
||||
/*init rfkill */
|
||||
rtl_init_rfkill(hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_fw_cb);
|
||||
|
||||
/*mutex for start & stop is must here. */
|
||||
static int rtl_op_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
|
@ -254,10 +296,12 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
* because that will cause nullfunc send by mac80211
|
||||
* fail, and cause pkt loss, we have tested that 5mA
|
||||
* is worked very well */
|
||||
if (!rtlpriv->psc.multi_buffered)
|
||||
if (!rtlpriv->psc.multi_buffered) {
|
||||
queue_delayed_work(rtlpriv->works.rtl_wq,
|
||||
&rtlpriv->works.ps_work,
|
||||
MSECS(5));
|
||||
pr_info("In section\n");
|
||||
}
|
||||
} else {
|
||||
rtl_swlps_rf_awake(hw);
|
||||
rtlpriv->psc.sw_ps_enabled = false;
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#ifndef __RTL_CORE_H__
|
||||
#define __RTL_CORE_H__
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#define RTL_SUPPORTED_FILTERS \
|
||||
(FIF_PROMISC_IN_BSS | \
|
||||
FIF_ALLMULTI | FIF_CONTROL | \
|
||||
|
@ -42,4 +40,6 @@
|
|||
#define RTL_SUPPORTED_CTRL_FILTER 0xFF
|
||||
|
||||
extern const struct ieee80211_ops rtl_ops;
|
||||
void rtl_fw_cb(const struct firmware *firmware, void *context);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "wifi.h"
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include "core.h"
|
||||
#include "wifi.h"
|
||||
#include "core.h"
|
||||
#include "pci.h"
|
||||
#include "base.h"
|
||||
#include "ps.h"
|
||||
#include "efuse.h"
|
||||
#include <linux/export.h>
|
||||
|
||||
static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
|
||||
PCI_VENDOR_ID_INTEL,
|
||||
|
@ -1565,6 +1565,9 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
|
|||
|
||||
rtlpci->driver_is_goingto_unload = true;
|
||||
rtlpriv->cfg->ops->hw_disable(hw);
|
||||
/* some things are not needed if firmware not available */
|
||||
if (!rtlpriv->max_fw_size)
|
||||
return;
|
||||
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
|
||||
|
||||
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
|
||||
|
@ -1779,6 +1782,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
rtlpriv = hw->priv;
|
||||
pcipriv = (void *)rtlpriv->priv;
|
||||
pcipriv->dev.pdev = pdev;
|
||||
init_completion(&rtlpriv->firmware_loading_complete);
|
||||
|
||||
/* init cfg & intf_ops */
|
||||
rtlpriv->rtlhal.interface = INTF_PCI;
|
||||
|
@ -1799,7 +1803,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
err = pci_request_regions(pdev, KBUILD_MODNAME);
|
||||
if (err) {
|
||||
RT_ASSERT(false, "Can't obtain PCI resources\n");
|
||||
return err;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id);
|
||||
|
@ -1862,15 +1866,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
goto fail3;
|
||||
}
|
||||
|
||||
err = ieee80211_register_hw(hw);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Can't register mac80211 hw\n");
|
||||
goto fail3;
|
||||
} else {
|
||||
rtlpriv->mac80211.mac80211_registered = 1;
|
||||
}
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
|
@ -1878,9 +1873,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
goto fail3;
|
||||
}
|
||||
|
||||
/*init rfkill */
|
||||
rtl_init_rfkill(hw);
|
||||
|
||||
rtlpci = rtl_pcidev(pcipriv);
|
||||
err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
|
||||
IRQF_SHARED, KBUILD_MODNAME, hw);
|
||||
|
@ -1889,24 +1881,22 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
"%s: failed to register IRQ handler\n",
|
||||
wiphy_name(hw->wiphy));
|
||||
goto fail3;
|
||||
} else {
|
||||
rtlpci->irq_alloc = 1;
|
||||
}
|
||||
rtlpci->irq_alloc = 1;
|
||||
|
||||
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
|
||||
return 0;
|
||||
|
||||
fail3:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
rtl_deinit_core(hw);
|
||||
_rtl_pci_io_handler_release(hw);
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
if (rtlpriv->io.pci_mem_start != 0)
|
||||
pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
|
||||
|
||||
fail2:
|
||||
pci_release_regions(pdev);
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
|
||||
fail1:
|
||||
|
||||
|
@ -1925,6 +1915,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
|
|||
struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
||||
struct rtl_mac *rtlmac = rtl_mac(rtlpriv);
|
||||
|
||||
/* just in case driver is removed before firmware callback */
|
||||
wait_for_completion(&rtlpriv->firmware_loading_complete);
|
||||
clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
|
||||
|
||||
sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group);
|
||||
|
|
|
@ -239,7 +239,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
void rtl_pci_disconnect(struct pci_dev *pdev);
|
||||
int rtl_pci_suspend(struct device *dev);
|
||||
int rtl_pci_resume(struct device *dev);
|
||||
|
||||
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
|
||||
{
|
||||
return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
|
|
|
@ -47,7 +47,8 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
|
|||
"Driver is already down!\n");
|
||||
|
||||
/*<2> Enable Adapter */
|
||||
rtlpriv->cfg->ops->hw_init(hw);
|
||||
if (rtlpriv->cfg->ops->hw_init(hw))
|
||||
return 1;
|
||||
RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
|
||||
|
||||
/*<3> Enable Interrupt */
|
||||
|
|
|
@ -27,16 +27,13 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/export.h>
|
||||
#include "../wifi.h"
|
||||
#include "../pci.h"
|
||||
#include "../base.h"
|
||||
#include "../rtl8192ce/reg.h"
|
||||
#include "../rtl8192ce/def.h"
|
||||
#include "fw_common.h"
|
||||
#include <linux/export.h>
|
||||
|
||||
static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
|
||||
{
|
||||
|
@ -260,10 +257,9 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
|
|||
u32 fwsize;
|
||||
enum version_8192c version = rtlhal->version;
|
||||
|
||||
if (!rtlhal->pfirmware)
|
||||
if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
|
||||
return 1;
|
||||
|
||||
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
|
||||
pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
|
||||
pfwdata = (u8 *) rtlhal->pfirmware;
|
||||
fwsize = rtlhal->fwsize;
|
||||
|
@ -515,15 +511,8 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
|
|||
void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
|
||||
u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
|
||||
{
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
u32 tmp_cmdbuf[2];
|
||||
|
||||
if (rtlhal->fw_ready == false) {
|
||||
RT_ASSERT(false,
|
||||
"return H2C cmd because of Fw download fail!!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(tmp_cmdbuf, 0, 8);
|
||||
memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
|
||||
_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "../wifi.h"
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
|
||||
|
|
|
@ -917,10 +917,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
|
|||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"Failed to download FW. Init HW without FW now..\n");
|
||||
err = 1;
|
||||
rtlhal->fw_ready = false;
|
||||
return err;
|
||||
} else {
|
||||
rtlhal->fw_ready = true;
|
||||
}
|
||||
|
||||
rtlhal->last_hmeboxnum = 0;
|
||||
|
@ -1193,7 +1190,6 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
|
|||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
u8 u1b_tmp;
|
||||
u32 u4b_tmp;
|
||||
|
||||
|
@ -1204,7 +1200,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
|
|||
rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
|
||||
if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
|
||||
if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7))
|
||||
rtl92c_firmware_selfreset(hw);
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
|
||||
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../core.h"
|
||||
#include "../pci.h"
|
||||
|
@ -43,6 +40,8 @@
|
|||
#include "trx.h"
|
||||
#include "led.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
@ -92,9 +91,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
|
|||
int err;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
const struct firmware *firmware;
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
char *fw_name = NULL;
|
||||
|
||||
rtl8192ce_bt_reg_init(hw);
|
||||
|
||||
|
@ -166,26 +163,20 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
|
|||
/* request fw */
|
||||
if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
|
||||
!IS_92C_SERIAL(rtlhal->version))
|
||||
fw_name = "rtlwifi/rtl8192cfwU.bin";
|
||||
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
|
||||
else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
fw_name = "rtlwifi/rtl8192cfwU_B.bin";
|
||||
else
|
||||
fw_name = rtlpriv->cfg->fw_name;
|
||||
err = request_firmware(&firmware, fw_name, rtlpriv->io.dev);
|
||||
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
|
||||
|
||||
rtlpriv->max_fw_size = 0x4000;
|
||||
pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Failed to request firmware!\n");
|
||||
return 1;
|
||||
}
|
||||
if (firmware->size > 0x4000) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return 1;
|
||||
}
|
||||
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
|
||||
rtlpriv->rtlhal.fwsize = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../efuse.h"
|
||||
#include "../base.h"
|
||||
|
@ -999,10 +997,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
|
|||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"Failed to download FW. Init HW without FW now..\n");
|
||||
err = 1;
|
||||
rtlhal->fw_ready = false;
|
||||
return err;
|
||||
} else {
|
||||
rtlhal->fw_ready = true;
|
||||
}
|
||||
rtlhal->last_hmeboxnum = 0; /* h2c */
|
||||
_rtl92cu_phy_param_tab_init(hw);
|
||||
|
@ -1096,23 +1091,21 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
|
|||
if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) {
|
||||
/* reset MCU ready status */
|
||||
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
|
||||
if (rtlhal->fw_ready) {
|
||||
/* 8051 reset by self */
|
||||
rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
|
||||
while ((retry_cnts++ < 100) &&
|
||||
(FEN_CPUEN & rtl_read_word(rtlpriv,
|
||||
REG_SYS_FUNC_EN))) {
|
||||
udelay(50);
|
||||
}
|
||||
if (retry_cnts >= 100) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"#####=> 8051 reset failed!.........................\n");
|
||||
/* if 8051 reset fail, reset MAC. */
|
||||
rtl_write_byte(rtlpriv,
|
||||
REG_SYS_FUNC_EN + 1,
|
||||
0x50);
|
||||
udelay(100);
|
||||
}
|
||||
/* 8051 reset by self */
|
||||
rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
|
||||
while ((retry_cnts++ < 100) &&
|
||||
(FEN_CPUEN & rtl_read_word(rtlpriv,
|
||||
REG_SYS_FUNC_EN))) {
|
||||
udelay(50);
|
||||
}
|
||||
if (retry_cnts >= 100) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"#####=> 8051 reset failed!.........................\n");
|
||||
/* if 8051 reset fail, reset MAC. */
|
||||
rtl_write_byte(rtlpriv,
|
||||
REG_SYS_FUNC_EN + 1,
|
||||
0x50);
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
/* Reset MAC and Enable 8051 */
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../pci.h"
|
||||
#include "../usb.h"
|
||||
|
@ -44,6 +40,8 @@
|
|||
#include "mac.h"
|
||||
#include "trx.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
/* macro to shorten lines */
|
||||
|
||||
#define LINK_Q ui_link_quality
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "trx.h"
|
||||
#include "led.h"
|
||||
#include "hw.h"
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
MODULE_AUTHOR("Georgia <georgia@realtek.com>");
|
||||
|
@ -54,7 +53,6 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
|
|||
static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
const struct firmware *firmware;
|
||||
int err;
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = true;
|
||||
|
@ -62,29 +60,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
|||
rtlpriv->dm.disable_framebursting = false;
|
||||
rtlpriv->dm.thermalvalue = 0;
|
||||
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
|
||||
rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
|
||||
|
||||
/* for firmware buf */
|
||||
rtlpriv->rtlhal.pfirmware = vzalloc(0x4000);
|
||||
if (!rtlpriv->rtlhal.pfirmware) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Can't alloc buffer for fw\n");
|
||||
return 1;
|
||||
}
|
||||
/* request fw */
|
||||
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Failed to request firmware!\n");
|
||||
return 1;
|
||||
}
|
||||
if (firmware->size > 0x4000) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return 1;
|
||||
}
|
||||
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
|
||||
rtlpriv->rtlhal.fwsize = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
rtlpriv->max_fw_size = 0x4000;
|
||||
err = request_firmware_nowait(THIS_MODULE, 1,
|
||||
rtlpriv->cfg->fw_name, rtlpriv->io.dev,
|
||||
GFP_KERNEL, hw, rtl_fw_cb);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ int rtl92d_download_fw(struct ieee80211_hw *hw)
|
|||
bool fw_downloaded = false, fwdl_in_process = false;
|
||||
unsigned long flags;
|
||||
|
||||
if (!rtlhal->pfirmware)
|
||||
if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
|
||||
return 1;
|
||||
fwsize = rtlhal->fwsize;
|
||||
pfwheader = (u8 *) rtlhal->pfirmware;
|
||||
|
@ -532,14 +532,8 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
|
|||
void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
|
||||
u8 element_id, u32 cmd_len, u8 *cmdbuffer)
|
||||
{
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
u32 tmp_cmdbuf[2];
|
||||
|
||||
if (rtlhal->fw_ready == false) {
|
||||
RT_ASSERT(false,
|
||||
"return H2C cmd because of Fw download fail!!!\n");
|
||||
return;
|
||||
}
|
||||
memset(tmp_cmdbuf, 0, 8);
|
||||
memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
|
||||
_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
|
||||
|
|
|
@ -931,10 +931,7 @@ int rtl92de_hw_init(struct ieee80211_hw *hw)
|
|||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"Failed to download FW. Init HW without FW..\n");
|
||||
rtlhal->fw_ready = false;
|
||||
return 1;
|
||||
} else {
|
||||
rtlhal->fw_ready = true;
|
||||
}
|
||||
rtlhal->last_hmeboxnum = 0;
|
||||
rtlpriv->psc.fw_current_inpsmode = false;
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../core.h"
|
||||
#include "../pci.h"
|
||||
|
@ -44,6 +39,8 @@
|
|||
#include "trx.h"
|
||||
#include "led.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
@ -94,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
|||
u8 tid;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
const struct firmware *firmware;
|
||||
static int header_print;
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = true;
|
||||
|
@ -170,6 +166,15 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
|||
else if (rtlpriv->psc.reg_fwctrl_lps == 3)
|
||||
rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
|
||||
|
||||
/* for early mode */
|
||||
rtlpriv->rtlhal.earlymode_enable = true;
|
||||
for (tid = 0; tid < 8; tid++)
|
||||
skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
|
||||
|
||||
/* Only load firmware for first MAC */
|
||||
if (header_print)
|
||||
return 0;
|
||||
|
||||
/* for firmware buf */
|
||||
rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
|
||||
if (!rtlpriv->rtlhal.pfirmware) {
|
||||
|
@ -178,33 +183,21 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!header_print) {
|
||||
pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
|
||||
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
|
||||
header_print++;
|
||||
}
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
|
||||
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
|
||||
header_print++;
|
||||
|
||||
/* request fw */
|
||||
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev);
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Failed to request firmware!\n");
|
||||
return 1;
|
||||
}
|
||||
if (firmware->size > 0x8000) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return 1;
|
||||
}
|
||||
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
|
||||
rtlpriv->rtlhal.fwsize = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
/* for early mode */
|
||||
rtlpriv->rtlhal.earlymode_enable = true;
|
||||
for (tid = 0; tid < 8; tid++)
|
||||
skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
|
|||
u8 fwstatus = FW_STATUS_INIT;
|
||||
bool rtstatus = true;
|
||||
|
||||
if (!rtlhal->pfirmware)
|
||||
if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
|
||||
return 1;
|
||||
|
||||
firmware = (struct rt_firmware *)rtlhal->pfirmware;
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../efuse.h"
|
||||
#include "../base.h"
|
||||
|
@ -951,10 +949,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
|
|||
rtstatus = rtl92s_download_fw(hw);
|
||||
if (!rtstatus) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"Failed to download FW. Init HW without FW now... Please copy FW into /lib/firmware/rtlwifi\n");
|
||||
rtlhal->fw_ready = false;
|
||||
} else {
|
||||
rtlhal->fw_ready = true;
|
||||
"Failed to download FW. Init HW without FW now... "
|
||||
"Please copy FW into /lib/firmware/rtlwifi\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* After FW download, we have to reset MAC register */
|
||||
|
@ -1217,9 +1214,14 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
|
|||
|
||||
void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_priv *rtlpriv;
|
||||
struct rtl_pci *rtlpci;
|
||||
|
||||
rtlpriv = rtl_priv(hw);
|
||||
/* if firmware not available, no interrupts */
|
||||
if (!rtlpriv || !rtlpriv->max_fw_size)
|
||||
return;
|
||||
rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
rtl_write_dword(rtlpriv, INTA_MASK, 0);
|
||||
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
|
||||
|
||||
|
|
|
@ -76,10 +76,13 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
|
|||
|
||||
void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_priv *rtlpriv;
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
u8 ledcfg;
|
||||
|
||||
rtlpriv = rtl_priv(hw);
|
||||
if (!rtlpriv || rtlpriv->max_fw_size)
|
||||
return;
|
||||
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
|
||||
LEDCFG, pled->ledpin);
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../pci.h"
|
||||
#include "../ps.h"
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "reg.h"
|
||||
#include "def.h"
|
||||
|
|
|
@ -27,14 +27,11 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "../wifi.h"
|
||||
#include "../core.h"
|
||||
#include "../pci.h"
|
||||
#include "../base.h"
|
||||
#include "../pci.h"
|
||||
#include "reg.h"
|
||||
#include "def.h"
|
||||
#include "phy.h"
|
||||
|
@ -45,6 +42,8 @@
|
|||
#include "trx.h"
|
||||
#include "led.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
@ -89,12 +88,53 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
|
|||
rtlpci->const_support_pciaspm = 2;
|
||||
}
|
||||
|
||||
static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
|
||||
{
|
||||
struct ieee80211_hw *hw = context;
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
|
||||
struct rt_firmware *pfirmware = NULL;
|
||||
int err;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
|
||||
"Firmware callback routine entered!\n");
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
if (!firmware) {
|
||||
pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
|
||||
rtlpriv->max_fw_size = 0;
|
||||
return;
|
||||
}
|
||||
if (firmware->size > rtlpriv->max_fw_size) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return;
|
||||
}
|
||||
pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
|
||||
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
|
||||
pfirmware->sz_fw_tmpbufferlen = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
err = ieee80211_register_hw(hw);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Can't register mac80211 hw\n");
|
||||
return;
|
||||
} else {
|
||||
rtlpriv->mac80211.mac80211_registered = 1;
|
||||
}
|
||||
rtlpci->irq_alloc = 1;
|
||||
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
|
||||
|
||||
/*init rfkill */
|
||||
rtl_init_rfkill(hw);
|
||||
}
|
||||
|
||||
static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
const struct firmware *firmware;
|
||||
struct rt_firmware *pfirmware = NULL;
|
||||
int err = 0;
|
||||
u16 earlyrxthreshold = 7;
|
||||
|
||||
|
@ -192,27 +232,19 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
|
|||
return 1;
|
||||
}
|
||||
|
||||
rtlpriv->max_fw_size = sizeof(struct rt_firmware);
|
||||
|
||||
pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
|
||||
"Loading firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
/* request fw */
|
||||
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev);
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl92se_fw_cb);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Failed to request firmware!\n");
|
||||
return 1;
|
||||
}
|
||||
if (firmware->size > sizeof(struct rt_firmware)) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
"Firmware is too big!\n");
|
||||
release_firmware(firmware);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
|
||||
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
|
||||
pfirmware->sz_fw_tmpbufferlen = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -25,16 +25,13 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/export.h>
|
||||
#include "core.h"
|
||||
#include "wifi.h"
|
||||
#include "core.h"
|
||||
#include "usb.h"
|
||||
#include "base.h"
|
||||
#include "ps.h"
|
||||
#include "rtl8192c/fw_common.h"
|
||||
#include <linux/export.h>
|
||||
|
||||
#define REALTEK_USB_VENQT_READ 0xC0
|
||||
#define REALTEK_USB_VENQT_WRITE 0x40
|
||||
|
@ -667,15 +664,17 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
|
|||
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
|
||||
|
||||
err = rtlpriv->cfg->ops->hw_init(hw);
|
||||
rtl_init_rx_config(hw);
|
||||
if (!err) {
|
||||
rtl_init_rx_config(hw);
|
||||
|
||||
/* Enable software */
|
||||
SET_USB_START(rtlusb);
|
||||
/* should after adapter start and interrupt enable. */
|
||||
set_hal_start(rtlhal);
|
||||
/* Enable software */
|
||||
SET_USB_START(rtlusb);
|
||||
/* should after adapter start and interrupt enable. */
|
||||
set_hal_start(rtlhal);
|
||||
|
||||
/* Start bulk IN */
|
||||
_rtl_usb_receive(hw);
|
||||
/* Start bulk IN */
|
||||
_rtl_usb_receive(hw);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -952,6 +951,7 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
|
|||
return -ENOMEM;
|
||||
}
|
||||
rtlpriv = hw->priv;
|
||||
init_completion(&rtlpriv->firmware_loading_complete);
|
||||
SET_IEEE80211_DEV(hw, &intf->dev);
|
||||
udev = interface_to_usbdev(intf);
|
||||
usb_get_dev(udev);
|
||||
|
@ -985,24 +985,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
|
|||
goto error_out;
|
||||
}
|
||||
|
||||
/*init rfkill */
|
||||
/* rtl_init_rfkill(hw); */
|
||||
|
||||
err = ieee80211_register_hw(hw);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
|
||||
"Can't register mac80211 hw\n");
|
||||
goto error_out;
|
||||
} else {
|
||||
rtlpriv->mac80211.mac80211_registered = 1;
|
||||
}
|
||||
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
|
||||
return 0;
|
||||
error_out:
|
||||
rtl_deinit_core(hw);
|
||||
_rtl_usb_io_handler_release(hw);
|
||||
ieee80211_free_hw(hw);
|
||||
usb_put_dev(udev);
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_usb_probe);
|
||||
|
@ -1016,6 +1004,9 @@ void rtl_usb_disconnect(struct usb_interface *intf)
|
|||
|
||||
if (unlikely(!rtlpriv))
|
||||
return;
|
||||
|
||||
/* just in case driver is removed before firmware callback */
|
||||
wait_for_completion(&rtlpriv->firmware_loading_complete);
|
||||
/*ieee80211_unregister_hw will call ops_stop */
|
||||
if (rtlmac->mac80211_registered == 1) {
|
||||
ieee80211_unregister_hw(hw);
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#ifndef __RTL_USB_H__
|
||||
#define __RTL_USB_H__
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#define RTL_RX_DESC_SIZE 24
|
||||
|
|
|
@ -30,12 +30,15 @@
|
|||
#ifndef __RTL_WIFI_H__
|
||||
#define __RTL_WIFI_H__
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/usb.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/completion.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define RF_CHANGE_BY_INIT 0
|
||||
|
@ -1045,7 +1048,6 @@ struct rtl_hal {
|
|||
u16 fw_subversion;
|
||||
bool h2c_setinprogress;
|
||||
u8 last_hmeboxnum;
|
||||
bool fw_ready;
|
||||
/*Reserve page start offset except beacon in TxQ. */
|
||||
u8 fw_rsvdpage_startoffset;
|
||||
u8 h2c_txcmd_seq;
|
||||
|
@ -1591,6 +1593,7 @@ struct rtl_debug {
|
|||
};
|
||||
|
||||
struct rtl_priv {
|
||||
struct completion firmware_loading_complete;
|
||||
struct rtl_locks locks;
|
||||
struct rtl_works works;
|
||||
struct rtl_mac mac80211;
|
||||
|
@ -1612,6 +1615,7 @@ struct rtl_priv {
|
|||
struct rtl_rate_priv *rate_priv;
|
||||
|
||||
struct rtl_debug dbg;
|
||||
int max_fw_size;
|
||||
|
||||
/*
|
||||
*hal_cfg : for diff cards
|
||||
|
|
|
@ -1475,6 +1475,7 @@ enum nl80211_attrs {
|
|||
#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
|
||||
|
||||
#define NL80211_MAX_SUPP_RATES 32
|
||||
#define NL80211_MAX_SUPP_HT_RATES 77
|
||||
#define NL80211_MAX_SUPP_REG_RULES 32
|
||||
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
|
||||
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
|
||||
|
@ -2405,12 +2406,15 @@ enum nl80211_key_attributes {
|
|||
* in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
|
||||
* 1 = 500 kbps) but without the IE length restriction (at most
|
||||
* %NL80211_MAX_SUPP_RATES in a single array).
|
||||
* @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection
|
||||
* in an array of MCS numbers.
|
||||
* @__NL80211_TXRATE_AFTER_LAST: internal
|
||||
* @NL80211_TXRATE_MAX: highest TX rate attribute
|
||||
*/
|
||||
enum nl80211_tx_rate_attributes {
|
||||
__NL80211_TXRATE_INVALID,
|
||||
NL80211_TXRATE_LEGACY,
|
||||
NL80211_TXRATE_MCS,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_TXRATE_AFTER_LAST,
|
||||
|
|
|
@ -1232,8 +1232,7 @@ enum wiphy_params_flags {
|
|||
struct cfg80211_bitrate_mask {
|
||||
struct {
|
||||
u32 legacy;
|
||||
/* TODO: add support for masking MCS rates; e.g.: */
|
||||
/* u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; */
|
||||
u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
|
||||
} control[IEEE80211_NUM_BANDS];
|
||||
};
|
||||
/**
|
||||
|
|
|
@ -3551,6 +3551,7 @@ struct ieee80211_tx_rate_control {
|
|||
bool rts, short_preamble;
|
||||
u8 max_rate_idx;
|
||||
u32 rate_idx_mask;
|
||||
u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
|
||||
bool bss;
|
||||
};
|
||||
|
||||
|
|
|
@ -776,12 +776,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
|
||||
if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
|
||||
!test_sta_flag(sta, WLAN_STA_AUTH)) {
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_AUTH);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_ASSOC);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -789,11 +787,9 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
|
||||
if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
||||
if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_AUTHORIZED);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_ASSOC);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -805,12 +801,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
|
||||
if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
|
||||
test_sta_flag(sta, WLAN_STA_AUTH)) {
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_AUTH);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = sta_info_move_state_checked(sta,
|
||||
IEEE80211_STA_NONE);
|
||||
ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -944,8 +938,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
if (!sta)
|
||||
return -ENOMEM;
|
||||
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
|
||||
err = sta_apply_parameters(local, sta, params);
|
||||
if (err) {
|
||||
|
@ -1908,8 +1902,11 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
|
|||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
||||
sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
|
||||
memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
|
||||
sizeof(mask->control[i].mcs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,21 @@ static ssize_t ieee80211_if_fmt_##name( \
|
|||
#define IEEE80211_IF_FMT_SIZE(name, field) \
|
||||
IEEE80211_IF_FMT(name, field, "%zd\n")
|
||||
|
||||
#define IEEE80211_IF_FMT_HEXARRAY(name, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, \
|
||||
char *buf, int buflen) \
|
||||
{ \
|
||||
char *p = buf; \
|
||||
int i; \
|
||||
for (i = 0; i < sizeof(sdata->field); i++) { \
|
||||
p += scnprintf(p, buflen + buf - p, "%.2x ", \
|
||||
sdata->field[i]); \
|
||||
} \
|
||||
p += scnprintf(p, buflen + buf - p, "\n"); \
|
||||
return p - buf; \
|
||||
}
|
||||
|
||||
#define IEEE80211_IF_FMT_ATOMIC(name, field) \
|
||||
static ssize_t ieee80211_if_fmt_##name( \
|
||||
const struct ieee80211_sub_if_data *sdata, \
|
||||
|
@ -148,6 +163,11 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
|
|||
HEX);
|
||||
IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
|
||||
HEX);
|
||||
IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz,
|
||||
rc_rateidx_mcs_mask[IEEE80211_BAND_2GHZ], HEXARRAY);
|
||||
IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
|
||||
rc_rateidx_mcs_mask[IEEE80211_BAND_5GHZ], HEXARRAY);
|
||||
|
||||
IEEE80211_IF_FILE(flags, flags, HEX);
|
||||
IEEE80211_IF_FILE(state, state, LHEX);
|
||||
IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
|
||||
|
@ -442,6 +462,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
|
|||
DEBUGFS_ADD(channel_type);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
|
||||
|
||||
DEBUGFS_ADD(bssid);
|
||||
DEBUGFS_ADD(aid);
|
||||
|
@ -459,6 +481,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
|
|||
DEBUGFS_ADD(channel_type);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
|
||||
|
||||
DEBUGFS_ADD(num_sta_authorized);
|
||||
DEBUGFS_ADD(num_sta_ps);
|
||||
|
@ -469,6 +493,12 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
DEBUGFS_ADD(channel_type);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
|
||||
|
||||
DEBUGFS_ADD_MODE(tsf, 0600);
|
||||
}
|
||||
|
||||
|
@ -480,6 +510,8 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
|
|||
DEBUGFS_ADD(channel_type);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
|
||||
|
||||
DEBUGFS_ADD(peer);
|
||||
}
|
||||
|
@ -492,6 +524,8 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
|
|||
DEBUGFS_ADD(channel_type);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
|
||||
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
|
||||
}
|
||||
|
||||
static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
|
||||
|
|
|
@ -63,14 +63,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
|
|||
test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
|
||||
|
||||
int res = scnprintf(buf, sizeof(buf),
|
||||
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
|
||||
TEST(PS_DRIVER), TEST(AUTHORIZED),
|
||||
TEST(SHORT_PREAMBLE),
|
||||
TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
|
||||
TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
|
||||
TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
|
||||
TEST(TDLS_PEER_AUTH));
|
||||
TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
|
||||
TEST(INSERTED));
|
||||
#undef TEST
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
|
||||
}
|
||||
|
|
|
@ -265,9 +265,9 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
|
|||
addr, sdata->name);
|
||||
#endif
|
||||
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
|
||||
rate_control_rate_init(sta);
|
||||
|
||||
|
@ -655,15 +655,14 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
|
|||
if (ieee80211_sta_active_ibss(sdata))
|
||||
return;
|
||||
|
||||
if (ifibss->fixed_bssid)
|
||||
if (ifibss->fixed_channel)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
|
||||
"IBSS networks with same SSID (merge)\n", sdata->name);
|
||||
|
||||
ieee80211_request_internal_scan(sdata,
|
||||
ifibss->ssid, ifibss->ssid_len,
|
||||
ifibss->fixed_channel ? ifibss->channel : NULL);
|
||||
ifibss->ssid, ifibss->ssid_len, NULL);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
|
|
|
@ -646,6 +646,7 @@ struct ieee80211_sub_if_data {
|
|||
|
||||
/* bitmap of allowed (non-MCS) rate indexes for rate control */
|
||||
u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
|
||||
u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
|
||||
|
||||
union {
|
||||
struct ieee80211_if_ap ap;
|
||||
|
|
|
@ -318,9 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
|
|||
goto err_del_interface;
|
||||
}
|
||||
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
|
||||
res = sta_info_insert(sta);
|
||||
if (res) {
|
||||
|
@ -1181,6 +1181,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||
sband = local->hw.wiphy->bands[i];
|
||||
sdata->rc_rateidx_mask[i] =
|
||||
sband ? (1 << sband->n_bitrates) - 1 : 0;
|
||||
if (sband)
|
||||
memcpy(sdata->rc_rateidx_mcs_mask[i],
|
||||
sband->ht_cap.mcs.rx_mask,
|
||||
sizeof(sdata->rc_rateidx_mcs_mask[i]));
|
||||
else
|
||||
memset(sdata->rc_rateidx_mcs_mask[i], 0,
|
||||
sizeof(sdata->rc_rateidx_mcs_mask[i]));
|
||||
}
|
||||
|
||||
/* setup type-dependent data */
|
||||
|
|
|
@ -96,9 +96,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
if (!sta)
|
||||
return NULL;
|
||||
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_WME);
|
||||
|
||||
|
|
|
@ -1587,10 +1587,19 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
|
|||
return false;
|
||||
}
|
||||
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
|
||||
sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
err = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
||||
if (!err)
|
||||
err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
|
||||
err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
||||
if (err) {
|
||||
printk(KERN_DEBUG
|
||||
"%s: failed to move station %pM to desired state\n",
|
||||
sdata->name, sta->sta.addr);
|
||||
WARN_ON(__sta_info_destroy(sta));
|
||||
mutex_unlock(&sdata->local->sta_mtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
rates = 0;
|
||||
basic_rates = 0;
|
||||
|
|
|
@ -289,8 +289,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
|
|||
}
|
||||
EXPORT_SYMBOL(rate_control_send_low);
|
||||
|
||||
static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
|
||||
int n_bitrates, u32 mask)
|
||||
static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate,
|
||||
int n_bitrates, u32 mask)
|
||||
{
|
||||
int j;
|
||||
|
||||
|
@ -299,7 +299,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
|
|||
if (mask & (1 << j)) {
|
||||
/* Okay, found a suitable rate. Use it. */
|
||||
rate->idx = j;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,6 +308,112 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
|
|||
if (mask & (1 << j)) {
|
||||
/* Okay, found a suitable rate. Use it. */
|
||||
rate->idx = j;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
|
||||
u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
{
|
||||
int i, j;
|
||||
int ridx, rbit;
|
||||
|
||||
ridx = rate->idx / 8;
|
||||
rbit = rate->idx % 8;
|
||||
|
||||
/* sanity check */
|
||||
if (ridx < 0 || ridx > IEEE80211_HT_MCS_MASK_LEN)
|
||||
return false;
|
||||
|
||||
/* See whether the selected rate or anything below it is allowed. */
|
||||
for (i = ridx; i >= 0; i--) {
|
||||
for (j = rbit; j >= 0; j--)
|
||||
if (mcs_mask[i] & BIT(j)) {
|
||||
rate->idx = i * 8 + j;
|
||||
return true;
|
||||
}
|
||||
rbit = 7;
|
||||
}
|
||||
|
||||
/* Try to find a higher rate that would be allowed */
|
||||
ridx = (rate->idx + 1) / 8;
|
||||
rbit = (rate->idx + 1) % 8;
|
||||
|
||||
for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
|
||||
for (j = rbit; j < 8; j++)
|
||||
if (mcs_mask[i] & BIT(j)) {
|
||||
rate->idx = i * 8 + j;
|
||||
return true;
|
||||
}
|
||||
rbit = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
|
||||
struct ieee80211_tx_rate_control *txrc,
|
||||
u32 mask,
|
||||
u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
|
||||
{
|
||||
struct ieee80211_tx_rate alt_rate;
|
||||
|
||||
/* handle HT rates */
|
||||
if (rate->flags & IEEE80211_TX_RC_MCS) {
|
||||
if (rate_idx_match_mcs_mask(rate, mcs_mask))
|
||||
return;
|
||||
|
||||
/* also try the legacy rates. */
|
||||
alt_rate.idx = 0;
|
||||
/* keep protection flags */
|
||||
alt_rate.flags = rate->flags &
|
||||
(IEEE80211_TX_RC_USE_RTS_CTS |
|
||||
IEEE80211_TX_RC_USE_CTS_PROTECT |
|
||||
IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
|
||||
alt_rate.count = rate->count;
|
||||
if (rate_idx_match_legacy_mask(&alt_rate,
|
||||
txrc->sband->n_bitrates,
|
||||
mask)) {
|
||||
*rate = alt_rate;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
struct sk_buff *skb = txrc->skb;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
__le16 fc;
|
||||
|
||||
/* handle legacy rates */
|
||||
if (rate_idx_match_legacy_mask(rate, txrc->sband->n_bitrates,
|
||||
mask))
|
||||
return;
|
||||
|
||||
/* if HT BSS, and we handle a data frame, also try HT rates */
|
||||
if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT)
|
||||
return;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
if (!ieee80211_is_data(fc))
|
||||
return;
|
||||
|
||||
alt_rate.idx = 0;
|
||||
/* keep protection flags */
|
||||
alt_rate.flags = rate->flags &
|
||||
(IEEE80211_TX_RC_USE_RTS_CTS |
|
||||
IEEE80211_TX_RC_USE_CTS_PROTECT |
|
||||
IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
|
||||
alt_rate.count = rate->count;
|
||||
|
||||
alt_rate.flags |= IEEE80211_TX_RC_MCS;
|
||||
|
||||
if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) ||
|
||||
(txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS))
|
||||
alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||
|
||||
if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
|
||||
*rate = alt_rate;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -331,6 +437,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
|
||||
int i;
|
||||
u32 mask;
|
||||
u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
|
||||
|
||||
if (sta) {
|
||||
ista = &sta->sta;
|
||||
|
@ -354,10 +461,14 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
|
|||
* the common case.
|
||||
*/
|
||||
mask = sdata->rc_rateidx_mask[info->band];
|
||||
memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
|
||||
sizeof(mcs_mask));
|
||||
if (mask != (1 << txrc->sband->n_bitrates) - 1) {
|
||||
if (sta) {
|
||||
/* Filter out rates that the STA does not support */
|
||||
mask &= sta->sta.supp_rates[info->band];
|
||||
for (i = 0; i < sizeof(mcs_mask); i++)
|
||||
mcs_mask[i] &= sta->sta.ht_cap.mcs.rx_mask[i];
|
||||
}
|
||||
/*
|
||||
* Make sure the rate index selected for each TX rate is
|
||||
|
@ -368,11 +479,8 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
|
|||
/* Skip invalid rates */
|
||||
if (info->control.rates[i].idx < 0)
|
||||
break;
|
||||
/* Rate masking supports only legacy rates for now */
|
||||
if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
|
||||
continue;
|
||||
rate_idx_match_mask(&info->control.rates[i],
|
||||
txrc->sband->n_bitrates, mask);
|
||||
rate_idx_match_mask(&info->control.rates[i], txrc,
|
||||
mask, mcs_mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1145,19 +1145,15 @@ static void ap_sta_ps_start(struct sta_info *sta)
|
|||
|
||||
static void ap_sta_ps_end(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
|
||||
sdata->name, sta->sta.addr, sta->sta.aid);
|
||||
sta->sdata->name, sta->sta.addr, sta->sta.aid);
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
|
||||
sdata->name, sta->sta.addr, sta->sta.aid);
|
||||
sta->sdata->name, sta->sta.addr, sta->sta.aid);
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -403,6 +403,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
|||
sta_info_hash_add(local, sta);
|
||||
|
||||
list_add(&sta->list, &local->sta_list);
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||
} else {
|
||||
sta->dummy = false;
|
||||
}
|
||||
|
@ -707,7 +709,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
|
|||
return have_buffered;
|
||||
}
|
||||
|
||||
static int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||
int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
@ -722,6 +724,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
|
|||
local = sta->local;
|
||||
sdata = sta->sdata;
|
||||
|
||||
lockdep_assert_held(&local->sta_mtx);
|
||||
|
||||
/*
|
||||
* Before removing the station from the driver and
|
||||
* rate control, it might still start new aggregation
|
||||
|
@ -746,25 +750,19 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
|
|||
|
||||
sta->dead = true;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
||||
test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
|
||||
BUG_ON(!sdata->bss);
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
sta_info_recalc_tim(sta);
|
||||
}
|
||||
|
||||
local->num_sta--;
|
||||
local->sta_generation++;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
|
||||
|
||||
while (sta->sta_state > IEEE80211_STA_NONE)
|
||||
sta_info_move_state(sta, sta->sta_state - 1);
|
||||
while (sta->sta_state > IEEE80211_STA_NONE) {
|
||||
int err = sta_info_move_state(sta, sta->sta_state - 1);
|
||||
if (err) {
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sta->uploaded) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
|
@ -783,6 +781,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
|
|||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
BUG_ON(!sdata->bss);
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
sta_info_recalc_tim(sta);
|
||||
}
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
|
||||
__skb_queue_purge(&sta->ps_tx_buf[ac]);
|
||||
|
@ -990,9 +997,11 @@ EXPORT_SYMBOL(ieee80211_find_sta);
|
|||
static void clear_sta_ps_flags(void *_sta)
|
||||
{
|
||||
struct sta_info *sta = _sta;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
|
||||
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
|
||||
clear_sta_flag(sta, WLAN_STA_PS_STA);
|
||||
if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
}
|
||||
|
||||
/* powersave support code */
|
||||
|
@ -1391,8 +1400,8 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_sta_set_buffered);
|
||||
|
||||
int sta_info_move_state_checked(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state)
|
||||
int sta_info_move_state(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
* @WLAN_STA_SP: Station is in a service period, so don't try to
|
||||
* reply to other uAPSD trigger frames or PS-Poll.
|
||||
* @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame.
|
||||
* @WLAN_STA_INSERTED: This station is inserted into the hash table.
|
||||
*/
|
||||
enum ieee80211_sta_info_flags {
|
||||
WLAN_STA_AUTH,
|
||||
|
@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags {
|
|||
WLAN_STA_UAPSD,
|
||||
WLAN_STA_SP,
|
||||
WLAN_STA_4ADDR_EVENT,
|
||||
WLAN_STA_INSERTED,
|
||||
};
|
||||
|
||||
enum ieee80211_sta_state {
|
||||
|
@ -427,13 +429,17 @@ static inline int test_and_set_sta_flag(struct sta_info *sta,
|
|||
return test_and_set_bit(flag, &sta->_flags);
|
||||
}
|
||||
|
||||
int sta_info_move_state_checked(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state);
|
||||
int sta_info_move_state(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state);
|
||||
|
||||
static inline void sta_info_move_state(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state)
|
||||
static inline void sta_info_pre_move_state(struct sta_info *sta,
|
||||
enum ieee80211_sta_state new_state)
|
||||
{
|
||||
int ret = sta_info_move_state_checked(sta, new_state);
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED));
|
||||
|
||||
ret = sta_info_move_state(sta, new_state);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
|
||||
|
@ -544,6 +550,7 @@ int sta_info_insert(struct sta_info *sta);
|
|||
int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
|
||||
int sta_info_reinsert(struct sta_info *sta);
|
||||
|
||||
int __must_check __sta_info_destroy(struct sta_info *sta);
|
||||
int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *addr);
|
||||
int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
|
||||
|
|
|
@ -635,6 +635,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
|||
txrc.max_rate_idx = -1;
|
||||
else
|
||||
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
|
||||
memcpy(txrc.rate_idx_mcs_mask,
|
||||
tx->sdata->rc_rateidx_mcs_mask[tx->channel->band],
|
||||
sizeof(txrc.rate_idx_mcs_mask));
|
||||
txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
|
||||
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
|
||||
|
@ -2431,6 +2434,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
txrc.max_rate_idx = -1;
|
||||
else
|
||||
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
|
||||
memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
|
||||
sizeof(txrc.rate_idx_mcs_mask));
|
||||
txrc.bss = true;
|
||||
rate_control_get_rate(sdata, NULL, &txrc);
|
||||
|
||||
|
|
|
@ -5393,9 +5393,39 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
|
|||
return mask;
|
||||
}
|
||||
|
||||
static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
|
||||
u8 *rates, u8 rates_len,
|
||||
u8 mcs[IEEE80211_HT_MCS_MASK_LEN])
|
||||
{
|
||||
u8 i;
|
||||
|
||||
memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN);
|
||||
|
||||
for (i = 0; i < rates_len; i++) {
|
||||
int ridx, rbit;
|
||||
|
||||
ridx = rates[i] / 8;
|
||||
rbit = BIT(rates[i] % 8);
|
||||
|
||||
/* check validity */
|
||||
if ((ridx < 0) || (ridx > IEEE80211_HT_MCS_MASK_LEN))
|
||||
return false;
|
||||
|
||||
/* check availability */
|
||||
if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
|
||||
mcs[ridx] |= rbit;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
|
||||
[NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
|
||||
.len = NL80211_MAX_SUPP_RATES },
|
||||
[NL80211_TXRATE_MCS] = { .type = NLA_BINARY,
|
||||
.len = NL80211_MAX_SUPP_HT_RATES },
|
||||
};
|
||||
|
||||
static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
||||
|
@ -5421,12 +5451,20 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
|||
sband = rdev->wiphy.bands[i];
|
||||
mask.control[i].legacy =
|
||||
sband ? (1 << sband->n_bitrates) - 1 : 0;
|
||||
if (sband)
|
||||
memcpy(mask.control[i].mcs,
|
||||
sband->ht_cap.mcs.rx_mask,
|
||||
sizeof(mask.control[i].mcs));
|
||||
else
|
||||
memset(mask.control[i].mcs, 0,
|
||||
sizeof(mask.control[i].mcs));
|
||||
}
|
||||
|
||||
/*
|
||||
* The nested attribute uses enum nl80211_band as the index. This maps
|
||||
* directly to the enum ieee80211_band values used in cfg80211.
|
||||
*/
|
||||
BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
|
||||
nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
|
||||
{
|
||||
enum ieee80211_band band = nla_type(tx_rates);
|
||||
|
@ -5442,7 +5480,28 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
|||
sband,
|
||||
nla_data(tb[NL80211_TXRATE_LEGACY]),
|
||||
nla_len(tb[NL80211_TXRATE_LEGACY]));
|
||||
if (mask.control[band].legacy == 0)
|
||||
}
|
||||
if (tb[NL80211_TXRATE_MCS]) {
|
||||
if (!ht_rateset_to_mask(
|
||||
sband,
|
||||
nla_data(tb[NL80211_TXRATE_MCS]),
|
||||
nla_len(tb[NL80211_TXRATE_MCS]),
|
||||
mask.control[band].mcs))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mask.control[band].legacy == 0) {
|
||||
/* don't allow empty legacy rates if HT
|
||||
* is not even supported. */
|
||||
if (!rdev->wiphy.bands[band]->ht_cap.ht_supported)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
|
||||
if (mask.control[band].mcs[i])
|
||||
break;
|
||||
|
||||
/* legacy and mcs rates may not be both empty */
|
||||
if (i == IEEE80211_HT_MCS_MASK_LEN)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue