forked from Minki/linux
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
commit
16698918cd
@ -101,7 +101,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
|
||||
}
|
||||
|
||||
void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
@ -257,7 +257,7 @@ static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
||||
}
|
||||
|
||||
/* query bus clock frequency for PMU-enabled chipcommon */
|
||||
u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
||||
static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
|
@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_BLOCKIO
|
||||
void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
void __iomem *addr = core->bus->mmio + offset;
|
||||
if (core->bus->mapped_core != core)
|
||||
@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
static void bcma_host_pci_block_write(struct bcma_device *core,
|
||||
const void *buffer, size_t count,
|
||||
u16 offset, u8 reg_width)
|
||||
{
|
||||
void __iomem *addr = core->bus->mmio + offset;
|
||||
if (core->bus->mapped_core != core)
|
||||
@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
|
||||
iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
|
||||
}
|
||||
|
||||
const struct bcma_host_ops bcma_host_pci_ops = {
|
||||
static const struct bcma_host_ops bcma_host_pci_ops = {
|
||||
.read8 = bcma_host_pci_read8,
|
||||
.read16 = bcma_host_pci_read16,
|
||||
.read32 = bcma_host_pci_read32,
|
||||
|
@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
|
||||
writel(value, core->io_wrap + offset);
|
||||
}
|
||||
|
||||
const struct bcma_host_ops bcma_host_soc_ops = {
|
||||
static const struct bcma_host_ops bcma_host_soc_ops = {
|
||||
.read8 = bcma_host_soc_read8,
|
||||
.read16 = bcma_host_soc_read16,
|
||||
.read32 = bcma_host_soc_read32,
|
||||
|
@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
BT_ERR("Can't allocate memory for data structure");
|
||||
return -ENOMEM;
|
||||
@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
data->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!data->urb) {
|
||||
BT_ERR("Can't allocate URB");
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
||||
BT_ERR("Mini driver request failed");
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
BT_ERR("Can't allocate memory for mini driver");
|
||||
release_firmware(firmware);
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
BT_ERR("Firmware request failed");
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
release_firmware(firmware);
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
|
||||
usb_free_urb(data->urb);
|
||||
kfree(data->fw_data);
|
||||
kfree(data->buffer);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bcm203x_driver = {
|
||||
|
@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
}
|
||||
|
||||
/* Initialize control structure and load firmware */
|
||||
data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
BT_ERR("Can't allocate memory for control structure");
|
||||
goto done;
|
||||
@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
|
||||
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
|
||||
BT_ERR("Firmware request failed");
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
|
||||
@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
BT_ERR("Can't allocate HCI device");
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
data->hdev = hdev;
|
||||
@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
if (hci_register_dev(hdev) < 0) {
|
||||
BT_ERR("Can't register HCI device");
|
||||
hci_free_dev(hdev);
|
||||
goto error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, data);
|
||||
@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
release:
|
||||
release_firmware(firmware);
|
||||
|
||||
error:
|
||||
kfree(data);
|
||||
|
||||
done:
|
||||
return -EIO;
|
||||
}
|
||||
@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bfusb_driver = {
|
||||
|
@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||
bluecard_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||
|
||||
static void bluecard_detach(struct pcmcia_device *link)
|
||||
{
|
||||
bluecard_info_t *info = link->priv;
|
||||
|
||||
bluecard_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
init_usb_anchor(&data->rx_anchor);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_USB;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
|
||||
hci_free_dev(data->hdev);
|
||||
kfree_skb(data->rx_skb[0]);
|
||||
kfree_skb(data->rx_skb[1]);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver bpa10x_driver = {
|
||||
|
@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||
bt3c_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||
|
||||
static void bt3c_detach(struct pcmcia_device *link)
|
||||
{
|
||||
bt3c_info_t *info = link->priv;
|
||||
|
||||
bt3c_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
|
||||
id->vendor, id->device, id->class, func->num);
|
||||
|
||||
card = kzalloc(sizeof(*card), GFP_KERNEL);
|
||||
if (!card) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
card->func = func;
|
||||
|
||||
@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
|
||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||
BT_ERR("Failed to register BT device!");
|
||||
ret = -ENODEV;
|
||||
goto free_card;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Disable the interrupts on the card */
|
||||
@ -1023,9 +1020,6 @@ disable_host_int:
|
||||
btmrvl_sdio_disable_host_int(card);
|
||||
unreg_dev:
|
||||
btmrvl_sdio_unregister_dev(card);
|
||||
free_card:
|
||||
kfree(card);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
|
||||
BT_DBG("unregester dev");
|
||||
btmrvl_sdio_unregister_dev(card);
|
||||
btmrvl_remove_card(card->priv);
|
||||
kfree(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
tuple = tuple->next;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
skb_queue_head_init(&data->txq);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_SDIO;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func)
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct sdio_driver btsdio_driver = {
|
||||
|
@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||
btuart_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||
|
||||
static void btuart_detach(struct pcmcia_device *link)
|
||||
{
|
||||
btuart_info_t *info = link->priv;
|
||||
|
||||
btuart_release(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
|
||||
kfree(data);
|
||||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cmdreq_type = USB_TYPE_CLASS;
|
||||
|
||||
@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
init_usb_anchor(&data->deferred);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(data);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->bus = HCI_USB;
|
||||
hci_set_drvdata(hdev, data);
|
||||
@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
data->isoc, data);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
|
||||
hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL);
|
||||
if (!hst)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Expose "hciX" device to user space */
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
kfree(hst);
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
BT_DBG("hdev %p", hdev);
|
||||
|
||||
@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't register HCI device error %d", err);
|
||||
kfree(hst);
|
||||
hci_free_dev(hdev);
|
||||
return err;
|
||||
}
|
||||
@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev)
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
kfree(hst);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
return 0;
|
||||
|
@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link)
|
||||
dtl1_info_t *info;
|
||||
|
||||
/* Create new info device */
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link)
|
||||
|
||||
dtl1_close(info);
|
||||
pcmcia_disable_device(link);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
@ -1331,7 +1331,6 @@ struct ath5k_hw {
|
||||
unsigned int nexttbtt; /* next beacon time in TU */
|
||||
struct ath5k_txq *cabq; /* content after beacon */
|
||||
|
||||
int power_level; /* Requested tx power in dBm */
|
||||
bool assoc; /* associate state */
|
||||
bool enable_beacon; /* true if beacons are on */
|
||||
|
||||
@ -1425,6 +1424,7 @@ struct ath5k_hw {
|
||||
/* Value in dB units */
|
||||
s16 txp_cck_ofdm_pwr_delta;
|
||||
bool txp_setup;
|
||||
int txp_requested; /* Requested tx power in dBm */
|
||||
} ah_txpower;
|
||||
|
||||
struct ath5k_nfcal_hist ah_nfcal_hist;
|
||||
|
@ -723,7 +723,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
get_hw_packet_type(skb),
|
||||
(ah->power_level * 2),
|
||||
(ah->ah_txpower.txp_requested * 2),
|
||||
hw_rate,
|
||||
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
|
||||
cts_rate, duration);
|
||||
@ -1778,7 +1778,8 @@ ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
|
||||
ds->ds_data = bf->skbaddr;
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
|
||||
ieee80211_get_hdrlen_from_skb(skb), padsize,
|
||||
AR5K_PKT_TYPE_BEACON, (ah->power_level * 2),
|
||||
AR5K_PKT_TYPE_BEACON,
|
||||
(ah->ah_txpower.txp_requested * 2),
|
||||
ieee80211_get_tx_rate(ah->hw, info)->hw_value,
|
||||
1, AR5K_TXKEYIX_INVALID,
|
||||
antenna, flags, 0, 0);
|
||||
|
@ -207,8 +207,8 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
|
||||
(ah->power_level != conf->power_level)) {
|
||||
ah->power_level = conf->power_level;
|
||||
(ah->ah_txpower.txp_requested != conf->power_level)) {
|
||||
ah->ah_txpower.txp_requested = conf->power_level;
|
||||
|
||||
/* Half dB steps */
|
||||
ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
|
||||
|
@ -3516,6 +3516,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
|
||||
{
|
||||
unsigned int i;
|
||||
u16 *rates;
|
||||
s16 rate_idx_scaled = 0;
|
||||
|
||||
/* max_pwr is power level we got from driver/user in 0.5dB
|
||||
* units, switch to 0.25dB units so we can compare */
|
||||
@ -3562,20 +3563,32 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
|
||||
for (i = 8; i <= 15; i++)
|
||||
rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
|
||||
|
||||
/* Save min/max and current tx power for this channel
|
||||
* in 0.25dB units.
|
||||
*
|
||||
* Note: We use rates[0] for current tx power because
|
||||
* it covers most of the rates, in most cases. It's our
|
||||
* tx power limit and what the user expects to see. */
|
||||
ah->ah_txpower.txp_min_pwr = 2 * rates[7];
|
||||
ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
|
||||
|
||||
/* Set max txpower for correct OFDM operation on all rates
|
||||
* -that is the txpower for 54Mbit-, it's used for the PAPD
|
||||
* gain probe and it's in 0.5dB units */
|
||||
ah->ah_txpower.txp_ofdm = rates[7];
|
||||
|
||||
/* Now that we have all rates setup use table offset to
|
||||
* match the power range set by user with the power indices
|
||||
* on PCDAC/PDADC table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
rates[i] += ah->ah_txpower.txp_offset;
|
||||
rate_idx_scaled = rates[i] + ah->ah_txpower.txp_offset;
|
||||
/* Don't get out of bounds */
|
||||
if (rates[i] > 63)
|
||||
rates[i] = 63;
|
||||
if (rate_idx_scaled > 63)
|
||||
rate_idx_scaled = 63;
|
||||
if (rate_idx_scaled < 0)
|
||||
rate_idx_scaled = 0;
|
||||
rates[i] = rate_idx_scaled;
|
||||
}
|
||||
|
||||
/* Min/max in 0.25dB units */
|
||||
ah->ah_txpower.txp_min_pwr = 2 * rates[7];
|
||||
ah->ah_txpower.txp_cur_pwr = 2 * rates[0];
|
||||
ah->ah_txpower.txp_ofdm = rates[7];
|
||||
}
|
||||
|
||||
|
||||
@ -3639,10 +3652,17 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
if (!ah->ah_txpower.txp_setup ||
|
||||
(channel->hw_value != curr_channel->hw_value) ||
|
||||
(channel->center_freq != curr_channel->center_freq)) {
|
||||
/* Reset TX power values */
|
||||
/* Reset TX power values but preserve requested
|
||||
* tx power from above */
|
||||
int requested_txpower = ah->ah_txpower.txp_requested;
|
||||
|
||||
memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
|
||||
|
||||
/* Restore TPC setting and requested tx power */
|
||||
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
||||
|
||||
ah->ah_txpower.txp_requested = requested_txpower;
|
||||
|
||||
/* Calculate the powertable */
|
||||
ret = ath5k_setup_channel_powertable(ah, channel,
|
||||
ee_mode, type);
|
||||
@ -3789,8 +3809,9 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
* RF buffer settings on 5211/5212+ so that we
|
||||
* properly set curve indices.
|
||||
*/
|
||||
ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ?
|
||||
ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER);
|
||||
ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_requested ?
|
||||
ah->ah_txpower.txp_requested * 2 :
|
||||
AR5K_TUNE_MAX_TXPOWER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -4901,90 +4901,79 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
|
||||
i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
|
||||
chan->channel);
|
||||
|
||||
/*
|
||||
* compare test group from regulatory
|
||||
* channel list with test mode from pCtlMode
|
||||
* list
|
||||
*/
|
||||
if ((((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
ctlIndex[i]) ||
|
||||
(((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
((ctlIndex[i] & CTL_MODE_M) |
|
||||
SD_NO_CTL))) {
|
||||
twiceMinEdgePower =
|
||||
ar9003_hw_get_max_edge_power(pEepData,
|
||||
freq, i,
|
||||
is2ghz);
|
||||
/*
|
||||
* compare test group from regulatory
|
||||
* channel list with test mode from pCtlMode
|
||||
* list
|
||||
*/
|
||||
if ((((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
ctlIndex[i]) ||
|
||||
(((cfgCtl & ~CTL_MODE_M) |
|
||||
(pCtlMode[ctlMode] & CTL_MODE_M)) ==
|
||||
((ctlIndex[i] & CTL_MODE_M) |
|
||||
SD_NO_CTL))) {
|
||||
twiceMinEdgePower =
|
||||
ar9003_hw_get_max_edge_power(pEepData,
|
||||
freq, i,
|
||||
is2ghz);
|
||||
|
||||
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
|
||||
/*
|
||||
* Find the minimum of all CTL
|
||||
* edge powers that apply to
|
||||
* this channel
|
||||
*/
|
||||
twiceMaxEdgePower =
|
||||
min(twiceMaxEdgePower,
|
||||
twiceMinEdgePower);
|
||||
else {
|
||||
/* specific */
|
||||
twiceMaxEdgePower =
|
||||
twiceMinEdgePower;
|
||||
break;
|
||||
}
|
||||
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
|
||||
/*
|
||||
* Find the minimum of all CTL
|
||||
* edge powers that apply to
|
||||
* this channel
|
||||
*/
|
||||
twiceMaxEdgePower =
|
||||
min(twiceMaxEdgePower,
|
||||
twiceMinEdgePower);
|
||||
else {
|
||||
/* specific */
|
||||
twiceMaxEdgePower = twiceMinEdgePower;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
|
||||
minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
|
||||
|
||||
ath_dbg(common, REGULATORY,
|
||||
"SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
|
||||
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
|
||||
scaledPower, minCtlPower);
|
||||
ath_dbg(common, REGULATORY,
|
||||
"SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
|
||||
ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
|
||||
scaledPower, minCtlPower);
|
||||
|
||||
/* Apply ctl mode to correct target power set */
|
||||
switch (pCtlMode[ctlMode]) {
|
||||
case CTL_11B:
|
||||
for (i = ALL_TARGET_LEGACY_1L_5L;
|
||||
i <= ALL_TARGET_LEGACY_11S; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_11A:
|
||||
case CTL_11G:
|
||||
for (i = ALL_TARGET_LEGACY_6_24;
|
||||
i <= ALL_TARGET_LEGACY_54; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT20:
|
||||
case CTL_2GHT20:
|
||||
for (i = ALL_TARGET_HT20_0_8_16;
|
||||
i <= ALL_TARGET_HT20_21; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
pPwrArray[ALL_TARGET_HT20_22] =
|
||||
(u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
|
||||
minCtlPower);
|
||||
pPwrArray[ALL_TARGET_HT20_23] =
|
||||
(u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT40:
|
||||
case CTL_2GHT40:
|
||||
for (i = ALL_TARGET_HT40_0_8_16;
|
||||
i <= ALL_TARGET_HT40_23; i++)
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Apply ctl mode to correct target power set */
|
||||
switch (pCtlMode[ctlMode]) {
|
||||
case CTL_11B:
|
||||
for (i = ALL_TARGET_LEGACY_1L_5L;
|
||||
i <= ALL_TARGET_LEGACY_11S; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_11A:
|
||||
case CTL_11G:
|
||||
for (i = ALL_TARGET_LEGACY_6_24;
|
||||
i <= ALL_TARGET_LEGACY_54; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT20:
|
||||
case CTL_2GHT20:
|
||||
for (i = ALL_TARGET_HT20_0_8_16;
|
||||
i <= ALL_TARGET_HT20_23; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
case CTL_5GHT40:
|
||||
case CTL_2GHT40:
|
||||
for (i = ALL_TARGET_HT40_0_8_16;
|
||||
i <= ALL_TARGET_HT40_23; i++)
|
||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||
minCtlPower);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} /* end ctl mode checking */
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -160,10 +160,6 @@ struct ath_rate_table {
|
||||
u32 user_ratekbps;
|
||||
u8 ratecode;
|
||||
u8 dot11rate;
|
||||
u8 ctrl_rate;
|
||||
u8 cw40index;
|
||||
u8 sgi_index;
|
||||
u8 ht_index;
|
||||
} info[RATE_TABLE_SIZE];
|
||||
u32 probe_interval;
|
||||
u8 initial_ratemax;
|
||||
|
@ -341,6 +341,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
||||
if (SUPP(CARL9170FW_WLANTX_CAB)) {
|
||||
if_comb_types |=
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
}
|
||||
}
|
||||
|
@ -318,10 +318,10 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
||||
bssid = common->curbssid;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cam_mode |= AR9170_MAC_CAM_IBSS;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
cam_mode |= AR9170_MAC_CAM_AP;
|
||||
|
||||
|
@ -616,10 +616,12 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
goto unlock;
|
||||
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
if ((vif->type == NL80211_IFTYPE_STATION) ||
|
||||
(vif->type == NL80211_IFTYPE_WDS) ||
|
||||
(vif->type == NL80211_IFTYPE_AP))
|
||||
(vif->type == NL80211_IFTYPE_AP) ||
|
||||
(vif->type == NL80211_IFTYPE_MESH_POINT))
|
||||
break;
|
||||
|
||||
err = -EBUSY;
|
||||
|
@ -206,6 +206,7 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
carl9170_update_beacon(ar, true);
|
||||
break;
|
||||
|
||||
|
@ -4,6 +4,7 @@ b43-y += tables.o
|
||||
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2056.o
|
||||
b43-$(CONFIG_B43_PHY_N) += radio_2057.o
|
||||
b43-y += phy_common.o
|
||||
b43-y += phy_g.o
|
||||
b43-y += phy_a.o
|
||||
|
@ -241,16 +241,18 @@ enum {
|
||||
#define B43_SHM_SH_PHYVER 0x0050 /* PHY version */
|
||||
#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
|
||||
#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
|
||||
#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
|
||||
#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
|
||||
#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
|
||||
#define B43_SHM_SH_HOSTF1 0x005E /* Hostflags 1 for ucode options */
|
||||
#define B43_SHM_SH_HOSTF2 0x0060 /* Hostflags 2 for ucode options */
|
||||
#define B43_SHM_SH_HOSTF3 0x0062 /* Hostflags 3 for ucode options */
|
||||
#define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
|
||||
#define B43_SHM_SH_RADAR 0x0066 /* Radar register */
|
||||
#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
|
||||
#define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */
|
||||
#define B43_SHM_SH_HOSTF4 0x0078 /* Hostflags 4 for ucode options */
|
||||
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
|
||||
#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5 Ghz channel */
|
||||
#define B43_SHM_SH_CHAN_40MHZ 0x0200 /* Bit set, if 40 Mhz channel width */
|
||||
#define B43_SHM_SH_HOSTF5 0x00D4 /* Hostflags 5 for ucode options */
|
||||
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
|
||||
/* TSSI information */
|
||||
#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
|
||||
@ -415,6 +417,8 @@ enum {
|
||||
#define B43_PHYTYPE_HT 0x07
|
||||
#define B43_PHYTYPE_LCN 0x08
|
||||
#define B43_PHYTYPE_LCNXN 0x09
|
||||
#define B43_PHYTYPE_LCN40 0x0a
|
||||
#define B43_PHYTYPE_AC 0x0b
|
||||
|
||||
/* PHYRegisters */
|
||||
#define B43_PHY_ILT_A_CTRL 0x0072
|
||||
|
@ -533,11 +533,11 @@ u64 b43_hf_read(struct b43_wldev *dev)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
|
||||
ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3);
|
||||
ret <<= 16;
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2);
|
||||
ret <<= 16;
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
|
||||
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -550,9 +550,9 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
|
||||
lo = (value & 0x00000000FFFFULL);
|
||||
mi = (value & 0x0000FFFF0000ULL) >> 16;
|
||||
hi = (value & 0xFFFF00000000ULL) >> 32;
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1, lo);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2, mi);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3, hi);
|
||||
}
|
||||
|
||||
/* Read the firmware capabilities bitmask (Opensource firmware only) */
|
||||
@ -4282,6 +4282,35 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
|
||||
{
|
||||
switch (phy_type) {
|
||||
case B43_PHYTYPE_A:
|
||||
return "A";
|
||||
case B43_PHYTYPE_B:
|
||||
return "B";
|
||||
case B43_PHYTYPE_G:
|
||||
return "G";
|
||||
case B43_PHYTYPE_N:
|
||||
return "N";
|
||||
case B43_PHYTYPE_LP:
|
||||
return "LP";
|
||||
case B43_PHYTYPE_SSLPN:
|
||||
return "SSLPN";
|
||||
case B43_PHYTYPE_HT:
|
||||
return "HT";
|
||||
case B43_PHYTYPE_LCN:
|
||||
return "LCN";
|
||||
case B43_PHYTYPE_LCNXN:
|
||||
return "LCNXN";
|
||||
case B43_PHYTYPE_LCN40:
|
||||
return "LCN40";
|
||||
case B43_PHYTYPE_AC:
|
||||
return "AC";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
/* Get PHY and RADIO versioning numbers */
|
||||
static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
{
|
||||
@ -4342,13 +4371,13 @@ static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
unsupported = 1;
|
||||
}
|
||||
if (unsupported) {
|
||||
b43err(dev->wl, "FOUND UNSUPPORTED PHY "
|
||||
"(Analog %u, Type %u, Revision %u)\n",
|
||||
analog_type, phy_type, phy_rev);
|
||||
b43err(dev->wl, "FOUND UNSUPPORTED PHY (Analog %u, Type %d (%s), Revision %u)\n",
|
||||
analog_type, phy_type, b43_phy_name(dev, phy_type),
|
||||
phy_rev);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n",
|
||||
analog_type, phy_type, phy_rev);
|
||||
b43info(dev->wl, "Found PHY: Analog %u, Type %d (%s), Revision %u\n",
|
||||
analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
|
||||
|
||||
/* Get RADIO versioning */
|
||||
if (dev->dev->core_rev >= 24) {
|
||||
|
@ -240,6 +240,21 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
|
||||
(b43_radio_read16(dev, offset) & mask) | set);
|
||||
}
|
||||
|
||||
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
|
||||
u16 value, int delay, int timeout)
|
||||
{
|
||||
u16 val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < timeout; i += delay) {
|
||||
val = b43_radio_read(dev, offset);
|
||||
if ((val & mask) == value)
|
||||
return true;
|
||||
udelay(delay);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
assert_mac_suspended(dev);
|
||||
@ -428,7 +443,7 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
|
||||
average = (a + b + c + d + 2) / 4;
|
||||
if (is_ofdm) {
|
||||
/* Adjust for CCK-boost */
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1)
|
||||
& B43_HF_CCKBOOST)
|
||||
average = (average >= 13) ? (average - 13) : 0;
|
||||
}
|
||||
|
@ -364,6 +364,12 @@ void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
*/
|
||||
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
/**
|
||||
* b43_radio_wait_value - Waits for a given value in masked register read
|
||||
*/
|
||||
bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
|
||||
u16 value, int delay, int timeout);
|
||||
|
||||
/**
|
||||
* b43_radio_lock - Lock firmware radio register access
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "tables_nphy.h"
|
||||
#include "radio_2055.h"
|
||||
#include "radio_2056.h"
|
||||
#include "radio_2057.h"
|
||||
#include "main.h"
|
||||
|
||||
struct nphy_txgains {
|
||||
@ -126,6 +127,46 @@ ok:
|
||||
b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
|
||||
static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
|
||||
u16 value, u8 core, bool off,
|
||||
u8 override)
|
||||
{
|
||||
const struct nphy_rf_control_override_rev7 *e;
|
||||
u16 en_addrs[3][2] = {
|
||||
{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
|
||||
};
|
||||
u16 en_addr;
|
||||
u16 en_mask = field;
|
||||
u16 val_addr;
|
||||
u8 i;
|
||||
|
||||
/* Remember: we can get NULL! */
|
||||
e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (override >= ARRAY_SIZE(en_addrs)) {
|
||||
b43err(dev->wl, "Invalid override value %d\n", override);
|
||||
return;
|
||||
}
|
||||
en_addr = en_addrs[override][i];
|
||||
|
||||
val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
|
||||
|
||||
if (off) {
|
||||
b43_phy_mask(dev, en_addr, ~en_mask);
|
||||
if (e) /* Do it safer, better than wl */
|
||||
b43_phy_mask(dev, val_addr, ~e->val_mask);
|
||||
} else {
|
||||
if (!core || (core & (1 << i))) {
|
||||
b43_phy_set(dev, en_addr, en_mask);
|
||||
if (e)
|
||||
b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
|
||||
static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
|
||||
u16 value, u8 core, bool off)
|
||||
@ -458,6 +499,137 @@ static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
|
||||
b43_nphy_stay_in_carrier_search(dev, false);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Radio 0x2057
|
||||
**************************************************/
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
|
||||
static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 tmp;
|
||||
|
||||
if (phy->radio_rev == 5) {
|
||||
b43_phy_mask(dev, 0x342, ~0x2);
|
||||
udelay(10);
|
||||
b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
|
||||
b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
|
||||
}
|
||||
|
||||
b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
|
||||
udelay(10);
|
||||
b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
|
||||
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
|
||||
return 0;
|
||||
}
|
||||
b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
|
||||
tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
|
||||
b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
|
||||
|
||||
if (phy->radio_rev == 5) {
|
||||
b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
|
||||
b43_radio_mask(dev, 0x1ca, ~0x2);
|
||||
}
|
||||
if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
|
||||
b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
|
||||
b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
|
||||
tmp << 2);
|
||||
}
|
||||
|
||||
return tmp & 0x3e;
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */
|
||||
static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
|
||||
phy->radio_rev == 6);
|
||||
u16 tmp;
|
||||
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x61);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000))
|
||||
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x69);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000))
|
||||
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
if (special) {
|
||||
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1AE, 0x73);
|
||||
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
|
||||
b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
|
||||
}
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
|
||||
if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
|
||||
5000000)) {
|
||||
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
|
||||
return 0;
|
||||
}
|
||||
tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
|
||||
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void b43_radio_2057_init_pre(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
|
||||
b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
|
||||
b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
}
|
||||
|
||||
static void b43_radio_2057_init_post(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
|
||||
|
||||
b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
|
||||
b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
|
||||
mdelay(2);
|
||||
b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
|
||||
b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
|
||||
|
||||
if (dev->phy.n->init_por) {
|
||||
b43_radio_2057_rcal(dev);
|
||||
b43_radio_2057_rccal(dev);
|
||||
}
|
||||
b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
|
||||
|
||||
dev->phy.n->init_por = false;
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
|
||||
static void b43_radio_2057_init(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_2057_init_pre(dev);
|
||||
r2057_upload_inittabs(dev);
|
||||
b43_radio_2057_init_post(dev);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Radio 0x2056
|
||||
**************************************************/
|
||||
@ -545,7 +717,9 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
enum ieee80211_band band = b43_current_band(dev->wl);
|
||||
u16 offset;
|
||||
u8 i;
|
||||
u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
|
||||
u16 bias, cbias;
|
||||
u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
|
||||
u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
|
||||
|
||||
B43_WARN_ON(dev->phy.rev < 3);
|
||||
|
||||
@ -630,7 +804,56 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
|
||||
}
|
||||
} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
|
||||
/* TODO */
|
||||
u16 freq = dev->phy.channel_freq;
|
||||
if (freq < 5100) {
|
||||
paa_boost = 0xA;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xF;
|
||||
mixa_boost = 0xF;
|
||||
} else if (freq < 5340) {
|
||||
paa_boost = 0x8;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xFB;
|
||||
mixa_boost = 0xF;
|
||||
} else if (freq < 5650) {
|
||||
paa_boost = 0x0;
|
||||
pada_boost = 0x77;
|
||||
pgaa_boost = 0xB;
|
||||
mixa_boost = 0xF;
|
||||
} else {
|
||||
paa_boost = 0x0;
|
||||
pada_boost = 0x77;
|
||||
if (freq != 5825)
|
||||
pgaa_boost = -(freq - 18) / 36 + 168;
|
||||
else
|
||||
pgaa_boost = 6;
|
||||
mixa_boost = 0xF;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
offset = i ? B2056_TX1 : B2056_TX0;
|
||||
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_TXSPARE1, 0x30);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PA_SPARE2, 0xee);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_PADA_CASCBIAS, 0x03);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_IAUX_STAT, 0x50);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_IMAIN_STAT, 0x50);
|
||||
b43_radio_write(dev,
|
||||
offset | B2056_TX_INTPAA_CASCBIAS, 0x30);
|
||||
}
|
||||
}
|
||||
|
||||
udelay(50);
|
||||
@ -643,6 +866,37 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
|
||||
udelay(300);
|
||||
}
|
||||
|
||||
static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 mast2, tmp;
|
||||
|
||||
if (phy->rev != 3)
|
||||
return 0;
|
||||
|
||||
mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
|
||||
b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
|
||||
|
||||
udelay(10);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
|
||||
udelay(10);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);
|
||||
|
||||
if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
|
||||
1000000)) {
|
||||
b43err(dev->wl, "Radio recalibration timeout\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
|
||||
tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
|
||||
b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);
|
||||
|
||||
b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);
|
||||
|
||||
return tmp & 0x1f;
|
||||
}
|
||||
|
||||
static void b43_radio_init2056_pre(struct b43_wldev *dev)
|
||||
{
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
@ -665,10 +919,8 @@ static void b43_radio_init2056_post(struct b43_wldev *dev)
|
||||
b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
|
||||
b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
|
||||
b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
|
||||
/*
|
||||
if (nphy->init_por)
|
||||
Call Radio 2056 Recalibrate
|
||||
*/
|
||||
if (dev->phy.n->init_por)
|
||||
b43_radio_2056_rcal(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -680,6 +932,8 @@ static void b43_radio_init2056(struct b43_wldev *dev)
|
||||
b43_radio_init2056_pre(dev);
|
||||
b2056_upload_inittabs(dev, 0, 0);
|
||||
b43_radio_init2056_post(dev);
|
||||
|
||||
dev->phy.n->init_por = false;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
@ -753,8 +1007,6 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
int i;
|
||||
u16 val;
|
||||
bool workaround = false;
|
||||
|
||||
if (sprom->revision < 4)
|
||||
@ -777,15 +1029,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x1);
|
||||
msleep(1);
|
||||
b43_radio_set(dev, B2055_CAL_MISC, 0x40);
|
||||
for (i = 0; i < 200; i++) {
|
||||
val = b43_radio_read(dev, B2055_CAL_COUT2);
|
||||
if (val & 0x80) {
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
udelay(10);
|
||||
}
|
||||
if (i)
|
||||
if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
|
||||
b43err(dev->wl, "radio post init timeout\n");
|
||||
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
@ -1860,12 +2104,334 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
|
||||
static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
|
||||
{
|
||||
if (dev->phy.rev >= 3)
|
||||
if (dev->phy.rev >= 7)
|
||||
; /* TODO */
|
||||
else if (dev->phy.rev >= 3)
|
||||
b43_nphy_gain_ctl_workarounds_rev3plus(dev);
|
||||
else
|
||||
b43_nphy_gain_ctl_workarounds_rev1_2(dev);
|
||||
}
|
||||
|
||||
/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
|
||||
static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
|
||||
{
|
||||
if (!offset)
|
||||
offset = (dev->phy.is_40mhz) ? 0x159 : 0x154;
|
||||
return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
|
||||
{
|
||||
struct ssb_sprom *sprom = dev->dev->bus_sprom;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
|
||||
0x1F };
|
||||
u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
|
||||
|
||||
u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
|
||||
u8 ntab7_138_146[] = { 0x11, 0x11 };
|
||||
u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
|
||||
|
||||
u16 lpf_20, lpf_40, lpf_11b;
|
||||
u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
|
||||
u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
|
||||
bool rccal_ovrd = false;
|
||||
|
||||
u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
|
||||
u16 bias, conv, filt;
|
||||
|
||||
u32 tmp32;
|
||||
u8 core;
|
||||
|
||||
if (phy->rev == 7) {
|
||||
b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
|
||||
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
|
||||
}
|
||||
if (phy->rev <= 8) {
|
||||
b43_phy_write(dev, 0x23F, 0x1B0);
|
||||
b43_phy_write(dev, 0x240, 0x1B0);
|
||||
}
|
||||
if (phy->rev >= 8)
|
||||
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
|
||||
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
|
||||
tmp32 &= 0xffffff;
|
||||
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
|
||||
|
||||
if (b43_nphy_ipa(dev))
|
||||
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
|
||||
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
|
||||
|
||||
b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000);
|
||||
b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000);
|
||||
|
||||
lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
|
||||
lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
|
||||
lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
|
||||
if (b43_nphy_ipa(dev)) {
|
||||
if ((phy->radio_rev == 5 && phy->is_40mhz) ||
|
||||
phy->radio_rev == 7 || phy->radio_rev == 8) {
|
||||
bcap_val = b43_radio_read(dev, 0x16b);
|
||||
scap_val = b43_radio_read(dev, 0x16a);
|
||||
scap_val_11b = scap_val;
|
||||
bcap_val_11b = bcap_val;
|
||||
if (phy->radio_rev == 5 && phy->is_40mhz) {
|
||||
scap_val_11n_20 = scap_val;
|
||||
bcap_val_11n_20 = bcap_val;
|
||||
scap_val_11n_40 = bcap_val_11n_40 = 0xc;
|
||||
rccal_ovrd = true;
|
||||
} else { /* Rev 7/8 */
|
||||
lpf_20 = 4;
|
||||
lpf_11b = 1;
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
scap_val_11n_20 = 0xc;
|
||||
bcap_val_11n_20 = 0xc;
|
||||
scap_val_11n_40 = 0xa;
|
||||
bcap_val_11n_40 = 0xa;
|
||||
} else {
|
||||
scap_val_11n_20 = 0x14;
|
||||
bcap_val_11n_20 = 0x14;
|
||||
scap_val_11n_40 = 0xf;
|
||||
bcap_val_11n_40 = 0xf;
|
||||
}
|
||||
rccal_ovrd = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (phy->radio_rev == 5) {
|
||||
lpf_20 = 1;
|
||||
lpf_40 = 3;
|
||||
bcap_val = b43_radio_read(dev, 0x16b);
|
||||
scap_val = b43_radio_read(dev, 0x16a);
|
||||
scap_val_11b = scap_val;
|
||||
bcap_val_11b = bcap_val;
|
||||
scap_val_11n_20 = 0x11;
|
||||
scap_val_11n_40 = 0x11;
|
||||
bcap_val_11n_20 = 0x13;
|
||||
bcap_val_11n_40 = 0x13;
|
||||
rccal_ovrd = true;
|
||||
}
|
||||
}
|
||||
if (rccal_ovrd) {
|
||||
rx2tx_lut_20_11b = (bcap_val_11b << 8) |
|
||||
(scap_val_11b << 3) |
|
||||
lpf_11b;
|
||||
rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
|
||||
(scap_val_11n_20 << 3) |
|
||||
lpf_20;
|
||||
rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
|
||||
(scap_val_11n_40 << 3) |
|
||||
lpf_40;
|
||||
for (core = 0; core < 2; core++) {
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
|
||||
rx2tx_lut_20_11b);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
|
||||
rx2tx_lut_20_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
|
||||
rx2tx_lut_20_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
|
||||
rx2tx_lut_40_11n);
|
||||
}
|
||||
b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2);
|
||||
}
|
||||
b43_phy_write(dev, 0x32F, 0x3);
|
||||
if (phy->radio_rev == 4 || phy->radio_rev == 6)
|
||||
b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0);
|
||||
|
||||
if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
|
||||
if (sprom->revision &&
|
||||
sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {
|
||||
b43_radio_write(dev, 0x5, 0x05);
|
||||
b43_radio_write(dev, 0x6, 0x30);
|
||||
b43_radio_write(dev, 0x7, 0x00);
|
||||
b43_radio_set(dev, 0x4f, 0x1);
|
||||
b43_radio_set(dev, 0xd4, 0x1);
|
||||
bias = 0x1f;
|
||||
conv = 0x6f;
|
||||
filt = 0xaa;
|
||||
} else {
|
||||
bias = 0x2b;
|
||||
conv = 0x7f;
|
||||
filt = 0xee;
|
||||
}
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x5F, bias);
|
||||
b43_radio_write(dev, 0x64, conv);
|
||||
b43_radio_write(dev, 0x66, filt);
|
||||
} else {
|
||||
b43_radio_write(dev, 0xE8, bias);
|
||||
b43_radio_write(dev, 0xE9, conv);
|
||||
b43_radio_write(dev, 0xEB, filt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b43_nphy_ipa(dev)) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
|
||||
phy->radio_rev == 6) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0)
|
||||
b43_radio_write(dev, 0x51,
|
||||
0x7f);
|
||||
else
|
||||
b43_radio_write(dev, 0xd6,
|
||||
0x7f);
|
||||
}
|
||||
}
|
||||
if (phy->radio_rev == 3) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x64,
|
||||
0x13);
|
||||
b43_radio_write(dev, 0x5F,
|
||||
0x1F);
|
||||
b43_radio_write(dev, 0x66,
|
||||
0xEE);
|
||||
b43_radio_write(dev, 0x59,
|
||||
0x8A);
|
||||
b43_radio_write(dev, 0x80,
|
||||
0x3E);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x69,
|
||||
0x13);
|
||||
b43_radio_write(dev, 0xE8,
|
||||
0x1F);
|
||||
b43_radio_write(dev, 0xEB,
|
||||
0xEE);
|
||||
b43_radio_write(dev, 0xDE,
|
||||
0x8A);
|
||||
b43_radio_write(dev, 0x105,
|
||||
0x3E);
|
||||
}
|
||||
}
|
||||
} else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
|
||||
if (!phy->is_40mhz) {
|
||||
b43_radio_write(dev, 0x5F, 0x14);
|
||||
b43_radio_write(dev, 0xE8, 0x12);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x5F, 0x16);
|
||||
b43_radio_write(dev, 0xE8, 0x16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
u16 freq = phy->channel_freq;
|
||||
if ((freq >= 5180 && freq <= 5230) ||
|
||||
(freq >= 5745 && freq <= 5805)) {
|
||||
b43_radio_write(dev, 0x7D, 0xFF);
|
||||
b43_radio_write(dev, 0xFE, 0xFF);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (phy->radio_rev != 5) {
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x5c, 0x61);
|
||||
b43_radio_write(dev, 0x51, 0x70);
|
||||
} else {
|
||||
b43_radio_write(dev, 0xe1, 0x61);
|
||||
b43_radio_write(dev, 0xd6, 0x70);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (phy->radio_rev == 4) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
|
||||
for (core = 0; core < 2; core++) {
|
||||
if (core == 0) {
|
||||
b43_radio_write(dev, 0x1a1, 0x00);
|
||||
b43_radio_write(dev, 0x1a2, 0x3f);
|
||||
b43_radio_write(dev, 0x1a6, 0x3f);
|
||||
} else {
|
||||
b43_radio_write(dev, 0x1a7, 0x00);
|
||||
b43_radio_write(dev, 0x1ab, 0x3f);
|
||||
b43_radio_write(dev, 0x1ac, 0x3f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
|
||||
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
|
||||
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
|
||||
}
|
||||
|
||||
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
|
||||
b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
|
||||
|
||||
if (!phy->is_40mhz) {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
|
||||
} else {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
|
||||
}
|
||||
|
||||
b43_nphy_gain_ctl_workarounds(dev);
|
||||
|
||||
/* TODO
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
|
||||
aux_adc_vmid_rev7_core0);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
|
||||
aux_adc_vmid_rev7_core1);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
|
||||
aux_adc_gain_rev7);
|
||||
b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
|
||||
aux_adc_gain_rev7);
|
||||
*/
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
@ -1916,7 +2482,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
rx2tx_delays[6] = 1;
|
||||
rx2tx_events[7] = 0x1F;
|
||||
}
|
||||
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
|
||||
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
|
||||
ARRAY_SIZE(rx2tx_events));
|
||||
}
|
||||
|
||||
@ -1926,8 +2492,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
|
||||
b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
|
||||
if (!dev->phy.is_40mhz) {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
|
||||
} else {
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
|
||||
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
|
||||
}
|
||||
|
||||
b43_nphy_gain_ctl_workarounds(dev);
|
||||
|
||||
@ -1963,13 +2534,14 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
|
||||
|
||||
if (dev->phy.rev == 4 &&
|
||||
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
|
||||
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
|
||||
b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
|
||||
0x70);
|
||||
b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
|
||||
0x70);
|
||||
}
|
||||
|
||||
/* Dropped probably-always-true condition */
|
||||
b43_phy_write(dev, 0x224, 0x03eb);
|
||||
b43_phy_write(dev, 0x225, 0x03eb);
|
||||
b43_phy_write(dev, 0x226, 0x0341);
|
||||
@ -1982,6 +2554,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, 0x22d, 0x042b);
|
||||
b43_phy_write(dev, 0x22e, 0x0381);
|
||||
b43_phy_write(dev, 0x22f, 0x0381);
|
||||
|
||||
if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
|
||||
; /* TODO: 0x0080000000000000 HF */
|
||||
}
|
||||
|
||||
static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
@ -1996,6 +2571,12 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
|
||||
u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
|
||||
|
||||
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
|
||||
dev->dev->board_type == 0x8B) {
|
||||
delays1[0] = 0x1;
|
||||
delays1[5] = 0x14;
|
||||
}
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
|
||||
nphy->band5g_pwrgain) {
|
||||
b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
|
||||
@ -2007,8 +2588,10 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
|
||||
if (dev->phy.rev < 3) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
|
||||
}
|
||||
|
||||
if (dev->phy.rev < 2) {
|
||||
b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
|
||||
@ -2024,11 +2607,6 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
|
||||
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
|
||||
|
||||
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
|
||||
dev->dev->board_type == 0x8B) {
|
||||
delays1[0] = 0x1;
|
||||
delays1[5] = 0x14;
|
||||
}
|
||||
b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
|
||||
b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
|
||||
|
||||
@ -2055,11 +2633,13 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
|
||||
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
|
||||
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
|
||||
if (dev->phy.rev < 3) {
|
||||
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
|
||||
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
|
||||
}
|
||||
|
||||
if (dev->phy.rev == 2)
|
||||
b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
|
||||
@ -2083,7 +2663,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
|
||||
b43_phy_set(dev, B43_NPHY_IQFLIP,
|
||||
B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
|
||||
|
||||
if (dev->phy.rev >= 3)
|
||||
if (dev->phy.rev >= 7)
|
||||
b43_nphy_workarounds_rev7plus(dev);
|
||||
else if (dev->phy.rev >= 3)
|
||||
b43_nphy_workarounds_rev3plus(dev);
|
||||
else
|
||||
b43_nphy_workarounds_rev1_2(dev);
|
||||
@ -2542,7 +3124,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
b43_nphy_ipa_internal_tssi_setup(dev);
|
||||
|
||||
if (phy->rev >= 7)
|
||||
; /* TODO: Override Rev7 with 0x2000, 0, 3, 0, 0 as arguments */
|
||||
b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0);
|
||||
else if (phy->rev >= 3)
|
||||
b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
|
||||
|
||||
@ -2554,7 +3136,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
|
||||
b43_nphy_rssi_select(dev, 0, 0);
|
||||
|
||||
if (phy->rev >= 7)
|
||||
; /* TODO: Override Rev7 with 0x2000, 0, 3, 1, 0 as arguments */
|
||||
b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0);
|
||||
else if (phy->rev >= 3)
|
||||
b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
|
||||
|
||||
@ -4761,6 +5343,7 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
|
||||
nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
|
||||
nphy->spur_avoid = (phy->rev >= 3) ?
|
||||
B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
|
||||
nphy->init_por = true;
|
||||
nphy->gain_boost = true; /* this way we follow wl, assume it is true */
|
||||
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
|
||||
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
|
||||
@ -4801,6 +5384,8 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
|
||||
nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
|
||||
nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
|
||||
}
|
||||
|
||||
nphy->init_por = true;
|
||||
}
|
||||
|
||||
static void b43_nphy_op_free(struct b43_wldev *dev)
|
||||
@ -4887,7 +5472,9 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
if (blocked) {
|
||||
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
|
||||
~B43_NPHY_RFCTL_CMD_CHIP0PU);
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (dev->phy.rev >= 7) {
|
||||
/* TODO */
|
||||
} else if (dev->phy.rev >= 3) {
|
||||
b43_radio_mask(dev, 0x09, ~0x2);
|
||||
|
||||
b43_radio_write(dev, 0x204D, 0);
|
||||
@ -4905,7 +5492,10 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
b43_radio_write(dev, 0x3064, 0);
|
||||
}
|
||||
} else {
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (dev->phy.rev >= 7) {
|
||||
b43_radio_2057_init(dev);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
} else if (dev->phy.rev >= 3) {
|
||||
b43_radio_init2056(dev);
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
} else {
|
||||
|
@ -785,6 +785,7 @@ struct b43_phy_n {
|
||||
u16 papd_epsilon_offset[2];
|
||||
s32 preamble_override;
|
||||
u32 bb_mult_save;
|
||||
bool init_por;
|
||||
|
||||
bool gain_boost;
|
||||
bool elna_gain_config;
|
||||
|
141
drivers/net/wireless/b43/radio_2057.c
Normal file
141
drivers/net/wireless/b43/radio_2057.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
IEEE 802.11n 2057 radio device data tables
|
||||
|
||||
Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "b43.h"
|
||||
#include "radio_2057.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
static u16 r2057_rev4_init[42][2] = {
|
||||
{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
|
||||
{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
|
||||
{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
|
||||
{ 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c },
|
||||
{ 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 },
|
||||
{ 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c },
|
||||
{ 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
|
||||
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
|
||||
{ 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
|
||||
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
|
||||
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev5_init[44][2] = {
|
||||
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
|
||||
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
|
||||
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
|
||||
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
|
||||
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
|
||||
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
|
||||
{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
|
||||
{ 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 },
|
||||
{ 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 },
|
||||
{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev5a_init[45][2] = {
|
||||
{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
|
||||
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
|
||||
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
|
||||
{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
|
||||
{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
|
||||
{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 },
|
||||
{ 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 },
|
||||
{ 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
|
||||
{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
|
||||
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 },
|
||||
{ 0x1C2, 0x80 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev7_init[54][2] = {
|
||||
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
|
||||
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
|
||||
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
|
||||
{ 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 },
|
||||
{ 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f },
|
||||
{ 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
|
||||
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee },
|
||||
{ 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 },
|
||||
{ 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 },
|
||||
{ 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
|
||||
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
|
||||
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
|
||||
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
|
||||
};
|
||||
|
||||
static u16 r2057_rev8_init[54][2] = {
|
||||
{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
|
||||
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
|
||||
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
|
||||
{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
|
||||
{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
|
||||
{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
|
||||
{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
|
||||
{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
|
||||
{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
|
||||
{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
|
||||
{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
|
||||
{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
|
||||
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
|
||||
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
|
||||
};
|
||||
|
||||
void r2057_upload_inittabs(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u16 *table = NULL;
|
||||
u16 size, i;
|
||||
|
||||
if (phy->rev == 7) {
|
||||
table = r2057_rev4_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev4_init);
|
||||
} else if (phy->rev == 8 || phy->rev == 9) {
|
||||
if (phy->radio_rev == 5) {
|
||||
if (phy->radio_rev == 8) {
|
||||
table = r2057_rev5_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev5_init);
|
||||
} else {
|
||||
table = r2057_rev5a_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev5a_init);
|
||||
}
|
||||
} else if (phy->radio_rev == 7) {
|
||||
table = r2057_rev7_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev7_init);
|
||||
} else if (phy->radio_rev == 9) {
|
||||
table = r2057_rev8_init[0];
|
||||
size = ARRAY_SIZE(r2057_rev8_init);
|
||||
}
|
||||
}
|
||||
|
||||
if (table) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
pr_info("radio_write 0x%X ", *table);
|
||||
table++;
|
||||
pr_info("0x%X\n", *table);
|
||||
table++;
|
||||
}
|
||||
}
|
||||
}
|
430
drivers/net/wireless/b43/radio_2057.h
Normal file
430
drivers/net/wireless/b43/radio_2057.h
Normal file
@ -0,0 +1,430 @@
|
||||
#ifndef B43_RADIO_2057_H_
|
||||
#define B43_RADIO_2057_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "tables_nphy.h"
|
||||
|
||||
#define R2057_DACBUF_VINCM_CORE0 0x000
|
||||
#define R2057_IDCODE 0x001
|
||||
#define R2057_RCCAL_MASTER 0x002
|
||||
#define R2057_RCCAL_CAP_SIZE 0x003
|
||||
#define R2057_RCAL_CONFIG 0x004
|
||||
#define R2057_GPAIO_CONFIG 0x005
|
||||
#define R2057_GPAIO_SEL1 0x006
|
||||
#define R2057_GPAIO_SEL0 0x007
|
||||
#define R2057_CLPO_CONFIG 0x008
|
||||
#define R2057_BANDGAP_CONFIG 0x009
|
||||
#define R2057_BANDGAP_RCAL_TRIM 0x00a
|
||||
#define R2057_AFEREG_CONFIG 0x00b
|
||||
#define R2057_TEMPSENSE_CONFIG 0x00c
|
||||
#define R2057_XTAL_CONFIG1 0x00d
|
||||
#define R2057_XTAL_ICORE_SIZE 0x00e
|
||||
#define R2057_XTAL_BUF_SIZE 0x00f
|
||||
#define R2057_XTAL_PULLCAP_SIZE 0x010
|
||||
#define R2057_RFPLL_MASTER 0x011
|
||||
#define R2057_VCOMONITOR_VTH_L 0x012
|
||||
#define R2057_VCOMONITOR_VTH_H 0x013
|
||||
#define R2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x014
|
||||
#define R2057_VCO_VARCSIZE_IDAC 0x015
|
||||
#define R2057_VCOCAL_COUNTVAL0 0x016
|
||||
#define R2057_VCOCAL_COUNTVAL1 0x017
|
||||
#define R2057_VCOCAL_INTCLK_COUNT 0x018
|
||||
#define R2057_VCOCAL_MASTER 0x019
|
||||
#define R2057_VCOCAL_NUMCAPCHANGE 0x01a
|
||||
#define R2057_VCOCAL_WINSIZE 0x01b
|
||||
#define R2057_VCOCAL_DELAY_AFTER_REFRESH 0x01c
|
||||
#define R2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x01d
|
||||
#define R2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x01e
|
||||
#define R2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x01f
|
||||
#define R2057_VCO_FORCECAPEN_FORCECAP1 0x020
|
||||
#define R2057_VCO_FORCECAP0 0x021
|
||||
#define R2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x022
|
||||
#define R2057_RFPLL_PFD_RESET_PW 0x023
|
||||
#define R2057_RFPLL_LOOPFILTER_R2 0x024
|
||||
#define R2057_RFPLL_LOOPFILTER_R1 0x025
|
||||
#define R2057_RFPLL_LOOPFILTER_C3 0x026
|
||||
#define R2057_RFPLL_LOOPFILTER_C2 0x027
|
||||
#define R2057_RFPLL_LOOPFILTER_C1 0x028
|
||||
#define R2057_CP_KPD_IDAC 0x029
|
||||
#define R2057_RFPLL_IDACS 0x02a
|
||||
#define R2057_RFPLL_MISC_EN 0x02b
|
||||
#define R2057_RFPLL_MMD0 0x02c
|
||||
#define R2057_RFPLL_MMD1 0x02d
|
||||
#define R2057_RFPLL_MISC_CAL_RESETN 0x02e
|
||||
#define R2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x02f
|
||||
#define R2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x030
|
||||
#define R2057_VCOCAL_READCAP0 0x031
|
||||
#define R2057_VCOCAL_READCAP1 0x032
|
||||
#define R2057_VCOCAL_STATUS 0x033
|
||||
#define R2057_LOGEN_PUS 0x034
|
||||
#define R2057_LOGEN_PTAT_RESETS 0x035
|
||||
#define R2057_VCOBUF_IDACS 0x036
|
||||
#define R2057_VCOBUF_TUNE 0x037
|
||||
#define R2057_CMOSBUF_TX2GQ_IDACS 0x038
|
||||
#define R2057_CMOSBUF_TX2GI_IDACS 0x039
|
||||
#define R2057_CMOSBUF_TX5GQ_IDACS 0x03a
|
||||
#define R2057_CMOSBUF_TX5GI_IDACS 0x03b
|
||||
#define R2057_CMOSBUF_RX2GQ_IDACS 0x03c
|
||||
#define R2057_CMOSBUF_RX2GI_IDACS 0x03d
|
||||
#define R2057_CMOSBUF_RX5GQ_IDACS 0x03e
|
||||
#define R2057_CMOSBUF_RX5GI_IDACS 0x03f
|
||||
#define R2057_LOGEN_MX2G_IDACS 0x040
|
||||
#define R2057_LOGEN_MX2G_TUNE 0x041
|
||||
#define R2057_LOGEN_MX5G_IDACS 0x042
|
||||
#define R2057_LOGEN_MX5G_TUNE 0x043
|
||||
#define R2057_LOGEN_MX5G_RCCR 0x044
|
||||
#define R2057_LOGEN_INDBUF2G_IDAC 0x045
|
||||
#define R2057_LOGEN_INDBUF2G_IBOOST 0x046
|
||||
#define R2057_LOGEN_INDBUF2G_TUNE 0x047
|
||||
#define R2057_LOGEN_INDBUF5G_IDAC 0x048
|
||||
#define R2057_LOGEN_INDBUF5G_IBOOST 0x049
|
||||
#define R2057_LOGEN_INDBUF5G_TUNE 0x04a
|
||||
#define R2057_CMOSBUF_TX_RCCR 0x04b
|
||||
#define R2057_CMOSBUF_RX_RCCR 0x04c
|
||||
#define R2057_LOGEN_SEL_PKDET 0x04d
|
||||
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
|
||||
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
|
||||
#define R2057_TXGM_TXRF_PUS_CORE0 0x050
|
||||
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
|
||||
#define R2057_TXGM_GAIN_CORE0 0x056
|
||||
#define R2057_TXGM2G_PKDET_PUS_CORE0 0x057
|
||||
#define R2057_PAD2G_PTATS_CORE0 0x058
|
||||
#define R2057_PAD2G_IDACS_CORE0 0x059
|
||||
#define R2057_PAD2G_BOOST_PU_CORE0 0x05a
|
||||
#define R2057_PAD2G_CASCV_GAIN_CORE0 0x05b
|
||||
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x05c
|
||||
#define R2057_TXMIX2G_LODC_CORE0 0x05d
|
||||
#define R2057_PAD2G_TUNE_PUS_CORE0 0x05e
|
||||
#define R2057_IPA2G_GAIN_CORE0 0x05f
|
||||
#define R2057_TSSI2G_SPARE1_CORE0 0x060
|
||||
#define R2057_TSSI2G_SPARE2_CORE0 0x061
|
||||
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x062
|
||||
#define R2057_IPA2G_IMAIN_CORE0 0x063
|
||||
#define R2057_IPA2G_CASCONV_CORE0 0x064
|
||||
#define R2057_IPA2G_CASCOFFV_CORE0 0x065
|
||||
#define R2057_IPA2G_BIAS_FILTER_CORE0 0x066
|
||||
#define R2057_TX5G_PKDET_CORE0 0x069
|
||||
#define R2057_PGA_PTAT_TXGM5G_PU_CORE0 0x06a
|
||||
#define R2057_PAD5G_PTATS1_CORE0 0x06b
|
||||
#define R2057_PAD5G_CLASS_PTATS2_CORE0 0x06c
|
||||
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x06d
|
||||
#define R2057_PAD5G_CASCV_IMAIN_CORE0 0x06e
|
||||
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x06f
|
||||
#define R2057_PGA_BOOST_TUNE_CORE0 0x070
|
||||
#define R2057_PGA_GAIN_CORE0 0x071
|
||||
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x072
|
||||
#define R2057_TXMIX5G_BOOST_TUNE_CORE0 0x073
|
||||
#define R2057_PAD5G_TUNE_MISC_PUS_CORE0 0x074
|
||||
#define R2057_IPA5G_IAUX_CORE0 0x075
|
||||
#define R2057_IPA5G_GAIN_CORE0 0x076
|
||||
#define R2057_TSSI5G_SPARE1_CORE0 0x077
|
||||
#define R2057_TSSI5G_SPARE2_CORE0 0x078
|
||||
#define R2057_IPA5G_CASCOFFV_PU_CORE0 0x079
|
||||
#define R2057_IPA5G_PTAT_CORE0 0x07a
|
||||
#define R2057_IPA5G_IMAIN_CORE0 0x07b
|
||||
#define R2057_IPA5G_CASCONV_CORE0 0x07c
|
||||
#define R2057_IPA5G_BIAS_FILTER_CORE0 0x07d
|
||||
#define R2057_PAD_BIAS_FILTER_BWS_CORE0 0x080
|
||||
#define R2057_TR2G_CONFIG1_CORE0_NU 0x081
|
||||
#define R2057_TR2G_CONFIG2_CORE0_NU 0x082
|
||||
#define R2057_LNA5G_RFEN_CORE0 0x083
|
||||
#define R2057_TR5G_CONFIG2_CORE0_NU 0x084
|
||||
#define R2057_RXRFBIAS_IBOOST_PU_CORE0 0x085
|
||||
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x086
|
||||
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x087
|
||||
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x088
|
||||
#define R2057_RXMIX_CMFBITAIL_PU_CORE0 0x089
|
||||
#define R2057_LNA2_IMAIN_PTAT_PU_CORE0 0x08a
|
||||
#define R2057_LNA2_IAUX_PTAT_CORE0 0x08b
|
||||
#define R2057_LNA1_IMAIN_PTAT_PU_CORE0 0x08c
|
||||
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x08d
|
||||
#define R2057_RXRFBIAS_BANDSEL_CORE0 0x08e
|
||||
#define R2057_TIA_CONFIG_CORE0 0x08f
|
||||
#define R2057_TIA_IQGAIN_CORE0 0x090
|
||||
#define R2057_TIA_IBIAS2_CORE0 0x091
|
||||
#define R2057_TIA_IBIAS1_CORE0 0x092
|
||||
#define R2057_TIA_SPARE_Q_CORE0 0x093
|
||||
#define R2057_TIA_SPARE_I_CORE0 0x094
|
||||
#define R2057_RXMIX2G_PUS_CORE0 0x095
|
||||
#define R2057_RXMIX2G_VCMREFS_CORE0 0x096
|
||||
#define R2057_RXMIX2G_LODC_QI_CORE0 0x097
|
||||
#define R2057_W12G_BW_LNA2G_PUS_CORE0 0x098
|
||||
#define R2057_LNA2G_GAIN_CORE0 0x099
|
||||
#define R2057_LNA2G_TUNE_CORE0 0x09a
|
||||
#define R2057_RXMIX5G_PUS_CORE0 0x09b
|
||||
#define R2057_RXMIX5G_VCMREFS_CORE0 0x09c
|
||||
#define R2057_RXMIX5G_LODC_QI_CORE0 0x09d
|
||||
#define R2057_W15G_BW_LNA5G_PUS_CORE0 0x09e
|
||||
#define R2057_LNA5G_GAIN_CORE0 0x09f
|
||||
#define R2057_LNA5G_TUNE_CORE0 0x0a0
|
||||
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0x0a1
|
||||
#define R2057_RXBB_BIAS_MASTER_CORE0 0x0a2
|
||||
#define R2057_RXBB_VGABUF_IDACS_CORE0 0x0a3
|
||||
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0x0a4
|
||||
#define R2057_TXBUF_VINCM_CORE0 0x0a5
|
||||
#define R2057_TXBUF_IDACS_CORE0 0x0a6
|
||||
#define R2057_LPF_RESP_RXBUF_BW_CORE0 0x0a7
|
||||
#define R2057_RXBB_CC_CORE0 0x0a8
|
||||
#define R2057_RXBB_SPARE3_CORE0 0x0a9
|
||||
#define R2057_RXBB_RCCAL_HPC_CORE0 0x0aa
|
||||
#define R2057_LPF_IDACS_CORE0 0x0ab
|
||||
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0x0ac
|
||||
#define R2057_TXBUF_GAIN_CORE0 0x0ad
|
||||
#define R2057_AFELOOPBACK_AACI_RESP_CORE0 0x0ae
|
||||
#define R2057_RXBUF_DEGEN_CORE0 0x0af
|
||||
#define R2057_RXBB_SPARE2_CORE0 0x0b0
|
||||
#define R2057_RXBB_SPARE1_CORE0 0x0b1
|
||||
#define R2057_RSSI_MASTER_CORE0 0x0b2
|
||||
#define R2057_W2_MASTER_CORE0 0x0b3
|
||||
#define R2057_NB_MASTER_CORE0 0x0b4
|
||||
#define R2057_W2_IDACS0_Q_CORE0 0x0b5
|
||||
#define R2057_W2_IDACS1_Q_CORE0 0x0b6
|
||||
#define R2057_W2_IDACS0_I_CORE0 0x0b7
|
||||
#define R2057_W2_IDACS1_I_CORE0 0x0b8
|
||||
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0x0b9
|
||||
#define R2057_NB_IDACS_Q_CORE0 0x0ba
|
||||
#define R2057_NB_IDACS_I_CORE0 0x0bb
|
||||
#define R2057_BACKUP4_CORE0 0x0c1
|
||||
#define R2057_BACKUP3_CORE0 0x0c2
|
||||
#define R2057_BACKUP2_CORE0 0x0c3
|
||||
#define R2057_BACKUP1_CORE0 0x0c4
|
||||
#define R2057_SPARE16_CORE0 0x0c5
|
||||
#define R2057_SPARE15_CORE0 0x0c6
|
||||
#define R2057_SPARE14_CORE0 0x0c7
|
||||
#define R2057_SPARE13_CORE0 0x0c8
|
||||
#define R2057_SPARE12_CORE0 0x0c9
|
||||
#define R2057_SPARE11_CORE0 0x0ca
|
||||
#define R2057_TX2G_BIAS_RESETS_CORE0 0x0cb
|
||||
#define R2057_TX5G_BIAS_RESETS_CORE0 0x0cc
|
||||
#define R2057_IQTEST_SEL_PU 0x0cd
|
||||
#define R2057_XTAL_CONFIG2 0x0ce
|
||||
#define R2057_BUFS_MISC_LPFBW_CORE0 0x0cf
|
||||
#define R2057_TXLPF_RCCAL_CORE0 0x0d0
|
||||
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
|
||||
#define R2057_LPF_GAIN_CORE0 0x0d2
|
||||
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
|
||||
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
|
||||
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
|
||||
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
|
||||
#define R2057_TXGM_GAIN_CORE1 0x0db
|
||||
#define R2057_TXGM2G_PKDET_PUS_CORE1 0x0dc
|
||||
#define R2057_PAD2G_PTATS_CORE1 0x0dd
|
||||
#define R2057_PAD2G_IDACS_CORE1 0x0de
|
||||
#define R2057_PAD2G_BOOST_PU_CORE1 0x0df
|
||||
#define R2057_PAD2G_CASCV_GAIN_CORE1 0x0e0
|
||||
#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0x0e1
|
||||
#define R2057_TXMIX2G_LODC_CORE1 0x0e2
|
||||
#define R2057_PAD2G_TUNE_PUS_CORE1 0x0e3
|
||||
#define R2057_IPA2G_GAIN_CORE1 0x0e4
|
||||
#define R2057_TSSI2G_SPARE1_CORE1 0x0e5
|
||||
#define R2057_TSSI2G_SPARE2_CORE1 0x0e6
|
||||
#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0x0e7
|
||||
#define R2057_IPA2G_IMAIN_CORE1 0x0e8
|
||||
#define R2057_IPA2G_CASCONV_CORE1 0x0e9
|
||||
#define R2057_IPA2G_CASCOFFV_CORE1 0x0ea
|
||||
#define R2057_IPA2G_BIAS_FILTER_CORE1 0x0eb
|
||||
#define R2057_TX5G_PKDET_CORE1 0x0ee
|
||||
#define R2057_PGA_PTAT_TXGM5G_PU_CORE1 0x0ef
|
||||
#define R2057_PAD5G_PTATS1_CORE1 0x0f0
|
||||
#define R2057_PAD5G_CLASS_PTATS2_CORE1 0x0f1
|
||||
#define R2057_PGA_BOOSTPTAT_IMAIN_CORE1 0x0f2
|
||||
#define R2057_PAD5G_CASCV_IMAIN_CORE1 0x0f3
|
||||
#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0x0f4
|
||||
#define R2057_PGA_BOOST_TUNE_CORE1 0x0f5
|
||||
#define R2057_PGA_GAIN_CORE1 0x0f6
|
||||
#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0x0f7
|
||||
#define R2057_TXMIX5G_BOOST_TUNE_CORE1 0x0f8
|
||||
#define R2057_PAD5G_TUNE_MISC_PUS_CORE1 0x0f9
|
||||
#define R2057_IPA5G_IAUX_CORE1 0x0fa
|
||||
#define R2057_IPA5G_GAIN_CORE1 0x0fb
|
||||
#define R2057_TSSI5G_SPARE1_CORE1 0x0fc
|
||||
#define R2057_TSSI5G_SPARE2_CORE1 0x0fd
|
||||
#define R2057_IPA5G_CASCOFFV_PU_CORE1 0x0fe
|
||||
#define R2057_IPA5G_PTAT_CORE1 0x0ff
|
||||
#define R2057_IPA5G_IMAIN_CORE1 0x100
|
||||
#define R2057_IPA5G_CASCONV_CORE1 0x101
|
||||
#define R2057_IPA5G_BIAS_FILTER_CORE1 0x102
|
||||
#define R2057_PAD_BIAS_FILTER_BWS_CORE1 0x105
|
||||
#define R2057_TR2G_CONFIG1_CORE1_NU 0x106
|
||||
#define R2057_TR2G_CONFIG2_CORE1_NU 0x107
|
||||
#define R2057_LNA5G_RFEN_CORE1 0x108
|
||||
#define R2057_TR5G_CONFIG2_CORE1_NU 0x109
|
||||
#define R2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a
|
||||
#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
|
||||
#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c
|
||||
#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d
|
||||
#define R2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e
|
||||
#define R2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f
|
||||
#define R2057_LNA2_IAUX_PTAT_CORE1 0x110
|
||||
#define R2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111
|
||||
#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
|
||||
#define R2057_RXRFBIAS_BANDSEL_CORE1 0x113
|
||||
#define R2057_TIA_CONFIG_CORE1 0x114
|
||||
#define R2057_TIA_IQGAIN_CORE1 0x115
|
||||
#define R2057_TIA_IBIAS2_CORE1 0x116
|
||||
#define R2057_TIA_IBIAS1_CORE1 0x117
|
||||
#define R2057_TIA_SPARE_Q_CORE1 0x118
|
||||
#define R2057_TIA_SPARE_I_CORE1 0x119
|
||||
#define R2057_RXMIX2G_PUS_CORE1 0x11a
|
||||
#define R2057_RXMIX2G_VCMREFS_CORE1 0x11b
|
||||
#define R2057_RXMIX2G_LODC_QI_CORE1 0x11c
|
||||
#define R2057_W12G_BW_LNA2G_PUS_CORE1 0x11d
|
||||
#define R2057_LNA2G_GAIN_CORE1 0x11e
|
||||
#define R2057_LNA2G_TUNE_CORE1 0x11f
|
||||
#define R2057_RXMIX5G_PUS_CORE1 0x120
|
||||
#define R2057_RXMIX5G_VCMREFS_CORE1 0x121
|
||||
#define R2057_RXMIX5G_LODC_QI_CORE1 0x122
|
||||
#define R2057_W15G_BW_LNA5G_PUS_CORE1 0x123
|
||||
#define R2057_LNA5G_GAIN_CORE1 0x124
|
||||
#define R2057_LNA5G_TUNE_CORE1 0x125
|
||||
#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126
|
||||
#define R2057_RXBB_BIAS_MASTER_CORE1 0x127
|
||||
#define R2057_RXBB_VGABUF_IDACS_CORE1 0x128
|
||||
#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
|
||||
#define R2057_TXBUF_VINCM_CORE1 0x12a
|
||||
#define R2057_TXBUF_IDACS_CORE1 0x12b
|
||||
#define R2057_LPF_RESP_RXBUF_BW_CORE1 0x12c
|
||||
#define R2057_RXBB_CC_CORE1 0x12d
|
||||
#define R2057_RXBB_SPARE3_CORE1 0x12e
|
||||
#define R2057_RXBB_RCCAL_HPC_CORE1 0x12f
|
||||
#define R2057_LPF_IDACS_CORE1 0x130
|
||||
#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131
|
||||
#define R2057_TXBUF_GAIN_CORE1 0x132
|
||||
#define R2057_AFELOOPBACK_AACI_RESP_CORE1 0x133
|
||||
#define R2057_RXBUF_DEGEN_CORE1 0x134
|
||||
#define R2057_RXBB_SPARE2_CORE1 0x135
|
||||
#define R2057_RXBB_SPARE1_CORE1 0x136
|
||||
#define R2057_RSSI_MASTER_CORE1 0x137
|
||||
#define R2057_W2_MASTER_CORE1 0x138
|
||||
#define R2057_NB_MASTER_CORE1 0x139
|
||||
#define R2057_W2_IDACS0_Q_CORE1 0x13a
|
||||
#define R2057_W2_IDACS1_Q_CORE1 0x13b
|
||||
#define R2057_W2_IDACS0_I_CORE1 0x13c
|
||||
#define R2057_W2_IDACS1_I_CORE1 0x13d
|
||||
#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e
|
||||
#define R2057_NB_IDACS_Q_CORE1 0x13f
|
||||
#define R2057_NB_IDACS_I_CORE1 0x140
|
||||
#define R2057_BACKUP4_CORE1 0x146
|
||||
#define R2057_BACKUP3_CORE1 0x147
|
||||
#define R2057_BACKUP2_CORE1 0x148
|
||||
#define R2057_BACKUP1_CORE1 0x149
|
||||
#define R2057_SPARE16_CORE1 0x14a
|
||||
#define R2057_SPARE15_CORE1 0x14b
|
||||
#define R2057_SPARE14_CORE1 0x14c
|
||||
#define R2057_SPARE13_CORE1 0x14d
|
||||
#define R2057_SPARE12_CORE1 0x14e
|
||||
#define R2057_SPARE11_CORE1 0x14f
|
||||
#define R2057_TX2G_BIAS_RESETS_CORE1 0x150
|
||||
#define R2057_TX5G_BIAS_RESETS_CORE1 0x151
|
||||
#define R2057_SPARE8_CORE1 0x152
|
||||
#define R2057_SPARE7_CORE1 0x153
|
||||
#define R2057_BUFS_MISC_LPFBW_CORE1 0x154
|
||||
#define R2057_TXLPF_RCCAL_CORE1 0x155
|
||||
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
|
||||
#define R2057_LPF_GAIN_CORE1 0x157
|
||||
#define R2057_DACBUF_IDACS_BW_CORE1 0x158
|
||||
#define R2057_DACBUF_VINCM_CORE1 0x159
|
||||
#define R2057_RCCAL_START_R1_Q1_P1 0x15a
|
||||
#define R2057_RCCAL_X1 0x15b
|
||||
#define R2057_RCCAL_TRC0 0x15c
|
||||
#define R2057_RCCAL_TRC1 0x15d
|
||||
#define R2057_RCCAL_DONE_OSCCAP 0x15e
|
||||
#define R2057_RCCAL_N0_0 0x15f
|
||||
#define R2057_RCCAL_N0_1 0x160
|
||||
#define R2057_RCCAL_N1_0 0x161
|
||||
#define R2057_RCCAL_N1_1 0x162
|
||||
#define R2057_RCAL_STATUS 0x163
|
||||
#define R2057_XTALPUOVR_PINCTRL 0x164
|
||||
#define R2057_OVR_REG0 0x165
|
||||
#define R2057_OVR_REG1 0x166
|
||||
#define R2057_OVR_REG2 0x167
|
||||
#define R2057_OVR_REG3 0x168
|
||||
#define R2057_OVR_REG4 0x169
|
||||
#define R2057_RCCAL_SCAP_VAL 0x16a
|
||||
#define R2057_RCCAL_BCAP_VAL 0x16b
|
||||
#define R2057_RCCAL_HPC_VAL 0x16c
|
||||
#define R2057_RCCAL_OVERRIDES 0x16d
|
||||
#define R2057_TX0_IQCAL_GAIN_BW 0x170
|
||||
#define R2057_TX0_LOFT_FINE_I 0x171
|
||||
#define R2057_TX0_LOFT_FINE_Q 0x172
|
||||
#define R2057_TX0_LOFT_COARSE_I 0x173
|
||||
#define R2057_TX0_LOFT_COARSE_Q 0x174
|
||||
#define R2057_TX0_TX_SSI_MASTER 0x175
|
||||
#define R2057_TX0_IQCAL_VCM_HG 0x176
|
||||
#define R2057_TX0_IQCAL_IDAC 0x177
|
||||
#define R2057_TX0_TSSI_VCM 0x178
|
||||
#define R2057_TX0_TX_SSI_MUX 0x179
|
||||
#define R2057_TX0_TSSIA 0x17a
|
||||
#define R2057_TX0_TSSIG 0x17b
|
||||
#define R2057_TX0_TSSI_MISC1 0x17c
|
||||
#define R2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d
|
||||
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
|
||||
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
|
||||
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
|
||||
#define R2057_TX1_IQCAL_GAIN_BW 0x190
|
||||
#define R2057_TX1_LOFT_FINE_I 0x191
|
||||
#define R2057_TX1_LOFT_FINE_Q 0x192
|
||||
#define R2057_TX1_LOFT_COARSE_I 0x193
|
||||
#define R2057_TX1_LOFT_COARSE_Q 0x194
|
||||
#define R2057_TX1_TX_SSI_MASTER 0x195
|
||||
#define R2057_TX1_IQCAL_VCM_HG 0x196
|
||||
#define R2057_TX1_IQCAL_IDAC 0x197
|
||||
#define R2057_TX1_TSSI_VCM 0x198
|
||||
#define R2057_TX1_TX_SSI_MUX 0x199
|
||||
#define R2057_TX1_TSSIA 0x19a
|
||||
#define R2057_TX1_TSSIG 0x19b
|
||||
#define R2057_TX1_TSSI_MISC1 0x19c
|
||||
#define R2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d
|
||||
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
|
||||
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
|
||||
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
|
||||
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
|
||||
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
|
||||
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
|
||||
#define R2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4
|
||||
#define R2057_AFE_STATUS_VCM_I_CORE0 0x1a5
|
||||
#define R2057_AFE_STATUS_VCM_Q_CORE0 0x1a6
|
||||
#define R2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7
|
||||
#define R2057_AFE_SET_VCM_I_CORE1 0x1a8
|
||||
#define R2057_AFE_SET_VCM_Q_CORE1 0x1a9
|
||||
#define R2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa
|
||||
#define R2057_AFE_STATUS_VCM_I_CORE1 0x1ab
|
||||
#define R2057_AFE_STATUS_VCM_Q_CORE1 0x1ac
|
||||
|
||||
#define R2057v7_DACBUF_VINCM_CORE0 0x1ad
|
||||
#define R2057v7_RCCAL_MASTER 0x1ae
|
||||
#define R2057v7_TR2G_CONFIG3_CORE0_NU 0x1af
|
||||
#define R2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0
|
||||
#define R2057v7_LOGEN_PUS1 0x1b1
|
||||
#define R2057v7_OVR_REG5 0x1b2
|
||||
#define R2057v7_OVR_REG6 0x1b3
|
||||
#define R2057v7_OVR_REG7 0x1b4
|
||||
#define R2057v7_OVR_REG8 0x1b5
|
||||
#define R2057v7_OVR_REG9 0x1b6
|
||||
#define R2057v7_OVR_REG10 0x1b7
|
||||
#define R2057v7_OVR_REG11 0x1b8
|
||||
#define R2057v7_OVR_REG12 0x1b9
|
||||
#define R2057v7_OVR_REG13 0x1ba
|
||||
#define R2057v7_OVR_REG14 0x1bb
|
||||
#define R2057v7_OVR_REG15 0x1bc
|
||||
#define R2057v7_OVR_REG16 0x1bd
|
||||
#define R2057v7_OVR_REG1 0x1be
|
||||
#define R2057v7_OVR_REG18 0x1bf
|
||||
#define R2057v7_OVR_REG19 0x1c0
|
||||
#define R2057v7_OVR_REG20 0x1c1
|
||||
#define R2057v7_OVR_REG21 0x1c2
|
||||
#define R2057v7_OVR_REG2 0x1c3
|
||||
#define R2057v7_OVR_REG23 0x1c4
|
||||
#define R2057v7_OVR_REG24 0x1c5
|
||||
#define R2057v7_OVR_REG25 0x1c6
|
||||
#define R2057v7_OVR_REG26 0x1c7
|
||||
#define R2057v7_OVR_REG27 0x1c8
|
||||
#define R2057v7_OVR_REG28 0x1c9
|
||||
#define R2057v7_IQTEST_SEL_PU2 0x1ca
|
||||
|
||||
#define R2057_VCM_MASK 0x7
|
||||
|
||||
void r2057_upload_inittabs(struct b43_wldev *dev);
|
||||
|
||||
#endif /* B43_RADIO_2057_H_ */
|
@ -2757,6 +2757,49 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
|
||||
{ 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over0[] = {
|
||||
{ 0x0004, 0x07A, 0x07D, 0x0002, 1 },
|
||||
{ 0x0008, 0x07A, 0x07D, 0x0004, 2 },
|
||||
{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
|
||||
{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
|
||||
{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
|
||||
{ 0x0080, 0x0F8, 0x0FA, 0x0080, 7 },
|
||||
{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
|
||||
{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
|
||||
{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
|
||||
{ 0x6000, 0x348, 0x349, 0xFFFF, 0 },
|
||||
{ 0x2000, 0x348, 0x349, 0x000F, 0 },
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over1[] = {
|
||||
{ 0x0002, 0x340, 0x341, 0x0002, 1 },
|
||||
{ 0x0008, 0x340, 0x341, 0x0008, 3 },
|
||||
{ 0x0020, 0x340, 0x341, 0x0020, 5 },
|
||||
{ 0x0010, 0x340, 0x341, 0x0010, 4 },
|
||||
{ 0x0004, 0x340, 0x341, 0x0004, 2 },
|
||||
{ 0x0080, 0x340, 0x341, 0x0700, 8 },
|
||||
{ 0x0800, 0x340, 0x341, 0x4000, 14 },
|
||||
{ 0x0400, 0x340, 0x341, 0x2000, 13 },
|
||||
{ 0x0200, 0x340, 0x341, 0x0800, 12 },
|
||||
{ 0x0100, 0x340, 0x341, 0x0100, 11 },
|
||||
{ 0x0040, 0x340, 0x341, 0x0040, 6 },
|
||||
{ 0x0001, 0x340, 0x341, 0x0001, 0 },
|
||||
};
|
||||
|
||||
/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
|
||||
static const struct nphy_rf_control_override_rev7
|
||||
tbl_rf_control_override_rev7_over2[] = {
|
||||
{ 0x0008, 0x344, 0x345, 0x0008, 3 },
|
||||
{ 0x0002, 0x344, 0x345, 0x0002, 1 },
|
||||
{ 0x0001, 0x344, 0x345, 0x0001, 0 },
|
||||
{ 0x0004, 0x344, 0x345, 0x0004, 2 },
|
||||
{ 0x0010, 0x344, 0x345, 0x0010, 4 },
|
||||
};
|
||||
|
||||
struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
|
||||
{ 10, 14, 19, 27 },
|
||||
{ -5, 6, 10, 15 },
|
||||
@ -3248,3 +3291,35 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
|
||||
struct b43_wldev *dev, u16 field, u8 override)
|
||||
{
|
||||
const struct nphy_rf_control_override_rev7 *e;
|
||||
u8 size, i;
|
||||
|
||||
switch (override) {
|
||||
case 0:
|
||||
e = tbl_rf_control_override_rev7_over0;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over0);
|
||||
break;
|
||||
case 1:
|
||||
e = tbl_rf_control_override_rev7_over1;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over1);
|
||||
break;
|
||||
case 2:
|
||||
e = tbl_rf_control_override_rev7_over2;
|
||||
size = ARRAY_SIZE(tbl_rf_control_override_rev7_over2);
|
||||
break;
|
||||
default:
|
||||
b43err(dev->wl, "Invalid override value %d\n", override);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (e[i].field == field)
|
||||
return &e[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -35,6 +35,14 @@ struct nphy_rf_control_override_rev3 {
|
||||
u8 val_addr1;
|
||||
};
|
||||
|
||||
struct nphy_rf_control_override_rev7 {
|
||||
u16 field;
|
||||
u16 val_addr_core0;
|
||||
u16 val_addr_core1;
|
||||
u16 val_mask;
|
||||
u8 val_shift;
|
||||
};
|
||||
|
||||
struct nphy_gain_ctl_workaround_entry {
|
||||
s8 lna1_gain[4];
|
||||
s8 lna2_gain[4];
|
||||
@ -202,5 +210,7 @@ extern const struct nphy_rf_control_override_rev2
|
||||
tbl_rf_control_override_rev2[];
|
||||
extern const struct nphy_rf_control_override_rev3
|
||||
tbl_rf_control_override_rev3[];
|
||||
const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
|
||||
struct b43_wldev *dev, u16 field, u8 override);
|
||||
|
||||
#endif /* B43_TABLES_NPHY_H_ */
|
||||
|
@ -1920,7 +1920,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
|
||||
return 0;
|
||||
ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,
|
||||
(ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)
|
||||
& mask) | set);
|
||||
& ~mask) | set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,7 +86,9 @@ MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
|
||||
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* This needs to be adjusted when brcms_firmwares changes */
|
||||
MODULE_FIRMWARE("brcm/bcm43xx-0.fw");
|
||||
MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw");
|
||||
|
||||
/* recognized BCMA Core IDs */
|
||||
static struct bcma_device_id brcms_coreid_table[] = {
|
||||
|
@ -7512,15 +7512,10 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
|
||||
|
||||
channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
|
||||
|
||||
if (channel > 14) {
|
||||
rx_status->band = IEEE80211_BAND_5GHZ;
|
||||
rx_status->freq = ieee80211_ofdm_chan_to_freq(
|
||||
WF_CHAN_FACTOR_5_G/2, channel);
|
||||
|
||||
} else {
|
||||
rx_status->band = IEEE80211_BAND_2GHZ;
|
||||
rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
|
||||
}
|
||||
rx_status->band =
|
||||
channel > 14 ? IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
|
||||
rx_status->freq =
|
||||
ieee80211_channel_to_frequency(channel, rx_status->band);
|
||||
|
||||
rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh);
|
||||
|
||||
|
@ -67,11 +67,6 @@
|
||||
#define WL_CHANSPEC_BAND_2G 0x2000
|
||||
#define INVCHANSPEC 255
|
||||
|
||||
/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */
|
||||
#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */
|
||||
#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
|
||||
#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
|
||||
|
||||
#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
|
||||
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
|
||||
|
||||
|
@ -4860,7 +4860,7 @@ EXPORT_SYMBOL(il_add_beacon_time);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int
|
||||
static int
|
||||
il_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
@ -4877,9 +4877,8 @@ il_pci_suspend(struct device *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(il_pci_suspend);
|
||||
|
||||
int
|
||||
static int
|
||||
il_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
@ -4906,16 +4905,8 @@ il_pci_resume(struct device *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(il_pci_resume);
|
||||
|
||||
const struct dev_pm_ops il_pm_ops = {
|
||||
.suspend = il_pci_suspend,
|
||||
.resume = il_pci_resume,
|
||||
.freeze = il_pci_suspend,
|
||||
.thaw = il_pci_resume,
|
||||
.poweroff = il_pci_suspend,
|
||||
.restore = il_pci_resume,
|
||||
};
|
||||
SIMPLE_DEV_PM_OPS(il_pm_ops, il_pci_suspend, il_pci_resume);
|
||||
EXPORT_SYMBOL(il_pm_ops);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
@ -1845,8 +1845,6 @@ __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
|
||||
u32 beacon_interval);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int il_pci_suspend(struct device *device);
|
||||
int il_pci_resume(struct device *device);
|
||||
extern const struct dev_pm_ops il_pm_ops;
|
||||
|
||||
#define IL_LEGACY_PM_OPS (&il_pm_ops)
|
||||
|
@ -726,3 +726,29 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function retrieves the entry for specific tx BA stream table by RA and
|
||||
* deletes it.
|
||||
*/
|
||||
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
|
||||
{
|
||||
struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ra)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
|
||||
flags);
|
||||
mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
|
||||
spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
|
||||
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
|
||||
int cmd_action,
|
||||
struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
|
||||
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
|
||||
|
||||
/*
|
||||
* This function checks whether AMPDU is allowed or not for a particular TID.
|
||||
@ -157,4 +158,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks whether associated station is 11n enabled
|
||||
*/
|
||||
static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
|
||||
struct mwifiex_sta_node *node)
|
||||
{
|
||||
|
||||
if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
|
||||
!priv->ap_11n_enabled)
|
||||
return 0;
|
||||
|
||||
return node->is_11n_enabled;
|
||||
}
|
||||
#endif /* !_MWIFIEX_11N_H_ */
|
||||
|
@ -62,9 +62,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
|
||||
};
|
||||
struct tx_packet_hdr *tx_header;
|
||||
|
||||
skb_put(skb_aggr, sizeof(*tx_header));
|
||||
|
||||
tx_header = (struct tx_packet_hdr *) skb_aggr->data;
|
||||
tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
|
||||
|
||||
/* Copy DA and SA */
|
||||
dt_offset = 2 * ETH_ALEN;
|
||||
@ -82,12 +80,10 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
|
||||
tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
|
||||
|
||||
/* Add payload */
|
||||
skb_put(skb_aggr, skb_src->len);
|
||||
memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data,
|
||||
skb_src->len);
|
||||
*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
|
||||
LLC_SNAP_LEN)) & 3)) : 0;
|
||||
skb_put(skb_aggr, *pad);
|
||||
memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
|
||||
|
||||
/* Add padding for new MSDU to start from 4 byte boundary */
|
||||
*pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
|
||||
|
||||
return skb_aggr->len + *pad;
|
||||
}
|
||||
|
@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
|
||||
if (rx_tmp_ptr)
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
if (rx_tmp_ptr) {
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
rx_tmp_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
||||
@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
||||
rx_tmp_ptr = tbl->rx_reorder_ptr[i];
|
||||
tbl->rx_reorder_ptr[i] = NULL;
|
||||
spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
||||
@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
|
||||
* This function returns the pointer to an entry in Rx reordering
|
||||
* table which matches the given TA/TID pair.
|
||||
*/
|
||||
static struct mwifiex_rx_reorder_tbl *
|
||||
struct mwifiex_rx_reorder_tbl *
|
||||
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl;
|
||||
@ -167,6 +176,31 @@ mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function retrieves the pointer to an entry in Rx reordering
|
||||
* table which matches the given TA and deletes it.
|
||||
*/
|
||||
void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
|
||||
{
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ta)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
|
||||
if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
|
||||
flags);
|
||||
mwifiex_del_rx_reorder_entry(priv, tbl);
|
||||
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds the last sequence number used in the packets
|
||||
* buffered in Rx reordering table.
|
||||
@ -226,6 +260,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
||||
struct mwifiex_rx_reorder_tbl *tbl, *new_node;
|
||||
u16 last_seq = 0;
|
||||
unsigned long flags;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
/*
|
||||
* If we get a TID, ta pair which is already present dispatch all the
|
||||
@ -248,13 +283,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
||||
new_node->tid = tid;
|
||||
memcpy(new_node->ta, ta, ETH_ALEN);
|
||||
new_node->start_win = seq_num;
|
||||
if (mwifiex_queuing_ra_based(priv))
|
||||
/* TODO for adhoc */
|
||||
|
||||
if (mwifiex_queuing_ra_based(priv)) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: ADHOC:last_seq=%d start_win=%d\n",
|
||||
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
|
||||
last_seq, new_node->start_win);
|
||||
else
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
last_seq = node->rx_seq[tid];
|
||||
}
|
||||
} else {
|
||||
last_seq = priv->rx_seq[tid];
|
||||
}
|
||||
|
||||
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
|
||||
last_seq >= new_node->start_win)
|
||||
@ -396,8 +437,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
|
||||
|
||||
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
|
||||
if (!tbl) {
|
||||
if (pkt_type != PKT_TYPE_BAR)
|
||||
mwifiex_process_rx_packet(priv->adapter, payload);
|
||||
if (pkt_type != PKT_TYPE_BAR) {
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, payload);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
payload);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
start_win = tbl->start_win;
|
||||
|
@ -38,6 +38,8 @@
|
||||
#define ADDBA_RSP_STATUS_ACCEPT 0
|
||||
|
||||
#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
|
||||
#define BA_SETUP_MAX_PACKET_THRESHOLD 16
|
||||
#define BA_SETUP_PACKET_OFFSET 16
|
||||
|
||||
static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
|
||||
{
|
||||
@ -68,5 +70,8 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
|
||||
mwifiex_private
|
||||
*priv, int tid,
|
||||
u8 *ta);
|
||||
struct mwifiex_rx_reorder_tbl *
|
||||
mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
|
||||
void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
|
||||
|
||||
#endif /* _MWIFIEX_11N_RXREORDER_H_ */
|
||||
|
@ -33,8 +33,10 @@ mwifiex-y += uap_cmd.o
|
||||
mwifiex-y += ie.o
|
||||
mwifiex-y += sta_cmdresp.o
|
||||
mwifiex-y += sta_event.o
|
||||
mwifiex-y += uap_event.o
|
||||
mwifiex-y += sta_tx.o
|
||||
mwifiex-y += sta_rx.o
|
||||
mwifiex-y += uap_txrx.o
|
||||
mwifiex-y += cfg80211.o
|
||||
mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
obj-$(CONFIG_MWIFIEX) += mwifiex.o
|
||||
|
@ -99,7 +99,7 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
|
||||
|
||||
if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) {
|
||||
if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
|
||||
wiphy_err(wiphy, "deleting the crypto keys\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -171,7 +171,8 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
|
||||
if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
|
||||
priv->wep_key_curr_index = key_index;
|
||||
} else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
|
||||
} else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
|
||||
NULL, 0)) {
|
||||
wiphy_err(wiphy, "set default Tx key index\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -207,7 +208,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mwifiex_set_encode(priv, params->key, params->key_len,
|
||||
if (mwifiex_set_encode(priv, params, params->key, params->key_len,
|
||||
key_index, peer_mac, 0)) {
|
||||
wiphy_err(wiphy, "crypto keys added\n");
|
||||
return -EFAULT;
|
||||
@ -748,6 +749,7 @@ static const u32 mwifiex_cipher_suites[] = {
|
||||
WLAN_CIPHER_SUITE_WEP104,
|
||||
WLAN_CIPHER_SUITE_TKIP,
|
||||
WLAN_CIPHER_SUITE_CCMP,
|
||||
WLAN_CIPHER_SUITE_AES_CMAC,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -906,6 +908,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
if (mwifiex_del_mgmt_ies(priv))
|
||||
wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
|
||||
|
||||
priv->ap_11n_enabled = 0;
|
||||
|
||||
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL)) {
|
||||
wiphy_err(wiphy, "Failed to stop the BSS\n");
|
||||
@ -1159,7 +1163,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
priv->wep_key_curr_index = 0;
|
||||
priv->sec_info.encryption_mode = 0;
|
||||
priv->sec_info.is_authtype_auto = 0;
|
||||
ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1);
|
||||
ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
|
||||
|
||||
if (mode == NL80211_IFTYPE_ADHOC) {
|
||||
/* "privacy" is set only for ad-hoc mode */
|
||||
@ -1206,8 +1210,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
"info: setting wep encryption"
|
||||
" with key len %d\n", sme->key_len);
|
||||
priv->wep_key_curr_index = sme->key_idx;
|
||||
ret = mwifiex_set_encode(priv, sme->key, sme->key_len,
|
||||
sme->key_idx, NULL, 0);
|
||||
ret = mwifiex_set_encode(priv, NULL, sme->key,
|
||||
sme->key_len, sme->key_idx,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
@ -447,7 +447,10 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||
}
|
||||
|
||||
ret = mwifiex_process_sta_event(priv);
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
ret = mwifiex_process_uap_event(priv);
|
||||
else
|
||||
ret = mwifiex_process_sta_event(priv);
|
||||
|
||||
adapter->event_cause = 0;
|
||||
adapter->event_skb = NULL;
|
||||
|
@ -60,6 +60,9 @@
|
||||
#define MWIFIEX_SDIO_BLOCK_SIZE 256
|
||||
|
||||
#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0)
|
||||
#define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1)
|
||||
|
||||
#define MWIFIEX_BRIDGED_PKTS_THRESHOLD 1024
|
||||
|
||||
enum mwifiex_bss_type {
|
||||
MWIFIEX_BSS_TYPE_STA = 0,
|
||||
|
@ -65,10 +65,12 @@ enum KEY_TYPE_ID {
|
||||
KEY_TYPE_ID_TKIP,
|
||||
KEY_TYPE_ID_AES,
|
||||
KEY_TYPE_ID_WAPI,
|
||||
KEY_TYPE_ID_AES_CMAC,
|
||||
};
|
||||
#define KEY_MCAST BIT(0)
|
||||
#define KEY_UNICAST BIT(1)
|
||||
#define KEY_ENABLED BIT(2)
|
||||
#define KEY_IGTK BIT(10)
|
||||
|
||||
#define WAPI_KEY_LEN 50
|
||||
|
||||
@ -424,10 +426,10 @@ struct txpd {
|
||||
struct rxpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
u16 rx_pkt_length;
|
||||
u16 rx_pkt_offset;
|
||||
u16 rx_pkt_type;
|
||||
u16 seq_num;
|
||||
__le16 rx_pkt_length;
|
||||
__le16 rx_pkt_offset;
|
||||
__le16 rx_pkt_type;
|
||||
__le16 seq_num;
|
||||
u8 priority;
|
||||
u8 rx_rate;
|
||||
s8 snr;
|
||||
@ -439,6 +441,31 @@ struct rxpd {
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct uap_txpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
__le16 tx_pkt_length;
|
||||
__le16 tx_pkt_offset;
|
||||
__le16 tx_pkt_type;
|
||||
__le32 tx_control;
|
||||
u8 priority;
|
||||
u8 flags;
|
||||
u8 pkt_delay_2ms;
|
||||
u8 reserved1;
|
||||
__le32 reserved2;
|
||||
};
|
||||
|
||||
struct uap_rxpd {
|
||||
u8 bss_type;
|
||||
u8 bss_num;
|
||||
__le16 rx_pkt_length;
|
||||
__le16 rx_pkt_offset;
|
||||
__le16 rx_pkt_type;
|
||||
__le16 seq_num;
|
||||
u8 priority;
|
||||
u8 reserved1;
|
||||
};
|
||||
|
||||
enum mwifiex_chan_scan_mode_bitmasks {
|
||||
MWIFIEX_PASSIVE_SCAN = BIT(0),
|
||||
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
|
||||
@ -558,6 +585,13 @@ struct mwifiex_ie_type_key_param_set {
|
||||
u8 key[50];
|
||||
} __packed;
|
||||
|
||||
#define IGTK_PN_LEN 8
|
||||
|
||||
struct mwifiex_cmac_param {
|
||||
u8 ipn[IGTK_PN_LEN];
|
||||
u8 key[WLAN_KEY_LEN_AES_CMAC];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_802_11_key_material {
|
||||
__le16 action;
|
||||
struct mwifiex_ie_type_key_param_set key_param_set;
|
||||
|
@ -64,60 +64,72 @@ static void scan_delay_timer_fn(unsigned long data)
|
||||
struct cmd_ctrl_node *cmd_node, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
if (!mwifiex_wmm_lists_empty(adapter)) {
|
||||
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
|
||||
if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
|
||||
/*
|
||||
* Abort scan operation by cancelling all pending scan
|
||||
* commands
|
||||
*/
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
adapter->scan_delay_cnt = 0;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: scan aborted\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!atomic_read(&priv->adapter->is_tx_received)) {
|
||||
adapter->empty_tx_q_cnt++;
|
||||
if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
|
||||
/*
|
||||
* Abort scan operation by cancelling all pending scan
|
||||
* command
|
||||
* No Tx traffic for 200msec. Get scan command from
|
||||
* scan pending queue and put to cmd pending queue to
|
||||
* resume scan operation
|
||||
*/
|
||||
adapter->scan_delay_cnt = 0;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q,
|
||||
list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock,
|
||||
flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: scan aborted\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Tx data queue is still not empty, delay scan
|
||||
* operation further by 20msec.
|
||||
*/
|
||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||
adapter->scan_delay_cnt++;
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
|
||||
true);
|
||||
goto done;
|
||||
}
|
||||
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
|
||||
} else {
|
||||
/*
|
||||
* Tx data queue is empty. Get scan command from scan_pending_q
|
||||
* and put to cmd_pending_q to resume scan operation
|
||||
*/
|
||||
adapter->scan_delay_cnt = 0;
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
cmd_node = list_first_entry(&adapter->scan_pending_q,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
}
|
||||
|
||||
/* Delay scan operation further by 20msec */
|
||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||
adapter->scan_delay_cnt++;
|
||||
|
||||
done:
|
||||
if (atomic_read(&priv->adapter->is_tx_received))
|
||||
atomic_set(&priv->adapter->is_tx_received, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -196,6 +208,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
|
||||
priv->curr_bcn_size = 0;
|
||||
priv->wps_ie = NULL;
|
||||
priv->wps_ie_len = 0;
|
||||
priv->ap_11n_enabled = 0;
|
||||
|
||||
priv->scan_block = false;
|
||||
|
||||
@ -345,6 +358,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
|
||||
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
|
||||
adapter->arp_filter_size = 0;
|
||||
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
|
||||
adapter->empty_tx_q_cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -410,6 +424,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
|
||||
list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
|
||||
list_del(&priv->tx_ba_stream_tbl_ptr);
|
||||
list_del(&priv->rx_reorder_tbl_ptr);
|
||||
list_del(&priv->sta_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -472,6 +487,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
|
||||
spin_lock_init(&priv->rx_pkt_lock);
|
||||
spin_lock_init(&priv->wmm.ra_list_spinlock);
|
||||
spin_lock_init(&priv->curr_bcn_buf_lock);
|
||||
spin_lock_init(&priv->sta_list_spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,6 +520,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
|
||||
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
|
||||
INIT_LIST_HEAD(&priv->sta_list);
|
||||
|
||||
spin_lock_init(&priv->tx_ba_stream_tbl_lock);
|
||||
spin_lock_init(&priv->rx_reorder_tbl_lock);
|
||||
|
@ -213,7 +213,7 @@ struct mwifiex_debug_info {
|
||||
};
|
||||
|
||||
#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000
|
||||
#define WAPI_RXPN_LEN 16
|
||||
#define PN_LEN 16
|
||||
|
||||
struct mwifiex_ds_encrypt_key {
|
||||
u32 key_disable;
|
||||
@ -222,7 +222,8 @@ struct mwifiex_ds_encrypt_key {
|
||||
u8 key_material[WLAN_MAX_KEY_LEN];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u32 is_wapi_key;
|
||||
u8 wapi_rxpn[WAPI_RXPN_LEN];
|
||||
u8 pn[PN_LEN]; /* packet number */
|
||||
u8 is_igtk_key;
|
||||
};
|
||||
|
||||
struct mwifiex_power_cfg {
|
||||
|
@ -520,6 +520,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
mwifiex_wmm_add_buf_txqueue(priv, skb);
|
||||
atomic_inc(&priv->adapter->tx_pending);
|
||||
|
||||
if (priv->adapter->scan_delay_cnt)
|
||||
atomic_set(&priv->adapter->is_tx_received, true);
|
||||
|
||||
if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
|
||||
mwifiex_set_trans_start(dev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
|
||||
|
@ -88,6 +88,7 @@ enum {
|
||||
#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
|
||||
|
||||
#define MWIFIEX_MAX_SCAN_DELAY_CNT 50
|
||||
#define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10
|
||||
#define MWIFIEX_SCAN_DELAY_MSEC 20
|
||||
|
||||
#define RSN_GTK_OUI_OFFSET 2
|
||||
@ -199,6 +200,9 @@ struct mwifiex_ra_list_tbl {
|
||||
u8 ra[ETH_ALEN];
|
||||
u32 total_pkts_size;
|
||||
u32 is_11n_enabled;
|
||||
u16 max_amsdu;
|
||||
u16 pkt_count;
|
||||
u8 ba_packet_thr;
|
||||
};
|
||||
|
||||
struct mwifiex_tid_tbl {
|
||||
@ -431,6 +435,9 @@ struct mwifiex_private {
|
||||
u8 wmm_enabled;
|
||||
u8 wmm_qosinfo;
|
||||
struct mwifiex_wmm_desc wmm;
|
||||
struct list_head sta_list;
|
||||
/* spin lock for associated station list */
|
||||
spinlock_t sta_list_spinlock;
|
||||
struct list_head tx_ba_stream_tbl_ptr;
|
||||
/* spin lock for tx_ba_stream_tbl_ptr queue */
|
||||
spinlock_t tx_ba_stream_tbl_lock;
|
||||
@ -486,6 +493,7 @@ struct mwifiex_private {
|
||||
u16 assocresp_idx;
|
||||
u16 rsn_idx;
|
||||
struct timer_list scan_delay_timer;
|
||||
u8 ap_11n_enabled;
|
||||
};
|
||||
|
||||
enum mwifiex_ba_status {
|
||||
@ -550,6 +558,19 @@ struct mwifiex_bss_priv {
|
||||
u64 fw_tsf;
|
||||
};
|
||||
|
||||
/* This is AP specific structure which stores information
|
||||
* about associated STA
|
||||
*/
|
||||
struct mwifiex_sta_node {
|
||||
struct list_head list;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 is_wmm_enabled;
|
||||
u8 is_11n_enabled;
|
||||
u8 ampdu_sta[MAX_NUM_TID];
|
||||
u16 rx_seq[MAX_NUM_TID];
|
||||
u16 max_amsdu;
|
||||
};
|
||||
|
||||
struct mwifiex_if_ops {
|
||||
int (*init_if) (struct mwifiex_adapter *);
|
||||
void (*cleanup_if) (struct mwifiex_adapter *);
|
||||
@ -690,6 +711,9 @@ struct mwifiex_adapter {
|
||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||
u16 max_mgmt_ie_index;
|
||||
u8 scan_delay_cnt;
|
||||
u8 empty_tx_q_cnt;
|
||||
atomic_t is_tx_received;
|
||||
atomic_t pending_bridged_pkts;
|
||||
};
|
||||
|
||||
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
|
||||
@ -780,7 +804,15 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
|
||||
struct host_cmd_ds_command *resp);
|
||||
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_process_sta_event(struct mwifiex_private *);
|
||||
int mwifiex_process_uap_event(struct mwifiex_private *);
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
|
||||
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
|
||||
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
|
||||
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
|
||||
@ -949,9 +981,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
||||
const struct mwifiex_user_scan_cfg *user_scan_in);
|
||||
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
|
||||
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index, const u8 *mac_addr,
|
||||
int disable);
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
||||
const u8 *key, int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable);
|
||||
|
||||
int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
|
||||
|
||||
|
@ -989,6 +989,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
||||
*max_chan_per_scan = 2;
|
||||
else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD)
|
||||
*max_chan_per_scan = 3;
|
||||
else
|
||||
*max_chan_per_scan = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1433,9 +1435,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
|
||||
if (ret)
|
||||
dev_err(priv->adapter->dev, "cannot find ssid "
|
||||
"%s\n", bss_desc->ssid.ssid);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +610,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
memcpy(&key_material->key_param_set.key[2],
|
||||
enc_key->key_material, enc_key->key_len);
|
||||
memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
|
||||
enc_key->wapi_rxpn, WAPI_RXPN_LEN);
|
||||
enc_key->pn, PN_LEN);
|
||||
key_material->key_param_set.length =
|
||||
cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN);
|
||||
|
||||
@ -621,23 +621,38 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
return ret;
|
||||
}
|
||||
if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
if (enc_key->is_igtk_key) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: CMAC_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(KEY_ENABLED);
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(!KEY_ENABLED);
|
||||
|
||||
if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_IGTK);
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
cpu_to_le16(KEY_TYPE_ID_AES);
|
||||
if (cmd_oid == KEY_INFO_ENABLED)
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(KEY_ENABLED);
|
||||
else
|
||||
key_material->key_param_set.key_info =
|
||||
cpu_to_le16(!KEY_ENABLED);
|
||||
|
||||
if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
|
||||
/* AES pairwise key: unicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_UNICAST);
|
||||
else /* AES group key: multicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
else /* AES group key: multicast */
|
||||
key_material->key_param_set.key_info |=
|
||||
cpu_to_le16(KEY_MCAST);
|
||||
}
|
||||
} else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
|
||||
dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
|
||||
key_material->key_param_set.key_type_id =
|
||||
@ -668,6 +683,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
|
||||
key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
|
||||
+ sizeof(struct mwifiex_ie_types_header);
|
||||
|
||||
if (le16_to_cpu(key_material->key_param_set.key_type_id) ==
|
||||
KEY_TYPE_ID_AES_CMAC) {
|
||||
struct mwifiex_cmac_param *param =
|
||||
(void *)key_material->key_param_set.key;
|
||||
|
||||
memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN);
|
||||
memcpy(param->key, enc_key->key_material,
|
||||
WLAN_KEY_LEN_AES_CMAC);
|
||||
|
||||
key_param_len = sizeof(struct mwifiex_cmac_param);
|
||||
key_material->key_param_set.key_len =
|
||||
cpu_to_le16(key_param_len);
|
||||
key_param_len += KEYPARAMSET_FIXED_LEN;
|
||||
key_material->key_param_set.length =
|
||||
cpu_to_le16(key_param_len);
|
||||
key_param_len += sizeof(struct mwifiex_ie_types_header);
|
||||
}
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
|
||||
+ key_param_len);
|
||||
|
||||
|
@ -184,10 +184,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
|
||||
int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int len, ret = 0;
|
||||
int ret = 0;
|
||||
u32 eventcause = adapter->event_cause;
|
||||
struct station_info sinfo;
|
||||
struct mwifiex_assoc_event *event;
|
||||
u16 ctrl;
|
||||
|
||||
switch (eventcause) {
|
||||
case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
|
||||
@ -279,10 +278,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
|
||||
case EVENT_MIC_ERR_UNICAST:
|
||||
dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n");
|
||||
cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
|
||||
NL80211_KEYTYPE_PAIRWISE,
|
||||
-1, NULL, GFP_KERNEL);
|
||||
break;
|
||||
|
||||
case EVENT_MIC_ERR_MULTICAST:
|
||||
dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n");
|
||||
cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
|
||||
NL80211_KEYTYPE_GROUP,
|
||||
-1, NULL, GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_MIB_CHANGED:
|
||||
case EVENT_INIT_DONE:
|
||||
@ -384,11 +389,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
adapter->event_body);
|
||||
break;
|
||||
case EVENT_AMSDU_AGGR_CTRL:
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n",
|
||||
*(u16 *) adapter->event_body);
|
||||
ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
|
||||
|
||||
adapter->tx_buf_size =
|
||||
min(adapter->curr_tx_buf_size,
|
||||
le16_to_cpu(*(__le16 *) adapter->event_body));
|
||||
min_t(u16, adapter->curr_tx_buf_size, ctrl);
|
||||
dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
|
||||
adapter->tx_buf_size);
|
||||
break;
|
||||
@ -405,51 +410,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
||||
dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
|
||||
break;
|
||||
|
||||
case EVENT_UAP_STA_ASSOC:
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
event = (struct mwifiex_assoc_event *)
|
||||
(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
|
||||
len = -1;
|
||||
|
||||
if (ieee80211_is_assoc_req(event->frame_control))
|
||||
len = 0;
|
||||
else if (ieee80211_is_reassoc_req(event->frame_control))
|
||||
/* There will be ETH_ALEN bytes of
|
||||
* current_ap_addr before the re-assoc ies.
|
||||
*/
|
||||
len = ETH_ALEN;
|
||||
|
||||
if (len != -1) {
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.assoc_req_ies = &event->data[len];
|
||||
len = (u8 *)sinfo.assoc_req_ies -
|
||||
(u8 *)&event->frame_control;
|
||||
sinfo.assoc_req_ies_len =
|
||||
le16_to_cpu(event->len) - (u16)len;
|
||||
}
|
||||
}
|
||||
cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_UAP_STA_DEAUTH:
|
||||
cfg80211_del_sta(priv->netdev, adapter->event_body +
|
||||
MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
|
||||
break;
|
||||
case EVENT_UAP_BSS_IDLE:
|
||||
priv->media_connected = false;
|
||||
break;
|
||||
case EVENT_UAP_BSS_ACTIVE:
|
||||
priv->media_connected = true;
|
||||
break;
|
||||
case EVENT_UAP_BSS_START:
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN);
|
||||
break;
|
||||
case EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
/* For future development */
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
|
||||
eventcause);
|
||||
|
@ -942,20 +942,26 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
|
||||
* This function allocates the IOCTL request buffer, fills it
|
||||
* with requisite parameters and calls the IOCTL handler.
|
||||
*/
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable)
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
||||
const u8 *key, int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable)
|
||||
{
|
||||
struct mwifiex_ds_encrypt_key encrypt_key;
|
||||
|
||||
memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
|
||||
encrypt_key.key_len = key_len;
|
||||
|
||||
if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
||||
encrypt_key.is_igtk_key = true;
|
||||
|
||||
if (!disable) {
|
||||
encrypt_key.key_index = key_index;
|
||||
if (key_len)
|
||||
memcpy(encrypt_key.key_material, key, key_len);
|
||||
if (mac_addr)
|
||||
memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
|
||||
if (kp && kp->seq && kp->seq_len)
|
||||
memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
|
||||
} else {
|
||||
encrypt_key.key_disable = true;
|
||||
if (mac_addr)
|
||||
|
@ -54,8 +54,8 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
||||
|
||||
local_rx_pd = (struct rxpd *) (skb->data);
|
||||
|
||||
rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
|
||||
local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_hdr = (void *)local_rx_pd +
|
||||
le16_to_cpu(local_rx_pd->rx_pkt_offset);
|
||||
|
||||
if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
|
||||
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
|
||||
@ -125,7 +125,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u8 ta[ETH_ALEN];
|
||||
u16 rx_pkt_type;
|
||||
u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
|
||||
struct mwifiex_private *priv =
|
||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
||||
rx_info->bss_type);
|
||||
@ -134,16 +134,17 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
return -1;
|
||||
|
||||
local_rx_pd = (struct rxpd *) (skb->data);
|
||||
rx_pkt_type = local_rx_pd->rx_pkt_type;
|
||||
rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
|
||||
rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
|
||||
seq_num = le16_to_cpu(local_rx_pd->seq_num);
|
||||
|
||||
rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
|
||||
local_rx_pd->rx_pkt_offset);
|
||||
rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
|
||||
|
||||
if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) >
|
||||
(u16) skb->len) {
|
||||
dev_err(adapter->dev, "wrong rx packet: len=%d,"
|
||||
" rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len,
|
||||
local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length);
|
||||
if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
|
||||
dev_err(adapter->dev,
|
||||
"wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
|
||||
skb->len, rx_pkt_offset, rx_pkt_length);
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
if (adapter->if_ops.data_complete)
|
||||
@ -154,14 +155,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
|
||||
if (rx_pkt_type == PKT_TYPE_AMSDU) {
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
|
||||
skb_pull(skb, local_rx_pd->rx_pkt_offset);
|
||||
skb_trim(skb, local_rx_pd->rx_pkt_length);
|
||||
skb_pull(skb, rx_pkt_offset);
|
||||
skb_trim(skb, rx_pkt_length);
|
||||
|
||||
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
||||
priv->wdev->iftype, 0, false);
|
||||
@ -189,17 +190,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||
} else {
|
||||
if (rx_pkt_type != PKT_TYPE_BAR)
|
||||
priv->rx_seq[local_rx_pd->priority] =
|
||||
local_rx_pd->seq_num;
|
||||
priv->rx_seq[local_rx_pd->priority] = seq_num;
|
||||
memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
/* Reorder and send to OS */
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
|
||||
local_rx_pd->priority, ta,
|
||||
(u8) local_rx_pd->rx_pkt_type,
|
||||
skb);
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
|
||||
ta, (u8) rx_pkt_type, skb);
|
||||
|
||||
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
|
||||
if (adapter->if_ops.data_complete)
|
||||
|
@ -51,6 +51,9 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
|
||||
rx_info->bss_num = priv->bss_num;
|
||||
rx_info->bss_type = priv->bss_type;
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
return mwifiex_process_uap_rx_packet(adapter, skb);
|
||||
|
||||
return mwifiex_process_sta_rx_packet(adapter, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
|
||||
@ -157,6 +160,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
|
||||
priv->stats.tx_errors++;
|
||||
}
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
|
||||
atomic_dec_return(&adapter->pending_bridged_pkts);
|
||||
if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
|
||||
goto done;
|
||||
|
||||
|
@ -167,6 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
|
||||
if (ht_ie) {
|
||||
memcpy(&bss_cfg->ht_cap, ht_ie + 2,
|
||||
sizeof(struct ieee80211_ht_cap));
|
||||
priv->ap_11n_enabled = 1;
|
||||
} else {
|
||||
memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
|
||||
bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
|
||||
|
290
drivers/net/wireless/mwifiex/uap_event.c
Normal file
290
drivers/net/wireless/mwifiex/uap_event.c
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Marvell Wireless LAN device driver: AP event handling
|
||||
*
|
||||
* Copyright (C) 2012, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*/
|
||||
|
||||
#include "decl.h"
|
||||
#include "main.h"
|
||||
#include "11n.h"
|
||||
|
||||
/*
|
||||
* This function will return the pointer to station entry in station list
|
||||
* table which matches specified mac address.
|
||||
* This function should be called after acquiring RA list spinlock.
|
||||
* NULL is returned if station entry is not found in associated STA list.
|
||||
*/
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(node, &priv->sta_list, list) {
|
||||
if (!memcmp(node->mac_addr, mac, ETH_ALEN))
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will add a sta_node entry to associated station list
|
||||
* table with the given mac address.
|
||||
* If entry exist already, existing entry is returned.
|
||||
* If received mac address is NULL, NULL is returned.
|
||||
*/
|
||||
static struct mwifiex_sta_node *
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node)
|
||||
goto done;
|
||||
|
||||
node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_ATOMIC);
|
||||
if (!node)
|
||||
goto done;
|
||||
|
||||
memcpy(node->mac_addr, mac, ETH_ALEN);
|
||||
list_add_tail(&node->list, &priv->sta_list);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will search for HT IE in association request IEs
|
||||
* and set station HT parameters accordingly.
|
||||
*/
|
||||
static void
|
||||
mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
|
||||
int ies_len, struct mwifiex_sta_node *node)
|
||||
{
|
||||
const struct ieee80211_ht_cap *ht_cap;
|
||||
|
||||
if (!ies)
|
||||
return;
|
||||
|
||||
ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
|
||||
if (ht_cap) {
|
||||
node->is_11n_enabled = 1;
|
||||
node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
|
||||
IEEE80211_HT_CAP_MAX_AMSDU ?
|
||||
MWIFIEX_TX_DATA_BUF_SIZE_8K :
|
||||
MWIFIEX_TX_DATA_BUF_SIZE_4K;
|
||||
} else {
|
||||
node->is_11n_enabled = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will delete a station entry from station list
|
||||
*/
|
||||
static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
|
||||
node = mwifiex_get_sta_entry(priv, mac);
|
||||
if (node) {
|
||||
list_for_each_entry_safe(node, tmp, &priv->sta_list,
|
||||
list) {
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will delete all stations from associated station list.
|
||||
*/
|
||||
static void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_sta_node *node, *tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->sta_list);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles AP interface specific events generated by firmware.
|
||||
*
|
||||
* Event specific routines are called by this function based
|
||||
* upon the generated event cause.
|
||||
*
|
||||
*
|
||||
* Events supported for AP -
|
||||
* - EVENT_UAP_STA_ASSOC
|
||||
* - EVENT_UAP_STA_DEAUTH
|
||||
* - EVENT_UAP_BSS_ACTIVE
|
||||
* - EVENT_UAP_BSS_START
|
||||
* - EVENT_UAP_BSS_IDLE
|
||||
* - EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
*/
|
||||
int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int len, i;
|
||||
u32 eventcause = adapter->event_cause;
|
||||
struct station_info sinfo;
|
||||
struct mwifiex_assoc_event *event;
|
||||
struct mwifiex_sta_node *node;
|
||||
u8 *deauth_mac;
|
||||
struct host_cmd_ds_11n_batimeout *ba_timeout;
|
||||
u16 ctrl;
|
||||
|
||||
switch (eventcause) {
|
||||
case EVENT_UAP_STA_ASSOC:
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
event = (struct mwifiex_assoc_event *)
|
||||
(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
|
||||
if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
|
||||
len = -1;
|
||||
|
||||
if (ieee80211_is_assoc_req(event->frame_control))
|
||||
len = 0;
|
||||
else if (ieee80211_is_reassoc_req(event->frame_control))
|
||||
/* There will be ETH_ALEN bytes of
|
||||
* current_ap_addr before the re-assoc ies.
|
||||
*/
|
||||
len = ETH_ALEN;
|
||||
|
||||
if (len != -1) {
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.assoc_req_ies = &event->data[len];
|
||||
len = (u8 *)sinfo.assoc_req_ies -
|
||||
(u8 *)&event->frame_control;
|
||||
sinfo.assoc_req_ies_len =
|
||||
le16_to_cpu(event->len) - (u16)len;
|
||||
}
|
||||
}
|
||||
cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
|
||||
GFP_KERNEL);
|
||||
|
||||
node = mwifiex_add_sta_entry(priv, event->sta_addr);
|
||||
if (!node) {
|
||||
dev_warn(adapter->dev,
|
||||
"could not create station entry!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!priv->ap_11n_enabled)
|
||||
break;
|
||||
|
||||
mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
|
||||
sinfo.assoc_req_ies_len, node);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; i++) {
|
||||
if (node->is_11n_enabled)
|
||||
node->ampdu_sta[i] =
|
||||
priv->aggr_prio_tbl[i].ampdu_user;
|
||||
else
|
||||
node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
|
||||
}
|
||||
memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
|
||||
break;
|
||||
case EVENT_UAP_STA_DEAUTH:
|
||||
deauth_mac = adapter->event_body +
|
||||
MWIFIEX_UAP_EVENT_EXTRA_HEADER;
|
||||
cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
|
||||
|
||||
if (priv->ap_11n_enabled) {
|
||||
mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
|
||||
mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
|
||||
}
|
||||
mwifiex_del_sta_entry(priv, deauth_mac);
|
||||
break;
|
||||
case EVENT_UAP_BSS_IDLE:
|
||||
priv->media_connected = false;
|
||||
mwifiex_clean_txrx(priv);
|
||||
mwifiex_del_all_sta_list(priv);
|
||||
break;
|
||||
case EVENT_UAP_BSS_ACTIVE:
|
||||
priv->media_connected = true;
|
||||
break;
|
||||
case EVENT_UAP_BSS_START:
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
|
||||
ETH_ALEN);
|
||||
break;
|
||||
case EVENT_UAP_MIC_COUNTERMEASURES:
|
||||
/* For future development */
|
||||
dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
|
||||
break;
|
||||
case EVENT_AMSDU_AGGR_CTRL:
|
||||
ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
|
||||
dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
|
||||
|
||||
if (priv->media_connected) {
|
||||
adapter->tx_buf_size =
|
||||
min_t(u16, adapter->curr_tx_buf_size, ctrl);
|
||||
dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
|
||||
adapter->tx_buf_size);
|
||||
}
|
||||
break;
|
||||
case EVENT_ADDBA:
|
||||
dev_dbg(adapter->dev, "event: ADDBA Request\n");
|
||||
if (priv->media_connected)
|
||||
mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
|
||||
HostCmd_ACT_GEN_SET, 0,
|
||||
adapter->event_body);
|
||||
break;
|
||||
case EVENT_DELBA:
|
||||
dev_dbg(adapter->dev, "event: DELBA Request\n");
|
||||
if (priv->media_connected)
|
||||
mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
|
||||
break;
|
||||
case EVENT_BA_STREAM_TIEMOUT:
|
||||
dev_dbg(adapter->dev, "event: BA Stream timeout\n");
|
||||
if (priv->media_connected) {
|
||||
ba_timeout = (void *)adapter->event_body;
|
||||
mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
|
||||
eventcause);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
255
drivers/net/wireless/mwifiex/uap_txrx.c
Normal file
255
drivers/net/wireless/mwifiex/uap_txrx.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Marvell Wireless LAN device driver: AP TX and RX data handling
|
||||
*
|
||||
* Copyright (C) 2012, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*/
|
||||
|
||||
#include "decl.h"
|
||||
#include "ioctl.h"
|
||||
#include "main.h"
|
||||
#include "wmm.h"
|
||||
#include "11n_aggr.h"
|
||||
#include "11n_rxreorder.h"
|
||||
|
||||
static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
struct sk_buff *new_skb;
|
||||
struct mwifiex_txinfo *tx_info;
|
||||
int hdr_chop;
|
||||
struct timeval tv;
|
||||
u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
if ((atomic_read(&adapter->pending_bridged_pkts) >=
|
||||
MWIFIEX_BRIDGED_PKTS_THRESHOLD)) {
|
||||
dev_err(priv->adapter->dev,
|
||||
"Tx: Bridge packet limit reached. Drop packet!\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
|
||||
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)))
|
||||
/* Chop off the rxpd + the excess memory from
|
||||
* 802.2/llc/snap header that was removed.
|
||||
*/
|
||||
hdr_chop = (u8 *)eth_hdr - (u8 *)uap_rx_pd;
|
||||
else
|
||||
/* Chop off the rxpd */
|
||||
hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
|
||||
|
||||
/* Chop off the leading header bytes so the it points
|
||||
* to the start of either the reconstructed EthII frame
|
||||
* or the 802.2/llc/snap frame.
|
||||
*/
|
||||
skb_pull(skb, hdr_chop);
|
||||
|
||||
if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"data: Tx: insufficient skb headroom %d\n",
|
||||
skb_headroom(skb));
|
||||
/* Insufficient skb headroom - allocate a new skb */
|
||||
new_skb =
|
||||
skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
|
||||
if (unlikely(!new_skb)) {
|
||||
dev_err(priv->adapter->dev,
|
||||
"Tx: cannot allocate new_skb\n");
|
||||
kfree_skb(skb);
|
||||
priv->stats.tx_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
skb = new_skb;
|
||||
dev_dbg(priv->adapter->dev, "info: new skb headroom %d\n",
|
||||
skb_headroom(skb));
|
||||
}
|
||||
|
||||
tx_info = MWIFIEX_SKB_TXCB(skb);
|
||||
tx_info->bss_num = priv->bss_num;
|
||||
tx_info->bss_type = priv->bss_type;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
skb->tstamp = timeval_to_ktime(tv);
|
||||
mwifiex_wmm_add_buf_txqueue(priv, skb);
|
||||
atomic_inc(&adapter->tx_pending);
|
||||
atomic_inc(&adapter->pending_bridged_pkts);
|
||||
|
||||
if ((atomic_read(&adapter->tx_pending) >= MAX_TX_PENDING)) {
|
||||
mwifiex_set_trans_start(priv->netdev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function contains logic for AP packet forwarding.
|
||||
*
|
||||
* If a packet is multicast/broadcast, it is sent to kernel/upper layer
|
||||
* as well as queued back to AP TX queue so that it can be sent to other
|
||||
* associated stations.
|
||||
* If a packet is unicast and RA is present in associated station list,
|
||||
* it is again requeued into AP TX queue.
|
||||
* If a packet is unicast and RA is not in associated station list,
|
||||
* packet is forwarded to kernel to handle routing logic.
|
||||
*/
|
||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u8 ra[ETH_ALEN];
|
||||
struct sk_buff *skb_uap;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
/* don't do packet forwarding in disconnected state */
|
||||
if (!priv->media_connected) {
|
||||
dev_err(adapter->dev, "drop packet in disconnected state.\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
|
||||
|
||||
if (is_multicast_ether_addr(ra)) {
|
||||
skb_uap = skb_copy(skb, GFP_ATOMIC);
|
||||
mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
|
||||
} else {
|
||||
if (mwifiex_get_sta_entry(priv, ra)) {
|
||||
/* Requeue Intra-BSS packet */
|
||||
mwifiex_uap_queue_bridged_pkt(priv, skb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward unicat/Inter-BSS packets to kernel. */
|
||||
return mwifiex_process_rx_packet(adapter, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function processes the packet received on AP interface.
|
||||
*
|
||||
* The function looks into the RxPD and performs sanity tests on the
|
||||
* received buffer to ensure its a valid packet before processing it
|
||||
* further. If the packet is determined to be aggregated, it is
|
||||
* de-aggregated accordingly. Then skb is passed to AP packet forwarding logic.
|
||||
*
|
||||
* The completion callback is called after processing is complete.
|
||||
*/
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int ret;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u16 rx_pkt_type;
|
||||
u8 ta[ETH_ALEN], pkt_type;
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
struct mwifiex_private *priv =
|
||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
||||
rx_info->bss_type);
|
||||
|
||||
if (!priv)
|
||||
return -1;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
||||
if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
|
||||
dev_err(adapter->dev,
|
||||
"wrong rx packet: len=%d, offset=%d, length=%d\n",
|
||||
skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
|
||||
le16_to_cpu(uap_rx_pd->rx_pkt_length));
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
if (adapter->if_ops.data_complete)
|
||||
adapter->if_ops.data_complete(adapter, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
|
||||
skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length));
|
||||
|
||||
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
||||
priv->wdev->iftype, 0, false);
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
rx_skb = __skb_dequeue(&list);
|
||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
||||
if (ret)
|
||||
dev_err(adapter->dev,
|
||||
"AP:Rx A-MSDU failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||
|
||||
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
||||
node = mwifiex_get_sta_entry(priv, ta);
|
||||
if (node)
|
||||
node->rx_seq[uap_rx_pd->priority] =
|
||||
le16_to_cpu(uap_rx_pd->seq_num);
|
||||
}
|
||||
|
||||
if (!priv->ap_11n_enabled ||
|
||||
(!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
|
||||
(le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
|
||||
ret = mwifiex_handle_uap_rx_forward(priv, skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reorder and send to kernel */
|
||||
pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||
ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
|
||||
uap_rx_pd->priority, ta, pkt_type,
|
||||
skb);
|
||||
|
||||
if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
|
||||
if (adapter->if_ops.data_complete)
|
||||
adapter->if_ops.data_complete(adapter, skb);
|
||||
else
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
priv->stats.rx_dropped++;
|
||||
|
||||
return ret;
|
||||
}
|
@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
|
||||
return ra_list;
|
||||
}
|
||||
|
||||
/* This function returns random no between 16 and 32 to be used as threshold
|
||||
* for no of packets after which BA setup is initiated.
|
||||
*/
|
||||
static u8 mwifiex_get_random_ba_threshold(void)
|
||||
{
|
||||
u32 sec, usec;
|
||||
struct timeval ba_tstamp;
|
||||
u8 ba_threshold;
|
||||
|
||||
/* setup ba_packet_threshold here random number between
|
||||
* [BA_SETUP_PACKET_OFFSET,
|
||||
* BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
|
||||
*/
|
||||
|
||||
do_gettimeofday(&ba_tstamp);
|
||||
sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
|
||||
usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
|
||||
ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
|
||||
+ BA_SETUP_PACKET_OFFSET;
|
||||
|
||||
return ba_threshold;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function allocates and adds a RA list for all TIDs
|
||||
* with the given RA.
|
||||
@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
|
||||
int i;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||
node = mwifiex_get_sta_entry(priv, ra);
|
||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||
|
||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
|
||||
@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
|
||||
if (!ra_list)
|
||||
break;
|
||||
|
||||
if (!mwifiex_queuing_ra_based(priv))
|
||||
ra_list->is_11n_enabled = 0;
|
||||
if (!mwifiex_queuing_ra_based(priv)) {
|
||||
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
|
||||
else
|
||||
ra_list->is_11n_enabled = false;
|
||||
} else {
|
||||
ra_list->is_11n_enabled =
|
||||
mwifiex_is_sta_11n_enabled(priv, node);
|
||||
if (ra_list->is_11n_enabled)
|
||||
ra_list->max_amsdu = node->max_amsdu;
|
||||
}
|
||||
|
||||
dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
|
||||
ra_list, ra_list->is_11n_enabled);
|
||||
|
||||
if (ra_list->is_11n_enabled) {
|
||||
ra_list->pkt_count = 0;
|
||||
ra_list->ba_packet_thr =
|
||||
mwifiex_get_random_ba_threshold();
|
||||
}
|
||||
list_add_tail(&ra_list->list,
|
||||
&priv->wmm.tid_tbl_ptr[i].ra_list);
|
||||
|
||||
@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
||||
skb_queue_tail(&ra_list->skb_head, skb);
|
||||
|
||||
ra_list->total_pkts_size += skb->len;
|
||||
ra_list->pkt_count++;
|
||||
|
||||
atomic_inc(&priv->wmm.tx_pkts_queued);
|
||||
|
||||
@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
|
||||
{
|
||||
int count = 0, total_size = 0;
|
||||
struct sk_buff *skb, *tmp;
|
||||
int max_amsdu_size;
|
||||
|
||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
|
||||
ptr->is_11n_enabled)
|
||||
max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
|
||||
else
|
||||
max_amsdu_size = max_buf_size;
|
||||
|
||||
skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
|
||||
total_size += skb->len;
|
||||
if (total_size >= max_buf_size)
|
||||
if (total_size >= max_amsdu_size)
|
||||
break;
|
||||
if (++count >= MIN_NUM_AMSDU)
|
||||
return true;
|
||||
@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
|
||||
skb_queue_tail(&ptr->skb_head, skb);
|
||||
|
||||
ptr->total_pkts_size += skb->len;
|
||||
ptr->pkt_count++;
|
||||
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
|
||||
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
|
||||
ra_list_flags);
|
||||
@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
|
||||
/* ra_list_spinlock has been freed in
|
||||
mwifiex_send_single_packet() */
|
||||
} else {
|
||||
if (mwifiex_is_ampdu_allowed(priv, tid)) {
|
||||
if (mwifiex_is_ampdu_allowed(priv, tid) &&
|
||||
ptr->pkt_count > ptr->ba_packet_thr) {
|
||||
if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
|
||||
mwifiex_create_ba_tbl(priv, ptr->ra, tid,
|
||||
BA_SETUP_INPROGRESS);
|
||||
|
@ -76,6 +76,7 @@ struct p54_channel_entry {
|
||||
u16 freq;
|
||||
u16 data;
|
||||
int index;
|
||||
int max_power;
|
||||
enum ieee80211_band band;
|
||||
};
|
||||
|
||||
@ -173,6 +174,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
|
||||
for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
|
||||
(i < list->entries); i++) {
|
||||
struct p54_channel_entry *chan = &list->channels[i];
|
||||
struct ieee80211_channel *dest = &tmp->channels[j];
|
||||
|
||||
if (chan->band != band)
|
||||
continue;
|
||||
@ -190,14 +192,15 @@ static int p54_generate_band(struct ieee80211_hw *dev,
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp->channels[j].band = chan->band;
|
||||
tmp->channels[j].center_freq = chan->freq;
|
||||
dest->band = chan->band;
|
||||
dest->center_freq = chan->freq;
|
||||
dest->max_power = chan->max_power;
|
||||
priv->survey[*chan_num].channel = &tmp->channels[j];
|
||||
priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
tmp->channels[j].hw_value = (*chan_num);
|
||||
dest->hw_value = (*chan_num);
|
||||
j++;
|
||||
(*chan_num)++;
|
||||
}
|
||||
@ -229,10 +232,11 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void p54_update_channel_param(struct p54_channel_list *list,
|
||||
u16 freq, u16 data)
|
||||
static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list,
|
||||
u16 freq, u16 data)
|
||||
{
|
||||
int band, i;
|
||||
int i;
|
||||
struct p54_channel_entry *entry = NULL;
|
||||
|
||||
/*
|
||||
* usually all lists in the eeprom are mostly sorted.
|
||||
@ -241,30 +245,78 @@ static void p54_update_channel_param(struct p54_channel_list *list,
|
||||
*/
|
||||
for (i = list->entries; i >= 0; i--) {
|
||||
if (freq == list->channels[i].freq) {
|
||||
list->channels[i].data |= data;
|
||||
entry = &list->channels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i < 0) && (list->entries < list->max_entries)) {
|
||||
/* entry does not exist yet. Initialize a new one. */
|
||||
band = p54_get_band_from_freq(freq);
|
||||
int band = p54_get_band_from_freq(freq);
|
||||
|
||||
/*
|
||||
* filter out frequencies which don't belong into
|
||||
* any supported band.
|
||||
*/
|
||||
if (band < 0)
|
||||
return ;
|
||||
if (band >= 0) {
|
||||
i = list->entries++;
|
||||
list->band_channel_num[band]++;
|
||||
|
||||
i = list->entries++;
|
||||
list->band_channel_num[band]++;
|
||||
entry = &list->channels[i];
|
||||
entry->freq = freq;
|
||||
entry->band = band;
|
||||
entry->index = ieee80211_frequency_to_channel(freq);
|
||||
entry->max_power = 0;
|
||||
entry->data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
list->channels[i].freq = freq;
|
||||
list->channels[i].data = data;
|
||||
list->channels[i].band = band;
|
||||
list->channels[i].index = ieee80211_frequency_to_channel(freq);
|
||||
/* TODO: parse output_limit and fill max_power */
|
||||
if (entry)
|
||||
entry->data |= data;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int p54_get_maxpower(struct p54_common *priv, void *data)
|
||||
{
|
||||
switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) {
|
||||
case PDR_SYNTH_FRONTEND_LONGBOW: {
|
||||
struct pda_channel_output_limit_longbow *pda = data;
|
||||
int j;
|
||||
u16 rawpower = 0;
|
||||
pda = data;
|
||||
for (j = 0; j < ARRAY_SIZE(pda->point); j++) {
|
||||
struct pda_channel_output_limit_point_longbow *point =
|
||||
&pda->point[j];
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_qpsk));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_bpsk));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_16qam));
|
||||
rawpower = max_t(u16,
|
||||
rawpower, le16_to_cpu(point->val_64qam));
|
||||
}
|
||||
/* longbow seems to use 1/16 dBm units */
|
||||
return rawpower / 16;
|
||||
}
|
||||
|
||||
case PDR_SYNTH_FRONTEND_DUETTE3:
|
||||
case PDR_SYNTH_FRONTEND_DUETTE2:
|
||||
case PDR_SYNTH_FRONTEND_FRISBEE:
|
||||
case PDR_SYNTH_FRONTEND_XBOW: {
|
||||
struct pda_channel_output_limit *pda = data;
|
||||
u8 rawpower = 0;
|
||||
rawpower = max(rawpower, pda->val_qpsk);
|
||||
rawpower = max(rawpower, pda->val_bpsk);
|
||||
rawpower = max(rawpower, pda->val_16qam);
|
||||
rawpower = max(rawpower, pda->val_64qam);
|
||||
/* raw values are in 1/4 dBm units */
|
||||
return rawpower / 4;
|
||||
}
|
||||
|
||||
default:
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,12 +367,19 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
if (i < priv->output_limit->entries) {
|
||||
freq = le16_to_cpup((__le16 *) (i *
|
||||
priv->output_limit->entry_size +
|
||||
priv->output_limit->offset +
|
||||
priv->output_limit->data));
|
||||
struct p54_channel_entry *tmp;
|
||||
|
||||
p54_update_channel_param(list, freq, CHAN_HAS_LIMIT);
|
||||
void *data = (void *) ((unsigned long) i *
|
||||
priv->output_limit->entry_size +
|
||||
priv->output_limit->offset +
|
||||
priv->output_limit->data);
|
||||
|
||||
freq = le16_to_cpup((__le16 *) data);
|
||||
tmp = p54_update_channel_param(list, freq,
|
||||
CHAN_HAS_LIMIT);
|
||||
if (tmp) {
|
||||
tmp->max_power = p54_get_maxpower(priv, data);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < priv->curve_data->entries) {
|
||||
@ -834,11 +893,12 @@ good_eeprom:
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
|
||||
|
||||
err = p54_generate_channel_lists(dev);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
|
||||
if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
|
||||
p54_init_xbow_synth(priv);
|
||||
if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
|
||||
|
@ -57,6 +57,18 @@ struct pda_channel_output_limit {
|
||||
u8 rate_set_size;
|
||||
} __packed;
|
||||
|
||||
struct pda_channel_output_limit_point_longbow {
|
||||
__le16 val_bpsk;
|
||||
__le16 val_qpsk;
|
||||
__le16 val_16qam;
|
||||
__le16 val_64qam;
|
||||
} __packed;
|
||||
|
||||
struct pda_channel_output_limit_longbow {
|
||||
__le16 freq;
|
||||
struct pda_channel_output_limit_point_longbow point[3];
|
||||
} __packed;
|
||||
|
||||
struct pda_pa_curve_data_sample_rev0 {
|
||||
u8 rf_power;
|
||||
u8 pa_detector;
|
||||
|
@ -488,6 +488,58 @@ static int p54p_open(struct ieee80211_hw *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p54p_firmware_step2(const struct firmware *fw,
|
||||
void *context)
|
||||
{
|
||||
struct p54p_priv *priv = context;
|
||||
struct ieee80211_hw *dev = priv->common.hw;
|
||||
struct pci_dev *pdev = priv->pdev;
|
||||
int err;
|
||||
|
||||
if (!fw) {
|
||||
dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->firmware = fw;
|
||||
|
||||
err = p54p_open(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = p54_read_eeprom(dev);
|
||||
p54p_stop(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = p54_register_common(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
|
||||
complete(&priv->fw_loaded);
|
||||
|
||||
if (err) {
|
||||
struct device *parent = pdev->dev.parent;
|
||||
|
||||
if (parent)
|
||||
device_lock(parent);
|
||||
|
||||
/*
|
||||
* This will indirectly result in a call to p54p_remove.
|
||||
* Hence, we don't need to bother with freeing any
|
||||
* allocated ressources at all.
|
||||
*/
|
||||
device_release_driver(&pdev->dev);
|
||||
|
||||
if (parent)
|
||||
device_unlock(parent);
|
||||
}
|
||||
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
@ -496,6 +548,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
unsigned long mem_addr, mem_len;
|
||||
int err;
|
||||
|
||||
pci_dev_get(pdev);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot enable new PCI device\n");
|
||||
@ -537,6 +590,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
priv = dev->priv;
|
||||
priv->pdev = pdev;
|
||||
|
||||
init_completion(&priv->fw_loaded);
|
||||
SET_IEEE80211_DEV(dev, &pdev->dev);
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
@ -561,32 +615,12 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
spin_lock_init(&priv->lock);
|
||||
tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
|
||||
|
||||
err = request_firmware(&priv->firmware, "isl3886pci",
|
||||
&priv->pdev->dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
|
||||
err = request_firmware(&priv->firmware, "isl3886",
|
||||
&priv->pdev->dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
}
|
||||
err = request_firmware_nowait(THIS_MODULE, 1, "isl3886pci",
|
||||
&priv->pdev->dev, GFP_KERNEL,
|
||||
priv, p54p_firmware_step2);
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
err = p54p_open(dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
err = p54_read_eeprom(dev);
|
||||
p54p_stop(dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
|
||||
err = p54_register_common(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto err_free_common;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_common:
|
||||
release_firmware(priv->firmware);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
|
||||
@ -601,6 +635,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
pci_release_regions(pdev);
|
||||
err_disable_dev:
|
||||
pci_disable_device(pdev);
|
||||
pci_dev_put(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -612,8 +647,9 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
p54_unregister_common(dev);
|
||||
priv = dev->priv;
|
||||
wait_for_completion(&priv->fw_loaded);
|
||||
p54_unregister_common(dev);
|
||||
release_firmware(priv->firmware);
|
||||
pci_free_consistent(pdev, sizeof(*priv->ring_control),
|
||||
priv->ring_control, priv->ring_control_dma);
|
||||
|
@ -105,6 +105,7 @@ struct p54p_priv {
|
||||
struct sk_buff *tx_buf_data[32];
|
||||
struct sk_buff *tx_buf_mgmt[4];
|
||||
struct completion boot_comp;
|
||||
struct completion fw_loaded;
|
||||
};
|
||||
|
||||
#endif /* P54USB_H */
|
||||
|
@ -190,16 +190,30 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
|
||||
{
|
||||
struct ssb_bus *bus = mcore->dev->bus;
|
||||
|
||||
mcore->flash_buswidth = 2;
|
||||
if (bus->chipco.dev) {
|
||||
mcore->flash_window = 0x1c000000;
|
||||
mcore->flash_window_size = 0x02000000;
|
||||
/* When there is no chipcommon on the bus there is 4MB flash */
|
||||
if (!bus->chipco.dev) {
|
||||
mcore->flash_buswidth = 2;
|
||||
mcore->flash_window = SSB_FLASH1;
|
||||
mcore->flash_window_size = SSB_FLASH1_SZ;
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is ChipCommon, so use it to read info about flash */
|
||||
switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) {
|
||||
case SSB_CHIPCO_FLASHT_STSER:
|
||||
case SSB_CHIPCO_FLASHT_ATSER:
|
||||
pr_err("Serial flash not supported\n");
|
||||
break;
|
||||
case SSB_CHIPCO_FLASHT_PARA:
|
||||
pr_debug("Found parallel flash\n");
|
||||
mcore->flash_window = SSB_FLASH2;
|
||||
mcore->flash_window_size = SSB_FLASH2_SZ;
|
||||
if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
|
||||
& SSB_CHIPCO_CFG_DS16) == 0)
|
||||
mcore->flash_buswidth = 1;
|
||||
} else {
|
||||
mcore->flash_window = 0x1fc00000;
|
||||
mcore->flash_window_size = 0x00400000;
|
||||
else
|
||||
mcore->flash_buswidth = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,7 @@
|
||||
#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
|
||||
#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */
|
||||
#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */
|
||||
#define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */
|
||||
#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
|
||||
#define BCMA_CC_JCMD_START 0x80000000
|
||||
#define BCMA_CC_JCMD_BUSY 0x80000000
|
||||
@ -266,6 +267,29 @@
|
||||
#define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004
|
||||
#define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1
|
||||
#define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001
|
||||
/* Block 0x140 - 0x190 registers are chipset specific */
|
||||
#define BCMA_CC_4706_FLASHSCFG 0x18C /* Flash struct configuration */
|
||||
#define BCMA_CC_4706_FLASHSCFG_MASK 0x000000ff
|
||||
#define BCMA_CC_4706_FLASHSCFG_SF1 0x00000001 /* 2nd serial flash present */
|
||||
#define BCMA_CC_4706_FLASHSCFG_PF1 0x00000002 /* 2nd parallel flash present */
|
||||
#define BCMA_CC_4706_FLASHSCFG_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */
|
||||
#define BCMA_CC_4706_FLASHSCFG_NF1 0x00000008 /* 2nd NAND flash present */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_MASK 0x000000f0
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */
|
||||
#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */
|
||||
/* NAND flash registers for BCM4706 (corerev = 31) */
|
||||
#define BCMA_CC_NFLASH_CTL 0x01A0
|
||||
#define BCMA_CC_NFLASH_CTL_ERR 0x08000000
|
||||
#define BCMA_CC_NFLASH_CONF 0x01A4
|
||||
#define BCMA_CC_NFLASH_COL_ADDR 0x01A8
|
||||
#define BCMA_CC_NFLASH_ROW_ADDR 0x01AC
|
||||
#define BCMA_CC_NFLASH_DATA 0x01B0
|
||||
#define BCMA_CC_NFLASH_WAITCNT0 0x01B4
|
||||
/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
||||
#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
||||
#define BCMA_CC_UART0_DATA 0x0300
|
||||
@ -325,6 +349,60 @@
|
||||
#define BCMA_CC_PLLCTL_ADDR 0x0660
|
||||
#define BCMA_CC_PLLCTL_DATA 0x0664
|
||||
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
||||
/* NAND flash MLC controller registers (corerev >= 38) */
|
||||
#define BCMA_CC_NAND_REVISION 0x0C00
|
||||
#define BCMA_CC_NAND_CMD_START 0x0C04
|
||||
#define BCMA_CC_NAND_CMD_ADDR_X 0x0C08
|
||||
#define BCMA_CC_NAND_CMD_ADDR 0x0C0C
|
||||
#define BCMA_CC_NAND_CMD_END_ADDR 0x0C10
|
||||
#define BCMA_CC_NAND_CS_NAND_SELECT 0x0C14
|
||||
#define BCMA_CC_NAND_CS_NAND_XOR 0x0C18
|
||||
#define BCMA_CC_NAND_SPARE_RD0 0x0C20
|
||||
#define BCMA_CC_NAND_SPARE_RD4 0x0C24
|
||||
#define BCMA_CC_NAND_SPARE_RD8 0x0C28
|
||||
#define BCMA_CC_NAND_SPARE_RD12 0x0C2C
|
||||
#define BCMA_CC_NAND_SPARE_WR0 0x0C30
|
||||
#define BCMA_CC_NAND_SPARE_WR4 0x0C34
|
||||
#define BCMA_CC_NAND_SPARE_WR8 0x0C38
|
||||
#define BCMA_CC_NAND_SPARE_WR12 0x0C3C
|
||||
#define BCMA_CC_NAND_ACC_CONTROL 0x0C40
|
||||
#define BCMA_CC_NAND_CONFIG 0x0C48
|
||||
#define BCMA_CC_NAND_TIMING_1 0x0C50
|
||||
#define BCMA_CC_NAND_TIMING_2 0x0C54
|
||||
#define BCMA_CC_NAND_SEMAPHORE 0x0C58
|
||||
#define BCMA_CC_NAND_DEVID 0x0C60
|
||||
#define BCMA_CC_NAND_DEVID_X 0x0C64
|
||||
#define BCMA_CC_NAND_BLOCK_LOCK_STATUS 0x0C68
|
||||
#define BCMA_CC_NAND_INTFC_STATUS 0x0C6C
|
||||
#define BCMA_CC_NAND_ECC_CORR_ADDR_X 0x0C70
|
||||
#define BCMA_CC_NAND_ECC_CORR_ADDR 0x0C74
|
||||
#define BCMA_CC_NAND_ECC_UNC_ADDR_X 0x0C78
|
||||
#define BCMA_CC_NAND_ECC_UNC_ADDR 0x0C7C
|
||||
#define BCMA_CC_NAND_READ_ERROR_COUNT 0x0C80
|
||||
#define BCMA_CC_NAND_CORR_STAT_THRESHOLD 0x0C84
|
||||
#define BCMA_CC_NAND_READ_ADDR_X 0x0C90
|
||||
#define BCMA_CC_NAND_READ_ADDR 0x0C94
|
||||
#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR_X 0x0C98
|
||||
#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR 0x0C9C
|
||||
#define BCMA_CC_NAND_COPY_BACK_ADDR_X 0x0CA0
|
||||
#define BCMA_CC_NAND_COPY_BACK_ADDR 0x0CA4
|
||||
#define BCMA_CC_NAND_BLOCK_ERASE_ADDR_X 0x0CA8
|
||||
#define BCMA_CC_NAND_BLOCK_ERASE_ADDR 0x0CAC
|
||||
#define BCMA_CC_NAND_INV_READ_ADDR_X 0x0CB0
|
||||
#define BCMA_CC_NAND_INV_READ_ADDR 0x0CB4
|
||||
#define BCMA_CC_NAND_BLK_WR_PROTECT 0x0CC0
|
||||
#define BCMA_CC_NAND_ACC_CONTROL_CS1 0x0CD0
|
||||
#define BCMA_CC_NAND_CONFIG_CS1 0x0CD4
|
||||
#define BCMA_CC_NAND_TIMING_1_CS1 0x0CD8
|
||||
#define BCMA_CC_NAND_TIMING_2_CS1 0x0CDC
|
||||
#define BCMA_CC_NAND_SPARE_RD16 0x0D30
|
||||
#define BCMA_CC_NAND_SPARE_RD20 0x0D34
|
||||
#define BCMA_CC_NAND_SPARE_RD24 0x0D38
|
||||
#define BCMA_CC_NAND_SPARE_RD28 0x0D3C
|
||||
#define BCMA_CC_NAND_CACHE_ADDR 0x0D40
|
||||
#define BCMA_CC_NAND_CACHE_DATA 0x0D44
|
||||
#define BCMA_CC_NAND_CTRL_CONFIG 0x0D48
|
||||
#define BCMA_CC_NAND_CTRL_STATUS 0x0D4C
|
||||
|
||||
/* Divider allocation in 4716/47162/5356 */
|
||||
#define BCMA_CC_PMU5_MAINPLL_CPU 1
|
||||
@ -415,6 +493,13 @@
|
||||
/* 4313 Chip specific ChipControl register bits */
|
||||
#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
|
||||
|
||||
/* BCM5357 ChipControl register bits */
|
||||
#define BCMA_CHIPCTL_5357_EXTPA BIT(14)
|
||||
#define BCMA_CHIPCTL_5357_ANT_MUX_2O3 BIT(15)
|
||||
#define BCMA_CHIPCTL_5357_NFLASH BIT(16)
|
||||
#define BCMA_CHIPCTL_5357_I2S_PINS_ENABLE BIT(18)
|
||||
#define BCMA_CHIPCTL_5357_I2CSPI_PINS_ENABLE BIT(19)
|
||||
|
||||
/* Data for the PMU, if available.
|
||||
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
*/
|
||||
|
@ -11,11 +11,13 @@
|
||||
#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||||
#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||||
#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
|
||||
#define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8
|
||||
#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
|
||||
#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
|
||||
#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
|
||||
#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
|
||||
#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
|
||||
#define BCMA_CLKCTLST_EXTRESST_SHIFT 24
|
||||
/* Is there any BCM4328 on BCMA bus? */
|
||||
#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
|
||||
#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
|
||||
|
@ -504,7 +504,9 @@
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_SE 0x02D8 /* Sector Erase */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_BE 0x00C7 /* Bulk Erase */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_DP 0x00B9 /* Deep Power-down */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_RSIG 0x03AB /* Read Electronic Signature */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_RES 0x03AB /* Read Electronic Signature */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */
|
||||
#define SSB_CHIPCO_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */
|
||||
|
||||
/* Status register bits for ST flashes */
|
||||
#define SSB_CHIPCO_FLASHSTA_ST_WIP 0x01 /* Write In Progress */
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <linux/poll.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#ifndef AF_BLUETOOTH
|
||||
#define AF_BLUETOOTH 31
|
||||
@ -202,6 +203,10 @@ enum {
|
||||
struct bt_sock_list {
|
||||
struct hlist_head head;
|
||||
rwlock_t lock;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct file_operations fops;
|
||||
int (* custom_seq_show)(struct seq_file *, void *);
|
||||
#endif
|
||||
};
|
||||
|
||||
int bt_sock_register(int proto, const struct net_proto_family *ops);
|
||||
@ -292,6 +297,11 @@ extern void hci_sock_cleanup(void);
|
||||
extern int bt_sysfs_init(void);
|
||||
extern void bt_sysfs_cleanup(void);
|
||||
|
||||
extern int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||
struct bt_sock_list* sk_list,
|
||||
int (* seq_show)(struct seq_file *, void *));
|
||||
extern void bt_procfs_cleanup(struct net *net, const char *name);
|
||||
|
||||
extern struct dentry *bt_debugfs;
|
||||
|
||||
int l2cap_init(void);
|
||||
|
@ -62,6 +62,15 @@
|
||||
/* First BR/EDR Controller shall have ID = 0 */
|
||||
#define HCI_BREDR_ID 0
|
||||
|
||||
/* AMP controller status */
|
||||
#define AMP_CTRL_POWERED_DOWN 0x00
|
||||
#define AMP_CTRL_BLUETOOTH_ONLY 0x01
|
||||
#define AMP_CTRL_NO_CAPACITY 0x02
|
||||
#define AMP_CTRL_LOW_CAPACITY 0x03
|
||||
#define AMP_CTRL_MEDIUM_CAPACITY 0x04
|
||||
#define AMP_CTRL_HIGH_CAPACITY 0x05
|
||||
#define AMP_CTRL_FULL_CAPACITY 0x06
|
||||
|
||||
/* HCI device quirks */
|
||||
enum {
|
||||
HCI_QUIRK_RESET_ON_CLOSE,
|
||||
@ -1295,6 +1304,8 @@ struct hci_ev_num_comp_blocks {
|
||||
} __packed;
|
||||
|
||||
/* Low energy meta events */
|
||||
#define LE_CONN_ROLE_MASTER 0x00
|
||||
|
||||
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
||||
struct hci_ev_le_conn_complete {
|
||||
__u8 status;
|
||||
|
@ -115,12 +115,6 @@ struct oob_data {
|
||||
u8 randomizer[16];
|
||||
};
|
||||
|
||||
struct adv_entry {
|
||||
struct list_head list;
|
||||
bdaddr_t bdaddr;
|
||||
u8 bdaddr_type;
|
||||
};
|
||||
|
||||
struct le_scan_params {
|
||||
u8 type;
|
||||
u16 interval;
|
||||
@ -356,16 +350,16 @@ extern rwlock_t hci_cb_list_lock;
|
||||
|
||||
/* ----- HCI interface to upper protocols ----- */
|
||||
extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
|
||||
extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
|
||||
extern int l2cap_disconn_ind(struct hci_conn *hcon);
|
||||
extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
|
||||
extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
|
||||
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
|
||||
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
|
||||
u16 flags);
|
||||
|
||||
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
|
||||
extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
|
||||
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
|
||||
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
|
||||
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
|
||||
|
||||
/* ----- Inquiry cache ----- */
|
||||
@ -587,8 +581,7 @@ void hci_conn_put_device(struct hci_conn *conn);
|
||||
|
||||
static inline void hci_conn_hold(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
|
||||
atomic_read(&conn->refcnt) + 1);
|
||||
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
|
||||
|
||||
atomic_inc(&conn->refcnt);
|
||||
cancel_delayed_work(&conn->disc_work);
|
||||
@ -596,8 +589,7 @@ static inline void hci_conn_hold(struct hci_conn *conn)
|
||||
|
||||
static inline void hci_conn_put(struct hci_conn *conn)
|
||||
{
|
||||
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
|
||||
atomic_read(&conn->refcnt) - 1);
|
||||
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
|
||||
|
||||
if (atomic_dec_and_test(&conn->refcnt)) {
|
||||
unsigned long timeo;
|
||||
@ -1056,7 +1048,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
|
||||
int mgmt_interleaved_discovery(struct hci_dev *hdev);
|
||||
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
||||
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
||||
|
||||
bool mgmt_valid_hdev(struct hci_dev *hdev);
|
||||
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
|
||||
|
||||
/* HCI info for socket */
|
||||
|
@ -671,20 +671,8 @@ enum {
|
||||
L2CAP_EV_RECV_FRAME,
|
||||
};
|
||||
|
||||
static inline void l2cap_chan_hold(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||
|
||||
atomic_inc(&c->refcnt);
|
||||
}
|
||||
|
||||
static inline void l2cap_chan_put(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||
|
||||
if (atomic_dec_and_test(&c->refcnt))
|
||||
kfree(c);
|
||||
}
|
||||
void l2cap_chan_hold(struct l2cap_chan *c);
|
||||
void l2cap_chan_put(struct l2cap_chan *c);
|
||||
|
||||
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
|
||||
{
|
||||
@ -771,7 +759,6 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
|
||||
|
||||
struct l2cap_chan *l2cap_chan_create(void);
|
||||
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
|
||||
void l2cap_chan_destroy(struct l2cap_chan *chan);
|
||||
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
bdaddr_t *dst, u8 dst_type);
|
||||
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||
|
@ -108,8 +108,8 @@ struct smp_cmd_security_req {
|
||||
#define SMP_CONFIRM_FAILED 0x04
|
||||
#define SMP_PAIRING_NOTSUPP 0x05
|
||||
#define SMP_ENC_KEY_SIZE 0x06
|
||||
#define SMP_CMD_NOTSUPP 0x07
|
||||
#define SMP_UNSPECIFIED 0x08
|
||||
#define SMP_CMD_NOTSUPP 0x07
|
||||
#define SMP_UNSPECIFIED 0x08
|
||||
#define SMP_REPEATED_ATTEMPTS 0x09
|
||||
|
||||
#define SMP_MIN_ENC_KEY_SIZE 7
|
||||
@ -123,8 +123,8 @@ struct smp_chan {
|
||||
struct l2cap_conn *conn;
|
||||
u8 preq[7]; /* SMP Pairing Request */
|
||||
u8 prsp[7]; /* SMP Pairing Response */
|
||||
u8 prnd[16]; /* SMP Pairing Random (local) */
|
||||
u8 rrnd[16]; /* SMP Pairing Random (remote) */
|
||||
u8 prnd[16]; /* SMP Pairing Random (local) */
|
||||
u8 rrnd[16]; /* SMP Pairing Random (remote) */
|
||||
u8 pcnf[16]; /* SMP Pairing Confirm */
|
||||
u8 tk[16]; /* SMP Temporary Key */
|
||||
u8 enc_key_size;
|
||||
|
@ -316,7 +316,7 @@ send_rsp:
|
||||
static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
struct a2mp_cmd *hdr)
|
||||
{
|
||||
BT_DBG("ident %d code %d", hdr->ident, hdr->code);
|
||||
BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code);
|
||||
|
||||
skb_pull(skb, le16_to_cpu(hdr->len));
|
||||
return 0;
|
||||
@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
/* Handle A2MP signalling */
|
||||
static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||
{
|
||||
struct a2mp_cmd *hdr = (void *) skb->data;
|
||||
struct a2mp_cmd *hdr;
|
||||
struct amp_mgr *mgr = chan->data;
|
||||
int err = 0;
|
||||
|
||||
amp_mgr_get(mgr);
|
||||
|
||||
while (skb->len >= sizeof(*hdr)) {
|
||||
struct a2mp_cmd *hdr = (void *) skb->data;
|
||||
u16 len = le16_to_cpu(hdr->len);
|
||||
u16 len;
|
||||
|
||||
BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len);
|
||||
hdr = (void *) skb->data;
|
||||
len = le16_to_cpu(hdr->len);
|
||||
|
||||
BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len);
|
||||
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
|
||||
@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||
|
||||
if (err) {
|
||||
struct a2mp_cmd_rej rej;
|
||||
|
||||
rej.reason = __constant_cpu_to_le16(0);
|
||||
hdr = (void *) skb->data;
|
||||
|
||||
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
|
||||
|
||||
@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||
|
||||
static void a2mp_chan_close_cb(struct l2cap_chan *chan)
|
||||
{
|
||||
l2cap_chan_destroy(chan);
|
||||
l2cap_chan_put(chan);
|
||||
}
|
||||
|
||||
static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <asm/ioctls.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#define VERSION "2.16"
|
||||
|
||||
@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_wait_state);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct bt_seq_state {
|
||||
struct bt_sock_list *l;
|
||||
};
|
||||
|
||||
static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
|
||||
__acquires(seq->private->l->lock)
|
||||
{
|
||||
struct bt_seq_state *s = seq->private;
|
||||
struct bt_sock_list *l = s->l;
|
||||
|
||||
read_lock(&l->lock);
|
||||
return seq_hlist_start_head(&l->head, *pos);
|
||||
}
|
||||
|
||||
static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
struct bt_seq_state *s = seq->private;
|
||||
struct bt_sock_list *l = s->l;
|
||||
|
||||
return seq_hlist_next(v, &l->head, pos);
|
||||
}
|
||||
|
||||
static void bt_seq_stop(struct seq_file *seq, void *v)
|
||||
__releases(seq->private->l->lock)
|
||||
{
|
||||
struct bt_seq_state *s = seq->private;
|
||||
struct bt_sock_list *l = s->l;
|
||||
|
||||
read_unlock(&l->lock);
|
||||
}
|
||||
|
||||
static int bt_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct sock *sk;
|
||||
struct bt_sock *bt;
|
||||
struct bt_seq_state *s = seq->private;
|
||||
struct bt_sock_list *l = s->l;
|
||||
bdaddr_t src_baswapped, dst_baswapped;
|
||||
|
||||
if (v == SEQ_START_TOKEN) {
|
||||
seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
|
||||
|
||||
if (l->custom_seq_show) {
|
||||
seq_putc(seq, ' ');
|
||||
l->custom_seq_show(seq, v);
|
||||
}
|
||||
|
||||
seq_putc(seq, '\n');
|
||||
} else {
|
||||
sk = sk_entry(v);
|
||||
bt = bt_sk(sk);
|
||||
baswap(&src_baswapped, &bt->src);
|
||||
baswap(&dst_baswapped, &bt->dst);
|
||||
|
||||
seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
|
||||
sk,
|
||||
atomic_read(&sk->sk_refcnt),
|
||||
sk_rmem_alloc_get(sk),
|
||||
sk_wmem_alloc_get(sk),
|
||||
sock_i_uid(sk),
|
||||
sock_i_ino(sk),
|
||||
&src_baswapped,
|
||||
&dst_baswapped,
|
||||
bt->parent? sock_i_ino(bt->parent): 0LU);
|
||||
|
||||
if (l->custom_seq_show) {
|
||||
seq_putc(seq, ' ');
|
||||
l->custom_seq_show(seq, v);
|
||||
}
|
||||
|
||||
seq_putc(seq, '\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations bt_seq_ops = {
|
||||
.start = bt_seq_start,
|
||||
.next = bt_seq_next,
|
||||
.stop = bt_seq_stop,
|
||||
.show = bt_seq_show,
|
||||
};
|
||||
|
||||
static int bt_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct bt_sock_list *sk_list;
|
||||
struct bt_seq_state *s;
|
||||
|
||||
sk_list = PDE(inode)->data;
|
||||
s = __seq_open_private(file, &bt_seq_ops,
|
||||
sizeof(struct bt_seq_state));
|
||||
if (s == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
s->l = sk_list;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||
struct bt_sock_list* sk_list,
|
||||
int (* seq_show)(struct seq_file *, void *))
|
||||
{
|
||||
struct proc_dir_entry * pde;
|
||||
|
||||
sk_list->custom_seq_show = seq_show;
|
||||
|
||||
sk_list->fops.owner = module;
|
||||
sk_list->fops.open = bt_seq_open;
|
||||
sk_list->fops.read = seq_read;
|
||||
sk_list->fops.llseek = seq_lseek;
|
||||
sk_list->fops.release = seq_release_private;
|
||||
|
||||
pde = proc_net_fops_create(net, name, 0, &sk_list->fops);
|
||||
if (pde == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pde->data = sk_list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_procfs_cleanup(struct net *net, const char *name)
|
||||
{
|
||||
proc_net_remove(net, name);
|
||||
}
|
||||
#else
|
||||
int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||
struct bt_sock_list* sk_list,
|
||||
int (* seq_show)(struct seq_file *, void *))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_procfs_cleanup(struct net *net, const char *name)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL(bt_procfs_init);
|
||||
EXPORT_SYMBOL(bt_procfs_cleanup);
|
||||
|
||||
static struct net_proto_family bt_sock_family_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.family = PF_BLUETOOTH,
|
||||
|
@ -29,6 +29,10 @@
|
||||
|
||||
#include "bnep.h"
|
||||
|
||||
static struct bt_sock_list bnep_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
|
||||
};
|
||||
|
||||
static int bnep_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock)
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
bt_sock_unlink(&bnep_sk_list, sk);
|
||||
|
||||
sock_orphan(sk);
|
||||
sock_put(sk);
|
||||
return 0;
|
||||
@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_protocol = protocol;
|
||||
sk->sk_state = BT_OPEN;
|
||||
|
||||
bt_sock_link(&bnep_sk_list, sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -222,19 +229,30 @@ int __init bnep_sock_init(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't register BNEP socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create BNEP proc file");
|
||||
bt_sock_unregister(BTPROTO_BNEP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BT_INFO("BNEP socket layer initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
BT_ERR("Can't register BNEP socket");
|
||||
proto_unregister(&bnep_proto);
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit bnep_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "bnep");
|
||||
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
|
||||
BT_ERR("Can't unregister BNEP socket");
|
||||
|
||||
|
@ -42,6 +42,10 @@
|
||||
|
||||
#include "cmtp.h"
|
||||
|
||||
static struct bt_sock_list cmtp_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock)
|
||||
};
|
||||
|
||||
static int cmtp_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock)
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
bt_sock_unlink(&cmtp_sk_list, sk);
|
||||
|
||||
sock_orphan(sk);
|
||||
sock_put(sk);
|
||||
|
||||
@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_protocol = protocol;
|
||||
sk->sk_state = BT_OPEN;
|
||||
|
||||
bt_sock_link(&cmtp_sk_list, sk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -232,19 +240,30 @@ int cmtp_init_sockets(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't register CMTP socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create CMTP proc file");
|
||||
bt_sock_unregister(BTPROTO_HIDP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BT_INFO("CMTP socket layer initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
BT_ERR("Can't register CMTP socket");
|
||||
proto_unregister(&cmtp_proto);
|
||||
return err;
|
||||
}
|
||||
|
||||
void cmtp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "cmtp");
|
||||
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
|
||||
BT_ERR("Can't unregister CMTP socket");
|
||||
|
||||
|
@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev)
|
||||
hci_dev_hold(hdev);
|
||||
set_bit(HCI_UP, &hdev->flags);
|
||||
hci_notify(hdev, HCI_DEV_UP);
|
||||
if (!test_bit(HCI_SETUP, &hdev->dev_flags)) {
|
||||
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
|
||||
mgmt_valid_hdev(hdev)) {
|
||||
hci_dev_lock(hdev);
|
||||
mgmt_powered(hdev, 1);
|
||||
hci_dev_unlock(hdev);
|
||||
@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
||||
* and no tasks are scheduled. */
|
||||
hdev->close(hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
|
||||
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
|
||||
mgmt_valid_hdev(hdev)) {
|
||||
hci_dev_lock(hdev);
|
||||
mgmt_powered(hdev, 0);
|
||||
hci_dev_unlock(hdev);
|
||||
|
@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||
if (hdev->features[3] & LMP_RSSI_INQ)
|
||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||
|
||||
if (hdev->features[5] & LMP_SNIFF_SUBR)
|
||||
if (lmp_sniffsubr_capable(hdev))
|
||||
events[5] |= 0x20; /* Sniff Subrating */
|
||||
|
||||
if (hdev->features[5] & LMP_PAUSE_ENC)
|
||||
@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||
if (hdev->features[6] & LMP_EXT_INQ)
|
||||
events[5] |= 0x40; /* Extended Inquiry Result */
|
||||
|
||||
if (hdev->features[6] & LMP_NO_FLUSH)
|
||||
if (lmp_no_flush_capable(hdev))
|
||||
events[7] |= 0x01; /* Enhanced Flush Complete */
|
||||
|
||||
if (hdev->features[7] & LMP_LSTO)
|
||||
events[6] |= 0x80; /* Link Supervision Timeout Changed */
|
||||
|
||||
if (hdev->features[6] & LMP_SIMPLE_PAIR) {
|
||||
if (lmp_ssp_capable(hdev)) {
|
||||
events[6] |= 0x01; /* IO Capability Request */
|
||||
events[6] |= 0x02; /* IO Capability Response */
|
||||
events[6] |= 0x04; /* User Confirmation Request */
|
||||
@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||
* Features Notification */
|
||||
}
|
||||
|
||||
if (hdev->features[4] & LMP_LE)
|
||||
if (lmp_le_capable(hdev))
|
||||
events[7] |= 0x20; /* LE Meta-Event */
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
||||
@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
|
||||
struct hci_cp_write_def_link_policy cp;
|
||||
u16 link_policy = 0;
|
||||
|
||||
if (hdev->features[0] & LMP_RSWITCH)
|
||||
if (lmp_rswitch_capable(hdev))
|
||||
link_policy |= HCI_LP_RSWITCH;
|
||||
if (hdev->features[0] & LMP_HOLD)
|
||||
link_policy |= HCI_LP_HOLD;
|
||||
if (hdev->features[0] & LMP_SNIFF)
|
||||
if (lmp_sniff_capable(hdev))
|
||||
link_policy |= HCI_LP_SNIFF;
|
||||
if (hdev->features[1] & LMP_PARK)
|
||||
link_policy |= HCI_LP_PARK;
|
||||
@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
|
||||
hdev->esco_type |= (ESCO_HV3);
|
||||
}
|
||||
|
||||
if (hdev->features[3] & LMP_ESCO)
|
||||
if (lmp_esco_capable(hdev))
|
||||
hdev->esco_type |= (ESCO_EV3);
|
||||
|
||||
if (hdev->features[4] & LMP_EV4)
|
||||
@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
|
||||
break;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
|
||||
if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
|
||||
hci_set_le_support(hdev);
|
||||
|
||||
done:
|
||||
@ -1614,43 +1614,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
|
||||
|
||||
static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
{
|
||||
struct hci_cp_le_create_conn *cp;
|
||||
struct hci_conn *conn;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
|
||||
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
|
||||
|
||||
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
|
||||
conn);
|
||||
|
||||
if (status) {
|
||||
if (conn && conn->state == BT_CONNECT) {
|
||||
conn->state = BT_CLOSED;
|
||||
mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
|
||||
conn->dst_type, status);
|
||||
hci_proto_connect_cfm(conn, status);
|
||||
hci_conn_del(conn);
|
||||
}
|
||||
} else {
|
||||
if (!conn) {
|
||||
conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
|
||||
if (conn) {
|
||||
conn->dst_type = cp->peer_addr_type;
|
||||
conn->out = true;
|
||||
} else {
|
||||
BT_ERR("No memory for new connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
||||
if (!conn) {
|
||||
hci_dev_unlock(hdev);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
|
||||
conn);
|
||||
|
||||
conn->state = BT_CLOSED;
|
||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, status);
|
||||
hci_proto_connect_cfm(conn, status);
|
||||
hci_conn_del(conn);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
|
||||
@ -3252,12 +3239,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
|
||||
@ -3350,11 +3333,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (ev->status) {
|
||||
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
||||
if (!conn)
|
||||
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
||||
if (!conn) {
|
||||
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
|
||||
if (!conn) {
|
||||
BT_ERR("No memory for new connection");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
conn->dst_type = ev->bdaddr_type;
|
||||
|
||||
if (ev->role == LE_CONN_ROLE_MASTER) {
|
||||
conn->out = true;
|
||||
conn->link_mode |= HCI_LM_MASTER;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->status) {
|
||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, ev->status);
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
@ -3363,18 +3358,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
|
||||
if (!conn) {
|
||||
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
|
||||
if (!conn) {
|
||||
BT_ERR("No memory for new connection");
|
||||
hci_dev_unlock(hdev);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->dst_type = ev->bdaddr_type;
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
||||
mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
|
||||
conn->dst_type, 0, NULL, 0, NULL);
|
||||
|
@ -1100,21 +1100,30 @@ int __init hci_sock_init(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("HCI socket registration failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create HCI proc file");
|
||||
bt_sock_unregister(BTPROTO_HCI);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BT_INFO("HCI socket layer initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
BT_ERR("HCI socket registration failed");
|
||||
proto_unregister(&hci_sk_proto);
|
||||
return err;
|
||||
}
|
||||
|
||||
void hci_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hci");
|
||||
if (bt_sock_unregister(BTPROTO_HCI) < 0)
|
||||
BT_ERR("HCI socket unregistration failed");
|
||||
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
#include "hidp.h"
|
||||
|
||||
static struct bt_sock_list hidp_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock)
|
||||
};
|
||||
|
||||
static int hidp_sock_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock)
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
bt_sock_unlink(&hidp_sk_list, sk);
|
||||
|
||||
sock_orphan(sk);
|
||||
sock_put(sk);
|
||||
|
||||
@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||
sk->sk_protocol = protocol;
|
||||
sk->sk_state = BT_OPEN;
|
||||
|
||||
bt_sock_link(&hidp_sk_list, sk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -271,8 +279,19 @@ int __init hidp_init_sockets(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't register HIDP socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create HIDP proc file");
|
||||
bt_sock_unregister(BTPROTO_HIDP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BT_INFO("HIDP socket layer initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
@ -284,6 +303,7 @@ error:
|
||||
|
||||
void __exit hidp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hidp");
|
||||
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
|
||||
BT_ERR("Can't unregister HIDP socket");
|
||||
|
||||
|
@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void)
|
||||
return chan;
|
||||
}
|
||||
|
||||
void l2cap_chan_destroy(struct l2cap_chan *chan)
|
||||
static void l2cap_chan_destroy(struct l2cap_chan *chan)
|
||||
{
|
||||
BT_DBG("chan %p", chan);
|
||||
|
||||
write_lock(&chan_list_lock);
|
||||
list_del(&chan->global_l);
|
||||
write_unlock(&chan_list_lock);
|
||||
|
||||
l2cap_chan_put(chan);
|
||||
kfree(chan);
|
||||
}
|
||||
|
||||
void l2cap_chan_hold(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||
|
||||
atomic_inc(&c->refcnt);
|
||||
}
|
||||
|
||||
void l2cap_chan_put(struct l2cap_chan *c)
|
||||
{
|
||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||
|
||||
if (atomic_dec_and_test(&c->refcnt))
|
||||
l2cap_chan_destroy(c);
|
||||
}
|
||||
|
||||
void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
||||
@ -5329,7 +5346,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
return exact ? lm1 : lm2;
|
||||
}
|
||||
|
||||
int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
{
|
||||
struct l2cap_conn *conn;
|
||||
|
||||
@ -5342,7 +5359,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||
} else
|
||||
l2cap_conn_del(hcon, bt_to_errno(status));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l2cap_disconn_ind(struct hci_conn *hcon)
|
||||
@ -5356,12 +5372,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
|
||||
return conn->disc_reason;
|
||||
}
|
||||
|
||||
int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
||||
void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
||||
{
|
||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||
|
||||
l2cap_conn_del(hcon, bt_to_errno(reason));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
|
||||
@ -5404,6 +5419,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
||||
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
|
||||
state_to_string(chan->state));
|
||||
|
||||
if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
|
||||
l2cap_chan_unlock(chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chan->scid == L2CAP_CID_LE_DATA) {
|
||||
if (!status && encrypt) {
|
||||
chan->sec_level = hcon->sec_level;
|
||||
|
@ -34,6 +34,10 @@
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
#include <net/bluetooth/smp.h>
|
||||
|
||||
static struct bt_sock_list l2cap_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
|
||||
};
|
||||
|
||||
static const struct proto_ops l2cap_sock_ops;
|
||||
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
|
||||
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
|
||||
@ -823,7 +827,7 @@ static void l2cap_sock_kill(struct sock *sk)
|
||||
|
||||
/* Kill poor orphan */
|
||||
|
||||
l2cap_chan_destroy(l2cap_pi(sk)->chan);
|
||||
l2cap_chan_put(l2cap_pi(sk)->chan);
|
||||
sock_set_flag(sk, SOCK_DEAD);
|
||||
sock_put(sk);
|
||||
}
|
||||
@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock)
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
bt_sock_unlink(&l2cap_sk_list, sk);
|
||||
|
||||
err = l2cap_sock_shutdown(sock, 2);
|
||||
|
||||
sock_orphan(sk);
|
||||
@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||
return -ENOMEM;
|
||||
|
||||
l2cap_sock_init(sk, NULL);
|
||||
bt_sock_link(&l2cap_sk_list, sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("L2CAP socket registration failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create L2CAP proc file");
|
||||
bt_sock_unregister(BTPROTO_L2CAP);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BT_INFO("L2CAP socket layer initialized");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
BT_ERR("L2CAP socket registration failed");
|
||||
proto_unregister(&l2cap_proto);
|
||||
return err;
|
||||
}
|
||||
|
||||
void l2cap_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "l2cap");
|
||||
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
|
||||
BT_ERR("L2CAP socket unregistration failed");
|
||||
|
||||
|
@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = {
|
||||
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
|
||||
};
|
||||
|
||||
bool mgmt_valid_hdev(struct hci_dev *hdev)
|
||||
{
|
||||
return hdev->dev_type == HCI_BREDR;
|
||||
}
|
||||
|
||||
static u8 mgmt_status(u8 hci_status)
|
||||
{
|
||||
if (hci_status < ARRAY_SIZE(mgmt_status_table))
|
||||
@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
u16 data_len)
|
||||
{
|
||||
struct mgmt_rp_read_index_list *rp;
|
||||
struct list_head *p;
|
||||
struct hci_dev *d;
|
||||
size_t rp_len;
|
||||
u16 count;
|
||||
@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
read_lock(&hci_dev_list_lock);
|
||||
|
||||
count = 0;
|
||||
list_for_each(p, &hci_dev_list) {
|
||||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (!mgmt_valid_hdev(d))
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
if (test_bit(HCI_SETUP, &d->dev_flags))
|
||||
continue;
|
||||
|
||||
if (!mgmt_valid_hdev(d))
|
||||
continue;
|
||||
|
||||
rp->index[i++] = cpu_to_le16(d->id);
|
||||
BT_DBG("Added hci%u", d->id);
|
||||
}
|
||||
@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
||||
settings |= MGMT_SETTING_DISCOVERABLE;
|
||||
settings |= MGMT_SETTING_PAIRABLE;
|
||||
|
||||
if (hdev->features[6] & LMP_SIMPLE_PAIR)
|
||||
if (lmp_ssp_capable(hdev))
|
||||
settings |= MGMT_SETTING_SSP;
|
||||
|
||||
if (!(hdev->features[4] & LMP_NO_BREDR)) {
|
||||
if (lmp_bredr_capable(hdev)) {
|
||||
settings |= MGMT_SETTING_BREDR;
|
||||
settings |= MGMT_SETTING_LINK_SECURITY;
|
||||
}
|
||||
@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
||||
if (enable_hs)
|
||||
settings |= MGMT_SETTING_HS;
|
||||
|
||||
if (hdev->features[4] & LMP_LE)
|
||||
if (lmp_le_capable(hdev))
|
||||
settings |= MGMT_SETTING_LE;
|
||||
|
||||
return settings;
|
||||
@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev)
|
||||
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
|
||||
settings |= MGMT_SETTING_PAIRABLE;
|
||||
|
||||
if (!(hdev->features[4] & LMP_NO_BREDR))
|
||||
if (lmp_bredr_capable(hdev))
|
||||
settings |= MGMT_SETTING_BREDR;
|
||||
|
||||
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
||||
@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
||||
if (!lmp_ssp_capable(hdev)) {
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
|
||||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
goto failed;
|
||||
@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (!(hdev->features[4] & LMP_LE)) {
|
||||
if (!lmp_le_capable(hdev)) {
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
|
||||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
goto unlock;
|
||||
@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
||||
if (!lmp_ssp_capable(hdev)) {
|
||||
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
goto unlock;
|
||||
@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
|
||||
|
||||
int mgmt_index_added(struct hci_dev *hdev)
|
||||
{
|
||||
if (!mgmt_valid_hdev(hdev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev)
|
||||
{
|
||||
u8 status = MGMT_STATUS_INVALID_INDEX;
|
||||
|
||||
if (!mgmt_valid_hdev(hdev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
|
||||
|
||||
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
|
||||
|
@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void)
|
||||
return err;
|
||||
|
||||
err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
BT_ERR("RFCOMM socket layer registration failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create RFCOMM proc file");
|
||||
bt_sock_unregister(BTPROTO_RFCOMM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bt_debugfs) {
|
||||
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
|
||||
@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
BT_ERR("RFCOMM socket layer registration failed");
|
||||
proto_unregister(&rfcomm_proto);
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit rfcomm_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "rfcomm");
|
||||
|
||||
debugfs_remove(rfcomm_sock_debugfs);
|
||||
|
||||
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
|
||||
|
@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
return lm;
|
||||
}
|
||||
|
||||
int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
||||
void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
||||
{
|
||||
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
|
||||
if (!status) {
|
||||
@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
||||
sco_conn_ready(conn);
|
||||
} else
|
||||
sco_conn_del(hcon, bt_to_errno(status));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
||||
void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
||||
{
|
||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||
|
||||
sco_conn_del(hcon, bt_to_errno(reason));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
|
||||
@ -1026,6 +1023,13 @@ int __init sco_init(void)
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL);
|
||||
if (err < 0) {
|
||||
BT_ERR("Failed to create SCO proc file");
|
||||
bt_sock_unregister(BTPROTO_SCO);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bt_debugfs) {
|
||||
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
|
||||
NULL, &sco_debugfs_fops);
|
||||
@ -1044,6 +1048,8 @@ error:
|
||||
|
||||
void __exit sco_exit(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "sco");
|
||||
|
||||
debugfs_remove(sco_debugfs);
|
||||
|
||||
if (bt_sock_unregister(BTPROTO_SCO) < 0)
|
||||
|
@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
|
||||
* mesh_accept_plinks_update - update accepting_plink in local mesh beacons
|
||||
*
|
||||
* @sdata: mesh interface in which mesh beacons are going to be updated
|
||||
*
|
||||
* Returns: beacon changed flag if the beacon content changed.
|
||||
*/
|
||||
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
|
||||
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
bool free_plinks;
|
||||
u32 changed = 0;
|
||||
|
||||
/* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
|
||||
* the mesh interface might be able to establish plinks with peers that
|
||||
@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
|
||||
*/
|
||||
free_plinks = mesh_plink_availables(sdata);
|
||||
|
||||
if (free_plinks != sdata->u.mesh.accepting_plinks)
|
||||
ieee80211_mesh_housekeeping_timer((unsigned long) sdata);
|
||||
if (free_plinks != sdata->u.mesh.accepting_plinks) {
|
||||
sdata->u.mesh.accepting_plinks = free_plinks;
|
||||
changed = BSS_CHANGED_BEACON;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
|
||||
@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
|
||||
neighbors = (neighbors > 15) ? 15 : neighbors;
|
||||
*pos++ = neighbors << 1;
|
||||
/* Mesh capability */
|
||||
ifmsh->accepting_plinks = mesh_plink_availables(sdata);
|
||||
*pos = MESHCONF_CAPAB_FORWARDING;
|
||||
*pos |= ifmsh->accepting_plinks ?
|
||||
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
|
||||
@ -521,14 +527,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
|
||||
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_if_mesh *ifmsh)
|
||||
{
|
||||
bool free_plinks;
|
||||
u32 changed;
|
||||
|
||||
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
|
||||
mesh_path_expire(sdata);
|
||||
|
||||
free_plinks = mesh_plink_availables(sdata);
|
||||
if (free_plinks != sdata->u.mesh.accepting_plinks)
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
changed = mesh_accept_plinks_update(sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
mod_timer(&ifmsh->housekeeping_timer,
|
||||
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
|
||||
|
@ -282,7 +282,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
|
||||
u8 *hw_addr,
|
||||
struct ieee802_11_elems *ie);
|
||||
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
|
||||
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
|
||||
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
|
||||
void mesh_plink_broken(struct sta_info *sta);
|
||||
void mesh_plink_deactivate(struct sta_info *sta);
|
||||
int mesh_plink_open(struct sta_info *sta);
|
||||
|
@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
|
||||
u8 *da, __le16 llid, __le16 plid, __le16 reason);
|
||||
|
||||
static inline
|
||||
void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
|
||||
u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
|
||||
mesh_accept_plinks_update(sdata);
|
||||
return mesh_accept_plinks_update(sdata);
|
||||
}
|
||||
|
||||
static inline
|
||||
void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
|
||||
u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
|
||||
mesh_accept_plinks_update(sdata);
|
||||
return mesh_accept_plinks_update(sdata);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,22 +170,21 @@ out:
|
||||
* @sta: mesh peer link to deactivate
|
||||
*
|
||||
* All mesh paths with this peer as next hop will be flushed
|
||||
* Returns beacon changed flag if the beacon content changed.
|
||||
*
|
||||
* Locking: the caller must hold sta->lock
|
||||
*/
|
||||
static bool __mesh_plink_deactivate(struct sta_info *sta)
|
||||
static u32 __mesh_plink_deactivate(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
bool deactivated = false;
|
||||
u32 changed = 0;
|
||||
|
||||
if (sta->plink_state == NL80211_PLINK_ESTAB) {
|
||||
mesh_plink_dec_estab_count(sdata);
|
||||
deactivated = true;
|
||||
}
|
||||
if (sta->plink_state == NL80211_PLINK_ESTAB)
|
||||
changed = mesh_plink_dec_estab_count(sdata);
|
||||
sta->plink_state = NL80211_PLINK_BLOCKED;
|
||||
mesh_path_flush_by_nexthop(sta);
|
||||
|
||||
return deactivated;
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,18 +197,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta)
|
||||
void mesh_plink_deactivate(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
bool deactivated;
|
||||
u32 changed;
|
||||
|
||||
spin_lock_bh(&sta->lock);
|
||||
deactivated = __mesh_plink_deactivate(sta);
|
||||
changed = __mesh_plink_deactivate(sta);
|
||||
sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
|
||||
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
|
||||
sta->sta.addr, sta->llid, sta->plid,
|
||||
sta->reason);
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
if (deactivated)
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
|
||||
static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
|
||||
@ -541,15 +539,14 @@ int mesh_plink_open(struct sta_info *sta)
|
||||
void mesh_plink_block(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
bool deactivated;
|
||||
u32 changed;
|
||||
|
||||
spin_lock_bh(&sta->lock);
|
||||
deactivated = __mesh_plink_deactivate(sta);
|
||||
changed = __mesh_plink_deactivate(sta);
|
||||
sta->plink_state = NL80211_PLINK_BLOCKED;
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
if (deactivated)
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
|
||||
|
||||
@ -852,9 +849,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
||||
del_timer(&sta->plink_timer);
|
||||
sta->plink_state = NL80211_PLINK_ESTAB;
|
||||
spin_unlock_bh(&sta->lock);
|
||||
mesh_plink_inc_estab_count(sdata);
|
||||
changed |= mesh_plink_inc_estab_count(sdata);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
|
||||
sta->sta.addr);
|
||||
break;
|
||||
@ -888,9 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
||||
del_timer(&sta->plink_timer);
|
||||
sta->plink_state = NL80211_PLINK_ESTAB;
|
||||
spin_unlock_bh(&sta->lock);
|
||||
mesh_plink_inc_estab_count(sdata);
|
||||
changed |= mesh_plink_inc_estab_count(sdata);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
|
||||
sta->sta.addr);
|
||||
mesh_plink_frame_tx(sdata,
|
||||
@ -908,13 +903,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
|
||||
case CLS_ACPT:
|
||||
reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
|
||||
sta->reason = reason;
|
||||
__mesh_plink_deactivate(sta);
|
||||
changed |= __mesh_plink_deactivate(sta);
|
||||
sta->plink_state = NL80211_PLINK_HOLDING;
|
||||
llid = sta->llid;
|
||||
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
|
||||
spin_unlock_bh(&sta->lock);
|
||||
changed |= mesh_set_ht_prot_mode(sdata);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
|
||||
sta->sta.addr, llid, plid, reason);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user