diff options
author | David S. Miller <davem@davemloft.net> | 2014-03-31 16:44:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-31 16:44:55 -0400 |
commit | ce22bb6122e849e0d3a6857d03eb69a25bfdc6e9 (patch) | |
tree | 8574d13b4cde10074fb83b0902f261d473ad0939 | |
parent | 43a43b6040165f7b40b5b489fe61a4cb7f8c4980 (diff) | |
parent | 96da266e77637ae892b196f377908c51fa9f2d1a (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says:
====================
pull request: wireless-next 2014-03-31
Please accept this one last round of general wireless updates for
the 3.15 merge window!
For the Bluetooth bits, Gustavo says:
"Here follow another set of patches to 3.15. This is mostly a bug fix
pull request with the exception of one commit from Marcel which adds
tracking to the current configured LE scan type parameter."
Beyond that, notable bits include some final refactoring of rtl8180
and the addition of the rtl8187se driver, fixes for a number of
problems identified by Dan Carpenter and his static analysis tools,
and a handful of other bits here and there.
Please let me know if there are problems!
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
49 files changed, 1805 insertions, 395 deletions
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 25f9887a35d0..d7f81ad56b8a 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -218,7 +218,14 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) #if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) chip->to_irq = bcma_gpio_to_irq; #endif - chip->ngpio = 16; + switch (cc->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM5357: + chip->ngpio = 32; + break; + default: + chip->ngpio = 16; + } + /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get * a random base number. */ diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index a9a989e5ee88..dfa5043e68ba 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -901,7 +901,7 @@ static void bluecard_release(struct pcmcia_device *link) bluecard_close(info); - del_timer(&(info->timer)); + del_timer_sync(&(info->timer)); pcmcia_disable_device(link); } diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 1e0320af00c6..2c4997ce2484 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -59,12 +59,13 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) priv->btmrvl_dev.sendcmdflag = false; priv->adapter->cmd_complete = true; wake_up_interruptible(&priv->adapter->cmd_wait_q); - } - if (hci_opcode_ogf(opcode) == 0x3F) { - BT_DBG("vendor event skipped: opcode=%#4.4x", opcode); - kfree_skb(skb); - return false; + if (hci_opcode_ogf(opcode) == 0x3F) { + BT_DBG("vendor event skipped: opcode=%#4.4x", + opcode); + kfree_skb(skb); + return false; + } } } diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 536bc46a2912..924135b8e575 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -572,7 +572,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) { - struct ieee80211_bar *bar = (void *) data; + struct ieee80211_bar *bar = data; struct carl9170_bar_list_entry *entry; unsigned int queue; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index e0e649aab8db..afb3d15e38ff 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1354,13 +1354,14 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, } static s32 -brcmf_set_set_cipher(struct net_device *ndev, - struct cfg80211_connect_params *sme) +brcmf_set_wsec_mode(struct net_device *ndev, + struct cfg80211_connect_params *sme, bool mfp) { struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; s32 pval = 0; s32 gval = 0; + s32 wsec; s32 err = 0; if (sme->crypto.n_ciphers_pairwise) { @@ -1412,7 +1413,12 @@ brcmf_set_set_cipher(struct net_device *ndev, if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval && sme->privacy) pval = AES_ENABLED; - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", pval | gval); + + if (mfp) + wsec = pval | gval | MFP_CAPABLE; + else + wsec = pval | gval; + err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec); if (err) { brcmf_err("error (%d)\n", err); return err; @@ -1582,7 +1588,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, u32 ie_len; struct brcmf_ext_join_params_le *ext_join_params; u16 chanspec; - s32 err = 0; brcmf_dbg(TRACE, "Enter\n"); @@ -1651,7 +1656,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - err = brcmf_set_set_cipher(ndev, sme); + err = brcmf_set_wsec_mode(ndev, sme, sme->mfp == NL80211_MFP_REQUIRED); if (err) { brcmf_err("wl_set_set_cipher failed (%d)\n", err); goto done; diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index 7ca2aa1035b2..74419d4bd123 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h @@ -217,6 +217,9 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WSEC_SWFLAG 0x0008 /* to go into transition mode without setting wep */ #define SES_OW_ENABLED 0x0040 +/* MFP */ +#define MFP_CAPABLE 0x0200 +#define MFP_REQUIRED 0x0400 /* WPA authentication mode bitvec */ #define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index b41155829220..1062c918a7bf 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -277,11 +277,11 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + adapter->seq_num++; sleep_cfm_buf->seq_num = cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO (adapter->seq_num, priv->bss_num, priv->bss_type))); - adapter->seq_num++; if (adapter->iface_type == MWIFIEX_USB) { sleep_cfm_tmp = @@ -509,6 +509,11 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, return -1; } + if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) { + dev_err(adapter->dev, "PREP_CMD: host entering sleep state\n"); + return -1; + } + if (adapter->surprise_removed) { dev_err(adapter->dev, "PREP_CMD: card is removed\n"); return -1; @@ -976,11 +981,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) struct mwifiex_private *priv; int i; + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); /* Cancel current cmd */ if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->curr_cmd->wait_q_enabled = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); adapter->cmd_wait_q.status = -1; mwifiex_complete_cmd(adapter, adapter->curr_cmd); } @@ -1000,6 +1004,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); } spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); /* Cancel all pending scan command */ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 7b4502fefec3..77db0886c6e2 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -38,7 +38,8 @@ static void scan_delay_timer_fn(unsigned long data) if (adapter->surprise_removed) return; - if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { + if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT || + !adapter->scan_processing) { /* * Abort scan operation by cancelling all pending scan * commands diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index a67f7da12b30..d53e1e8c9467 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -774,6 +774,7 @@ struct mwifiex_adapter { u16 hs_activate_wait_q_woken; wait_queue_head_t hs_activate_wait_q; bool is_suspended; + bool hs_enabling; u8 event_body[MAX_EVENT_SIZE]; u32 hw_dot_11n_dev_cap; u8 hw_dev_mcs_support; diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 57c353a94b29..a7e8b96b2d90 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -120,6 +120,7 @@ static int mwifiex_pcie_suspend(struct device *dev) /* Indicate device suspended */ adapter->is_suspended = true; + adapter->hs_enabling = false; return 0; } @@ -1033,7 +1034,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) card->tx_buf_list[wrdoneidx] = NULL; if (reg->pfu_enabled) { - desc2 = (void *)card->txbd_ring[wrdoneidx]; + desc2 = card->txbd_ring[wrdoneidx]; memset(desc2, 0, sizeof(*desc2)); } else { desc = card->txbd_ring[wrdoneidx]; @@ -1118,7 +1119,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, card->tx_buf_list[wrindx] = skb; if (reg->pfu_enabled) { - desc2 = (void *)card->txbd_ring[wrindx]; + desc2 = card->txbd_ring[wrindx]; desc2->paddr = buf_pa; desc2->len = (u16)skb->len; desc2->frag_len = (u16)skb->len; @@ -1278,7 +1279,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) card->rx_buf_list[rd_index] = skb_tmp; if (reg->pfu_enabled) { - desc2 = (void *)card->rxbd_ring[rd_index]; + desc2 = card->rxbd_ring[rd_index]; desc2->paddr = buf_pa; desc2->len = skb_tmp->len; desc2->frag_len = skb_tmp->len; diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index f13924447a2c..7b3af3d29ded 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -591,10 +591,12 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, *chan_tlv_out, struct mwifiex_chan_scan_param_set *scan_chan_list) { + struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct mwifiex_chan_scan_param_set *tmp_chan_list; struct mwifiex_chan_scan_param_set *start_chan; - + struct cmd_ctrl_node *cmd_node, *tmp_node; + unsigned long flags; u32 tlv_idx, rates_size, cmd_no; u32 total_scan_time; u32 done_early; @@ -748,8 +750,19 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, scan_cfg_out->tlv_buf_len -= sizeof(struct mwifiex_ie_types_header) + rates_size; - if (ret) + if (ret) { + 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); break; + } } if (ret) @@ -1653,7 +1666,7 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, curr_bcn_bytes -= ETH_ALEN; if (!ext_scan) { - rssi = (s32) *(u8 *)current_ptr; + rssi = (s32) *current_ptr; rssi = (-rssi) * 100; /* Convert dBm to mBm */ current_ptr += sizeof(u8); curr_bcn_bytes -= sizeof(u8); diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index e0dcd3ed7a69..d206f04d4994 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -237,6 +237,7 @@ static int mwifiex_sdio_suspend(struct device *dev) /* Enable the Host Sleep */ if (!mwifiex_enable_hs(adapter)) { dev_err(adapter->dev, "cmd: failed to suspend\n"); + adapter->hs_enabling = false; return -EFAULT; } @@ -245,6 +246,7 @@ static int mwifiex_sdio_suspend(struct device *dev) /* Indicate device suspended */ adapter->is_suspended = true; + adapter->hs_enabling = false; return ret; } diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 33170af150f6..894270611f2c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -64,6 +64,7 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, *(cmd_queued->condition)); if (status) { dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); + mwifiex_cancel_all_pending_cmd(adapter); return status; } @@ -508,6 +509,9 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); hscfg.is_invoke_hostcmd = true; + adapter->hs_enabling = true; + mwifiex_cancel_all_pending_cmd(adapter); + if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, @@ -516,8 +520,9 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return false; } - if (wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken)) { + if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken, + (10 * HZ)) <= 0) { dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); return false; } diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index 8cec6e4ba8c4..97662a1ba58c 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c @@ -730,13 +730,13 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, if (len < (sizeof(struct ethhdr) + 3)) return; - if (*(u8 *)(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE) + if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE) return; - if (*(u8 *)(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS) + if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS) return; peer = buf + ETH_ALEN; - action = *(u8 *)(buf + sizeof(struct ethhdr) + 2); + action = *(buf + sizeof(struct ethhdr) + 2); /* just handle TDLS setup request/response/confirm */ if (action > WLAN_TDLS_SETUP_CONFIRM) diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index ae30c390ebd3..edbe4aff00d8 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -459,6 +459,7 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) * 'suspended' state and a 'disconnect' one. */ adapter->is_suspended = true; + adapter->hs_enabling = false; if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) usb_kill_urb(card->rx_cmd.urb); diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index ef37d4b27bd4..2361a6849ad7 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -1292,10 +1292,11 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg) return -EINVAL; } } else if (msg_type == TX_STATUS_IND) { - if (msg[15] == PROBEREQ_CONFIRM) + if (msg[15] == PROBEREQ_CONFIRM) { common->mgmt_q_block = false; rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n", __func__); + } } else { return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type); } diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig index 30332175bcd8..1ce1d55f0010 100644 --- a/drivers/net/wireless/rtl818x/Kconfig +++ b/drivers/net/wireless/rtl818x/Kconfig @@ -2,11 +2,11 @@ # RTL818X Wireless LAN device configuration # config RTL8180 - tristate "Realtek 8180/8185 PCI support" + tristate "Realtek 8180/8185/8187SE PCI support" depends on MAC80211 && PCI select EEPROM_93CX6 ---help--- - This is a driver for RTL8180 and RTL8185 based cards. + This is a driver for RTL8180, RTL8185 and RTL8187SE based cards. These are PCI based chips found in cards such as: (RTL8185 802.11g) diff --git a/drivers/net/wireless/rtl818x/rtl8180/Makefile b/drivers/net/wireless/rtl818x/rtl8180/Makefile index cb4fb8596f0b..08b056db4a3b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/Makefile +++ b/drivers/net/wireless/rtl818x/rtl8180/Makefile @@ -1,4 +1,4 @@ -rtl8180-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o +rtl8180-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o obj-$(CONFIG_RTL8180) += rtl8180.o diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 0b405b8c8d70..98d8256f0377 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -1,15 +1,42 @@ -/* - * Linux device driver for RTL8180 / RTL8185 +/* Linux device driver for RTL8180 / RTL8185 / RTL8187SE * * Copyright 2007 Michael Wu <flamingice@sourmilk.net> - * Copyright 2007 Andrea Merello <andrea.merello@gmail.com> + * Copyright 2007,2014 Andrea Merello <andrea.merello@gmail.com> * * Based on the r8180 driver, which is: * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. * * Thanks to Realtek for their support! * + ************************************************************************ + * + * The driver was extended to the RTL8187SE in 2014 by + * Andrea Merello <andrea.merello@gmail.com> + * + * based also on: + * - portions of rtl8187se Linux staging driver, Copyright Realtek corp. + * - other GPL, unpublished (until now), Linux driver code, + * Copyright Larry Finger <Larry.Finger@lwfinger.net> + * + * A huge thanks goes to Sara V. Nari who forgives me when I'm + * sitting in front of my laptop at evening, week-end, night... + * + * A special thanks goes to Antonio Cuni, who helped me with + * some python userspace stuff I used to debug RTL8187SE code, and who + * bought a laptop with an unsupported Wi-Fi card some years ago... + * + * Thanks to Larry Finger for writing some code for rtl8187se and for + * his suggestions. + * + * Thanks to Dan Carpenter for reviewing my initial patch and for his + * suggestions. + * + * Thanks to Bernhard Schiffner for his help in testing and for his + * suggestions. + * + ************************************************************************ + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -29,13 +56,18 @@ #include "sa2400.h" #include "max2820.h" #include "grf5101.h" +#include "rtl8225se.h" MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>"); -MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver"); +MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver"); MODULE_LICENSE("GPL"); static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { + + /* rtl8187se */ + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) }, + /* rtl8185 */ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, @@ -85,6 +117,76 @@ static const struct ieee80211_channel rtl818x_channels[] = { { .center_freq = 2484 }, }; +/* Queues for rtl8187se card + * + * name | reg | queue + * BC | 7 | 6 + * MG | 1 | 0 + * HI | 6 | 1 + * VO | 5 | 2 + * VI | 4 | 3 + * BE | 3 | 4 + * BK | 2 | 5 + * + * The complete map for DMA kick reg using use all queue is: + * static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = + * {1, 6, 5, 4, 3, 2, 7}; + * + * .. but.. Because for mac80211 4 queues are enough for QoS we use this + * + * name | reg | queue + * BC | 7 | 4 <- currently not used yet + * MG | 1 | x <- Not used + * HI | 6 | x <- Not used + * VO | 5 | 0 <- used + * VI | 4 | 1 <- used + * BE | 3 | 2 <- used + * BK | 2 | 3 <- used + * + * Beacon queue could be used, but this is not finished yet. + * + * I thougth about using the other two queues but I decided not to do this: + * + * - I'm unsure whether the mac80211 will ever try to use more than 4 queues + * by itself. + * + * - I could route MGMT frames (currently sent over VO queue) to the MGMT + * queue but since mac80211 will do not know about it, I will probably gain + * some HW priority whenever the VO queue is not empty, but this gain is + * limited by the fact that I had to stop the mac80211 queue whenever one of + * the VO or MGMT queues is full, stopping also submitting of MGMT frame + * to the driver. + * + * - I don't know how to set in the HW the contention window params for MGMT + * and HI-prio queues. + */ + +static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = {5, 4, 3, 2, 7}; + +/* Queues for rtl8180/rtl8185 cards + * + * name | reg | prio + * BC | 7 | 3 + * HI | 6 | 0 + * NO | 5 | 1 + * LO | 4 | 2 + * + * The complete map for DMA kick reg using all queue is: + * static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {6, 5, 4, 7}; + * + * .. but .. Because the mac80211 needs at least 4 queues for QoS or + * otherwise QoS can't be done, we use just one. + * Beacon queue could be used, but this is not finished yet. + * Actual map is: + * + * name | reg | prio + * BC | 7 | 1 <- currently not used yet. + * HI | 6 | x <- not used + * NO | 5 | x <- not used + * LO | 4 | 0 <- used + */ + +static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {4, 7}; void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) { @@ -105,14 +207,30 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) static void rtl8180_handle_rx(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; + struct rtl818x_rx_cmd_desc *cmd_desc; unsigned int count = 32; u8 signal, agc, sq; dma_addr_t mapping; while (count--) { - struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; + void *entry = priv->rx_ring + priv->rx_idx * priv->rx_ring_sz; struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; - u32 flags = le32_to_cpu(entry->flags); + u32 flags, flags2; + u64 tsft; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + struct rtl8187se_rx_desc *desc = entry; + + flags = le32_to_cpu(desc->flags); + flags2 = le32_to_cpu(desc->flags2); + tsft = le64_to_cpu(desc->tsft); + } else { + struct rtl8180_rx_desc *desc = entry; + + flags = le32_to_cpu(desc->flags); + flags2 = le32_to_cpu(desc->flags2); + tsft = le64_to_cpu(desc->tsft); + } if (flags & RTL818X_RX_DESC_FLAG_OWN) return; @@ -122,7 +240,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) RTL818X_RX_DESC_FLAG_RX_ERR))) goto done; else { - u32 flags2 = le32_to_cpu(entry->flags2); struct ieee80211_rx_status rx_status = {0}; struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE); @@ -154,14 +271,18 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) signal = 90 - clamp_t(u8, agc, 25, 90); else signal = 95 - clamp_t(u8, agc, 30, 95); - } else { + } else if (priv->chip_family == + RTL818X_CHIP_FAMILY_RTL8180) { sq = flags2 & 0xff; signal = priv->rf->calc_rssi(agc, sq); + } else { + /* TODO: rtl8187se rssi */ + signal = 10; } rx_status.signal = signal; rx_status.freq = dev->conf.chandef.chan->center_freq; rx_status.band = dev->conf.chandef.chan->band; - rx_status.mactime = le64_to_cpu(entry->tsft); + rx_status.mactime = tsft; rx_status.flag |= RX_FLAG_MACTIME_START; if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; @@ -175,11 +296,13 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) } done: - entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb)); - entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | + cmd_desc = entry; + cmd_desc->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb)); + cmd_desc->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | MAX_RX_SIZE); if (priv->rx_idx == 31) - entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); + cmd_desc->flags |= + cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); priv->rx_idx = (priv->rx_idx + 1) % 32; } } @@ -219,6 +342,55 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) } } +static irqreturn_t rtl8187se_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *dev = dev_id; + struct rtl8180_priv *priv = dev->priv; + u32 reg; + unsigned long flags; + static int desc_err; + + spin_lock_irqsave(&priv->lock, flags); + /* Note: 32-bit interrupt status */ + reg = rtl818x_ioread32(priv, &priv->map->INT_STATUS_SE); + if (unlikely(reg == 0xFFFFFFFF)) { + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + } + + rtl818x_iowrite32(priv, &priv->map->INT_STATUS_SE, reg); + + if (reg & IMR_TIMEOUT1) + rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); + + if (reg & (IMR_TBDOK | IMR_TBDER)) + rtl8180_handle_tx(dev, 4); + + if (reg & (IMR_TVODOK | IMR_TVODER)) + rtl8180_handle_tx(dev, 0); + + if (reg & (IMR_TVIDOK | IMR_TVIDER)) + rtl8180_handle_tx(dev, 1); + + if (reg & (IMR_TBEDOK | IMR_TBEDER)) + rtl8180_handle_tx(dev, 2); + + if (reg & (IMR_TBKDOK | IMR_TBKDER)) + rtl8180_handle_tx(dev, 3); + + if (reg & (IMR_ROK | IMR_RER | RTL818X_INT_SE_RX_DU | IMR_RQOSOK)) + rtl8180_handle_rx(dev); + /* The interface sometimes generates several RX DMA descriptor errors + * at startup. Do not report these. + */ + if ((reg & RTL818X_INT_SE_RX_DU) && desc_err++ > 2) + if (net_ratelimit()) + wiphy_err(dev->wiphy, "No RX DMA Descriptor avail\n"); + + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; +} + static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) { struct ieee80211_hw *dev = dev_id; @@ -235,12 +407,6 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) - rtl8180_handle_tx(dev, 3); - - if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) - rtl8180_handle_tx(dev, 2); - - if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) rtl8180_handle_tx(dev, 1); if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) @@ -264,12 +430,14 @@ static void rtl8180_tx(struct ieee80211_hw *dev, struct rtl8180_tx_ring *ring; struct rtl8180_tx_desc *entry; unsigned long flags; - unsigned int idx, prio; + unsigned int idx, prio, hw_prio; dma_addr_t mapping; u32 tx_flags; u8 rc_flags; u16 plcp_len = 0; __le16 rts_duration = 0; + /* do arithmetic and then convert to le16 */ + u16 frame_duration = 0; prio = skb_get_queue_mapping(skb); ring = &priv->tx_ring[prio]; @@ -281,7 +449,6 @@ static void rtl8180_tx(struct ieee80211_hw *dev, kfree_skb(skb); dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); return; - } tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | @@ -317,6 +484,18 @@ static void rtl8180_tx(struct ieee80211_hw *dev, plcp_len |= 1 << 15; } + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + __le16 duration; + /* SIFS time (required by HW) is already included by + * ieee80211_generic_frame_duration + */ + duration = ieee80211_generic_frame_duration(dev, priv->vif, + IEEE80211_BAND_2GHZ, skb->len, + ieee80211_get_tx_rate(dev, info)); + + frame_duration = priv->ack_time + le16_to_cpu(duration); + } + spin_lock_irqsave(&priv->lock, flags); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -329,10 +508,19 @@ static void rtl8180_tx(struct ieee80211_hw *dev, idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; entry = &ring->desc[idx]; + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + entry->frame_duration = cpu_to_le16(frame_duration); + entry->frame_len_se = cpu_to_le16(skb->len); + + /* tpc polarity */ + entry->flags3 = cpu_to_le16(1<<4); + } else + entry->frame_len = cpu_to_le32(skb->len); + entry->rts_duration = rts_duration; entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); - entry->frame_len = cpu_to_le32(skb->len); + entry->flags2 = info->control.rates[1].idx >= 0 ? ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; entry->retry_limit = info->control.rates[0].count; @@ -354,7 +542,57 @@ static void rtl8180_tx(struct ieee80211_hw *dev, spin_unlock_irqrestore(&priv->lock, flags); - rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + /* just poll: rings are stopped with TPPollStop reg */ + hw_prio = rtl8187se_queues_map[prio]; + rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, + (1 << hw_prio)); + } else { + hw_prio = rtl8180_queues_map[prio]; + rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, + (1 << hw_prio) | /* ring to poll */ + (1<<1) | (1<<2));/* stopped rings */ + } +} + +static void rtl8180_set_anaparam3(struct rtl8180_priv *priv, u16 anaparam3) +{ + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite16(priv, &priv->map->ANAPARAM3, anaparam3); + + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + +void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2) +{ + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); + + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); } void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) @@ -371,6 +609,105 @@ void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); } +static void rtl8187se_mac_config(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u8 reg; + + rtl818x_iowrite32(priv, REG_ADDR4(0x1F0), 0); + rtl818x_ioread32(priv, REG_ADDR4(0x1F0)); + rtl818x_iowrite32(priv, REG_ADDR4(0x1F4), 0); + rtl818x_ioread32(priv, REG_ADDR4(0x1F4)); + rtl818x_iowrite8(priv, REG_ADDR1(0x1F8), 0); + rtl818x_ioread8(priv, REG_ADDR1(0x1F8)); + /* Enable DA10 TX power saving */ + reg = rtl818x_ioread8(priv, &priv->map->PHY_PR); + rtl818x_iowrite8(priv, &priv->map->PHY_PR, reg | 0x04); + /* Power */ + rtl818x_iowrite16(priv, PI_DATA_REG, 0x1000); + rtl818x_iowrite16(priv, SI_DATA_REG, 0x1000); + /* AFE - default to power ON */ + rtl818x_iowrite16(priv, REG_ADDR2(0x370), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x372), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x374), 0x0DA4); + rtl818x_iowrite16(priv, REG_ADDR2(0x376), 0x0DA4); + rtl818x_iowrite16(priv, REG_ADDR2(0x378), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x37A), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x37C), 0x00EC); + rtl818x_iowrite16(priv, REG_ADDR2(0x37E), 0x00EC); + rtl818x_iowrite8(priv, REG_ADDR1(0x24E), 0x01); + /* unknown, needed for suspend to RAM resume */ + rtl818x_iowrite8(priv, REG_ADDR1(0x0A), 0x72); +} + +static void rtl8187se_set_antenna_config(struct ieee80211_hw *dev, u8 def_ant, + bool diversity) +{ + struct rtl8180_priv *priv = dev->priv; + + rtl8225_write_phy_cck(dev, 0x0C, 0x09); + if (diversity) { + if (def_ant == 1) { + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); + rtl8225_write_phy_cck(dev, 0x11, 0xBB); + rtl8225_write_phy_cck(dev, 0x01, 0xC7); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); + rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); + } else { /* main antenna */ + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225_write_phy_cck(dev, 0x11, 0x9B); + rtl8225_write_phy_cck(dev, 0x01, 0xC7); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); + rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); + } + } else { /* disable antenna diversity */ + if (def_ant == 1) { + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); + rtl8225_write_phy_cck(dev, 0x11, 0xBB); + rtl8225_write_phy_cck(dev, 0x01, 0x47); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); + rtl8225_write_phy_ofdm(dev, 0x18, 0x32); + } else { /* main antenna */ + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225_write_phy_cck(dev, 0x11, 0x9B); + rtl8225_write_phy_cck(dev, 0x01, 0x47); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); + rtl8225_write_phy_ofdm(dev, 0x18, 0x32); + } + } + /* priv->curr_ant = def_ant; */ +} + +static void rtl8180_int_enable(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->IMR, IMR_TMGDOK | + IMR_TBDER | IMR_THPDER | + IMR_THPDER | IMR_THPDOK | + IMR_TVODER | IMR_TVODOK | + IMR_TVIDER | IMR_TVIDOK | + IMR_TBEDER | IMR_TBEDOK | + IMR_TBKDER | IMR_TBKDOK | + IMR_RDU | IMR_RER | + IMR_ROK | IMR_RQOSOK); + } else { + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + } +} + +static void rtl8180_int_disable(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->IMR, 0); + } else { + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + } +} + static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, u32 rates_mask) { @@ -390,7 +727,6 @@ static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, reg &= ~3; reg |= max; rtl818x_iowrite16(priv, &priv->map->BRSR, reg); - break; case RTL818X_CHIP_FAMILY_RTL8185: @@ -398,20 +734,46 @@ static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, rtl818x_iowrite16(priv, &priv->map->BRSR, rates_mask); rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (max << 4) | min); break; + + case RTL818X_CHIP_FAMILY_RTL8187SE: + /* in 8187se this is a BITMAP */ + rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, rates_mask); + break; + } +} + +static void rtl8180_config_cardbus(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg16; + u8 reg8; + + reg8 = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg8 |= 1 << 1; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg8); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite16(priv, FEMR_SE, 0xffff); + } else { + reg16 = rtl818x_ioread16(priv, &priv->map->FEMR); + reg16 |= (1 << 15) | (1 << 14) | (1 << 4); + rtl818x_iowrite16(priv, &priv->map->FEMR, reg16); } + } static int rtl8180_init_hw(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; u16 reg; + u32 reg32; rtl818x_iowrite8(priv, &priv->map->CMD, 0); rtl818x_ioread8(priv, &priv->map->CMD); msleep(10); /* reset */ - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + rtl8180_int_disable(dev); rtl818x_ioread8(priv, &priv->map->CMD); reg = rtl818x_ioread8(priv, &priv->map->CMD); @@ -432,25 +794,39 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) msleep(200); if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) { - /* For cardbus */ - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= 1 << 1; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - reg = rtl818x_ioread16(priv, &priv->map->FEMR); - reg |= (1 << 15) | (1 << 14) | (1 << 4); - rtl818x_iowrite16(priv, &priv->map->FEMR, reg); + rtl8180_config_cardbus(dev); } - rtl818x_iowrite8(priv, &priv->map->MSR, 0); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); + else + rtl818x_iowrite8(priv, &priv->map->MSR, 0); if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) rtl8180_set_anaparam(priv, priv->anaparam); rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); - rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma); - rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma); - rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); + /* mac80211 queue have higher prio for lower index. The last queue + * (that mac80211 is not aware of) is reserved for beacons (and have + * the highest priority on the NIC) + */ + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->TBDA, + priv->tx_ring[1].dma); + rtl818x_iowrite32(priv, &priv->map->TLPDA, + priv->tx_ring[0].dma); + } else { + rtl818x_iowrite32(priv, &priv->map->TBDA, + priv->tx_ring[4].dma); + rtl818x_iowrite32(priv, &priv->map->TVODA, + priv->tx_ring[0].dma); + rtl818x_iowrite32(priv, &priv->map->TVIDA, + priv->tx_ring[1].dma); + rtl818x_iowrite32(priv, &priv->map->TBEDA, + priv->tx_ring[2].dma); + rtl818x_iowrite32(priv, &priv->map->TBKDA, + priv->tx_ring[3].dma); + } /* TODO: necessary? specs indicate not */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); @@ -471,7 +847,14 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); + } else { + rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); + rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); + rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { /* TODO: set ClkRun enable? necessary? */ reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6)); @@ -479,11 +862,55 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - } else { - rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); + } - rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + + /* the set auto rate fallback bitmask from 1M to 54 Mb/s */ + rtl818x_iowrite16(priv, ARFR, 0xFFF); + rtl818x_ioread16(priv, ARFR); + + /* stop unused queus (no dma alloc) */ + rtl818x_iowrite8(priv, &priv->map->TPPOLL_STOP, + RTL818x_TPPOLL_STOP_MG | RTL818x_TPPOLL_STOP_HI); + + rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0x00); + rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); + + rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); + + /* some black magic here.. */ + rtl8187se_mac_config(dev); + + rtl818x_iowrite16(priv, RFSW_CTRL, 0x569A); + rtl818x_ioread16(priv, RFSW_CTRL); + + rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_ON); + rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_ON); + rtl8180_set_anaparam3(priv, RTL8225SE_ANAPARAM3); + + + rtl818x_iowrite8(priv, &priv->map->CONFIG5, + rtl818x_ioread8(priv, &priv->map->CONFIG5) & 0x7F); + + /*probably this switch led on */ + rtl818x_iowrite8(priv, &priv->map->PGSELECT, + rtl818x_ioread8(priv, &priv->map->PGSELECT) | 0x08); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1BFF); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x4003); + + /* the reference code mac hardcode table write + * this reg by doing byte-wide accesses. + * It does it just for lowest and highest byte.. + */ + reg32 = rtl818x_ioread32(priv, &priv->map->RF_PARA); + reg32 &= 0x00ffff00; + reg32 |= 0xb8000054; + rtl818x_iowrite32(priv, &priv->map->RF_PARA, reg32); } priv->rf->init(dev); @@ -499,17 +926,26 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev) else rtl8180_conf_basic_rates(dev, 0x1f3); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl8187se_set_antenna_config(dev, + priv->antenna_diversity_default, + priv->antenna_diversity_en); return 0; } static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; - struct rtl8180_rx_desc *entry; + struct rtl818x_rx_cmd_desc *entry; int i; + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + priv->rx_ring_sz = sizeof(struct rtl8187se_rx_desc); + else + priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); + priv->rx_ring = pci_alloc_consistent(priv->pdev, - sizeof(*priv->rx_ring) * 32, + priv->rx_ring_sz * 32, &priv->rx_ring_dma); if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { @@ -517,13 +953,13 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) return -ENOMEM; } - memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * 32); + memset(priv->rx_ring, 0, priv->rx_ring_sz * 32); priv->rx_idx = 0; for (i = 0; i < 32; i++) { struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE); dma_addr_t *mapping; - entry = &priv->rx_ring[i]; + entry = priv->rx_ring + priv->rx_ring_sz*i; if (!skb) { wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); return -ENOMEM; @@ -563,7 +999,7 @@ static void rtl8180_free_rx_ring(struct ieee80211_hw *dev) kfree_skb(skb); } - pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * 32, + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, priv->rx_ring, priv->rx_ring_dma); priv->rx_ring = NULL; } @@ -627,7 +1063,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) if (ret) return ret; - for (i = 0; i < 4; i++) + for (i = 0; i < (dev->queues + 1); i++) if ((ret = rtl8180_init_tx_ring(dev, i, 16))) goto err_free_rings; @@ -635,23 +1071,28 @@ static int rtl8180_start(struct ieee80211_hw *dev) if (ret) goto err_free_rings; - rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); - rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma); - rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma); - rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); - - ret = request_irq(priv->pdev->irq, rtl8180_interrupt, + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + ret = request_irq(priv->pdev->irq, rtl8187se_interrupt, IRQF_SHARED, KBUILD_MODNAME, dev); + } else { + ret = request_irq(priv->pdev->irq, rtl8180_interrupt, + IRQF_SHARED, KBUILD_MODNAME, dev); + } + if (ret) { wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); goto err_free_rings; } - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + rtl8180_int_enable(dev); - rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); - rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + /* in rtl8187se at MAR regs offset there is the management + * TX descriptor DMA addres.. + */ + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); + rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + } reg = RTL818X_RX_CONF_ONLYERLPKT | RTL818X_RX_CONF_RX_AUTORESETPHY | @@ -663,11 +1104,13 @@ static int rtl8180_start(struct ieee80211_hw *dev) if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; - else { + else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) ? RTL818X_RX_CONF_CSDM1 : 0; reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2) ? RTL818X_RX_CONF_CSDM2 : 0; + } else { + reg &= ~(RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2); } priv->rx_conf = reg; @@ -678,6 +1121,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) /* CW is not on per-packet basis. * in rtl8185 the CW_VALUE reg is used. + * in rtl8187se the AC param regs are used. */ reg &= ~RTL818X_CW_CONF_PERPACKET_CW; /* retry limit IS on per-packet basis. @@ -705,7 +1149,8 @@ static int rtl8180_start(struct ieee80211_hw *dev) reg |= (6 << 21 /* MAX TX DMA */) | RTL818X_TX_CONF_NO_ICV; - + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + reg |= 1<<30; /* "duration procedure mode" */ if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) reg &= ~RTL818X_TX_CONF_PROBE_DTS; @@ -728,7 +1173,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) err_free_rings: rtl8180_free_rx_ring(dev); - for (i = 0; i < 4; i++) + for (i = 0; i < (dev->queues + 1); i++) if (priv->tx_ring[i].desc) rtl8180_free_tx_ring(dev, i); @@ -741,7 +1186,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) u8 reg; int i; - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + rtl8180_int_disable(dev); reg = rtl818x_ioread8(priv, &priv->map->CMD); reg &= ~RTL818X_CMD_TX_ENABLE; @@ -758,7 +1203,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) free_irq(priv->pdev->irq, dev); rtl8180_free_rx_ring(dev); - for (i = 0; i < 4; i++) + for (i = 0; i < (dev->queues + 1); i++) rtl8180_free_tx_ring(dev, i); } @@ -866,6 +1311,49 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) return 0; } +static void rtl8187se_conf_ac_parm(struct ieee80211_hw *dev, u8 queue) +{ + const struct ieee80211_tx_queue_params *params; + struct rtl8180_priv *priv = dev->priv; + + /* hw value */ + u32 ac_param; + + u8 aifs; + u8 txop; + u8 cw_min, cw_max; + + params = &priv->queue_param[queue]; + + cw_min = fls(params->cw_min); + cw_max = fls(params->cw_max); + + aifs = 10 + params->aifs * priv->slot_time; + + /* TODO: check if txop HW is in us (mult by 32) */ + txop = params->txop; + + ac_param = txop << AC_PARAM_TXOP_LIMIT_SHIFT | + cw_max << AC_PARAM_ECW_MAX_SHIFT | + cw_min << AC_PARAM_ECW_MIN_SHIFT | + aifs << AC_PARAM_AIFS_SHIFT; + + switch (queue) { + case IEEE80211_AC_BK: + rtl818x_iowrite32(priv, &priv->map->AC_BK_PARAM, ac_param); + break; + case IEEE80211_AC_BE: + rtl818x_iowrite32(priv, &priv->map->AC_BE_PARAM, ac_param); + break; + case IEEE80211_AC_VI: + rtl818x_iowrite32(priv, &priv->map->AC_VI_PARAM, ac_param); + break; + case IEEE80211_AC_VO: + rtl818x_iowrite32(priv, &priv->map->AC_VO_PARAM, ac_param); + break; + } +} + static int rtl8180_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) @@ -880,8 +1368,12 @@ static int rtl8180_conf_tx(struct ieee80211_hw *dev, cw_min = fls(params->cw_min); cw_max = fls(params->cw_max); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, (cw_max << 4) | cw_min); - + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + priv->queue_param[queue] = *params; + rtl8187se_conf_ac_parm(dev, queue); + } else + rtl818x_iowrite8(priv, &priv->map->CW_VAL, + (cw_max << 4) | cw_min); return 0; } @@ -923,13 +1415,17 @@ static void rtl8180_conf_erp(struct ieee80211_hw *dev, /* from reference code. set ack timeout reg = eifs reg */ rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, hw_eifs); - /* rtl8187/rtl8185 HW bug. After EIFS is elapsed, - * the HW still wait for DIFS. - * HW uses 4uS units for EIFS. - */ - hw_eifs = DIV_ROUND_UP(eifs - difs, 4); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl818x_iowrite8(priv, &priv->map->EIFS_8187SE, hw_eifs); + else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { + /* rtl8187/rtl8185 HW bug. After EIFS is elapsed, + * the HW still wait for DIFS. + * HW uses 4uS units for EIFS. + */ + hw_eifs = DIV_ROUND_UP(eifs - difs, 4); - rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs); + rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs); + } } static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, @@ -956,6 +1452,10 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, reg = RTL818X_MSR_INFRA; } else reg = RTL818X_MSR_NO_LINK; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + reg |= RTL818X_MSR_ENEDCA; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); } @@ -975,6 +1475,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, &priv->rates[0])) - 10; rtl8180_conf_erp(dev, info); + + /* mac80211 supplies aifs_n to driver and calls + * conf_tx callback whether aifs_n changes, NOT + * when aifs changes. + * Aifs should be recalculated if slot changes. + */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + for (i = 0; i < 4; i++) + rtl8187se_conf_ac_parm(dev, i); + } } if (changed & BSS_CHANGED_BEACON_ENABLED) @@ -1098,7 +1608,10 @@ static void rtl8180_eeprom_read(struct rtl8180_priv *priv) eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)priv->mac_addr, 3); - eeprom_cck_table_adr = 0x10; + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + eeprom_cck_table_adr = 0x30; + else + eeprom_cck_table_adr = 0x10; /* CCK TX power */ for (i = 0; i < 14; i += 2) { @@ -1126,6 +1639,19 @@ static void rtl8180_eeprom_read(struct rtl8180_priv *priv) eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); } + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + eeprom_93cx6_read(&eeprom, 0x3F, &eeprom_val); + priv->antenna_diversity_en = !!(eeprom_val & 0x100); + priv->antenna_diversity_default = (eeprom_val & 0xC00) == 0x400; + + eeprom_93cx6_read(&eeprom, 0x7C, &eeprom_val); + priv->xtal_out = eeprom_val & 0xF; + priv->xtal_in = (eeprom_val & 0xF0) >> 4; + priv->xtal_cal = !!(eeprom_val & 0x1000); + priv->thermal_meter_val = (eeprom_val & 0xF00) >> 8; + priv->thermal_meter_en = !!(eeprom_val & 0x2000); + } + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); } @@ -1221,7 +1747,6 @@ static int rtl8180_probe(struct pci_dev *pdev, dev->vif_data_size = sizeof(struct rtl8180_vif); dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - dev->queues = 1; dev->max_signal = 65; reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); @@ -1246,12 +1771,30 @@ static int rtl8180_probe(struct pci_dev *pdev, chip_name = "RTL8185vD"; priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; break; + + case RTL818X_TX_CONF_RTL8187SE: + chip_name = "RTL8187SE"; + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE; + break; + default: printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", pci_name(pdev), reg >> 25); goto err_iounmap; } + /* we declare to MAC80211 all the queues except for beacon queue + * that will be eventually handled by DRV. + * TX rings are arranged in such a way that lower is the IDX, + * higher is the priority, in order to achieve direct mapping + * with mac80211, however the beacon queue is an exception and it + * is mapped on the highst tx ring IDX. + */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + dev->queues = RTL8187SE_NR_TX_QUEUES - 1; + else + dev->queues = RTL8180_NR_TX_QUEUES - 1; + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); pci_try_set_mwi(pdev); @@ -1270,7 +1813,11 @@ static int rtl8180_probe(struct pci_dev *pdev, break; case 5: priv->rf = &grf5101_rf_ops; break; - case 9: priv->rf = rtl8180_detect_rf(dev); + case 9: + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + priv->rf = rtl8187se_detect_rf(dev); + else + priv->rf = rtl8180_detect_rf(dev); break; case 10: rf_name = "RTL8255"; diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h index 26383d77fc3a..291a55970d1a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h @@ -24,27 +24,64 @@ #define ANAPARAM_PWR1_SHIFT 20 #define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT) +/* rtl8180/rtl8185 have 3 queue + beacon queue. + * mac80211 can use just one, + beacon = 2 tot. + */ +#define RTL8180_NR_TX_QUEUES 2 + +/* rtl8187SE have 6 queues + beacon queues + * mac80211 can use 4 QoS data queue, + beacon = 5 tot + */ +#define RTL8187SE_NR_TX_QUEUES 5 + +/* for array static allocation, it is the max of above */ +#define RTL818X_NR_TX_QUEUES 5 + struct rtl8180_tx_desc { __le32 flags; __le16 rts_duration; __le16 plcp_len; __le32 tx_buf; - __le32 frame_len; + union{ + __le32 frame_len; + struct { + __le16 frame_len_se; + __le16 frame_duration; + } __packed; + } __packed; __le32 next_tx_desc; u8 cw; u8 retry_limit; u8 agc; u8 flags2; - u32 reserved[2]; + /* rsvd for 8180/8185. + * valid for 8187se but we dont use it + */ + u32 reserved; + /* all rsvd for 8180/8185 */ + __le16 flags3; + __le16 frag_qsize; +} __packed; + +struct rtl818x_rx_cmd_desc { + __le32 flags; + u32 reserved; + __le32 rx_buf; } __packed; struct rtl8180_rx_desc { __le32 flags; __le32 flags2; - union { - __le32 rx_buf; - __le64 tsft; - }; + __le64 tsft; + +} __packed; + +struct rtl8187se_rx_desc { + __le32 flags; + __le64 tsft; + __le32 flags2; + __le32 flags3; + u32 reserved[3]; } __packed; struct rtl8180_tx_ring { @@ -71,14 +108,16 @@ struct rtl8180_priv { /* rtl8180 driver specific */ spinlock_t lock; - struct rtl8180_rx_desc *rx_ring; + void *rx_ring; + u8 rx_ring_sz; dma_addr_t rx_ring_dma; unsigned int rx_idx; struct sk_buff *rx_buf[32]; - struct rtl8180_tx_ring tx_ring[4]; + struct rtl8180_tx_ring tx_ring[RTL818X_NR_TX_QUEUES]; struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; struct ieee80211_supported_band band; + struct ieee80211_tx_queue_params queue_param[4]; struct pci_dev *pdev; u32 rx_conf; u8 slot_time; @@ -87,18 +126,27 @@ struct rtl8180_priv { enum { RTL818X_CHIP_FAMILY_RTL8180, RTL818X_CHIP_FAMILY_RTL8185, + RTL818X_CHIP_FAMILY_RTL8187SE, } chip_family; u32 anaparam; u16 rfparam; u8 csthreshold; u8 mac_addr[ETH_ALEN]; u8 rf_type; + u8 xtal_out; + u8 xtal_in; + u8 xtal_cal; + u8 thermal_meter_val; + u8 thermal_meter_en; + u8 antenna_diversity_en; + u8 antenna_diversity_default; /* sequence # */ u16 seqno; }; void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam); +void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2); static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr) { diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c index 1c0fe238d995..9bda5bc78eda 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c @@ -282,6 +282,7 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) msleep(1); /* FIXME: optional? */ + /* TODO: use set_anaparam2 dev.c_func*/ /* anaparam2 on */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c new file mode 100644 index 000000000000..fde89866fa8d --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c @@ -0,0 +1,475 @@ + +/* Radio tuning for RTL8225 on RTL8187SE + * + * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net> + * Copyright 2014 Andrea Merello <andrea.merello@gmail.com> + * + * Based on the r8180 and Realtek r8187se drivers, which are: + * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. + * + * Also based on the rtl8187 driver, which is: + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andrea.merello@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <net/mac80211.h> + +#include "rtl8180.h" +#include "rtl8225se.h" + +#define PFX "rtl8225 (se) " + +static const u32 RF_GAIN_TABLE[] = { + 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, + 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, + 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, + 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, + 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 +}; + +static const u8 cck_ofdm_gain_settings[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, +}; + +static const u8 rtl8225se_tx_gain_cck_ofdm[] = { + 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e +}; + +static const u8 rtl8225se_tx_power_cck[] = { + 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, + 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, + 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, + 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 +}; + +static const u8 rtl8225se_tx_power_cck_ch14[] = { + 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225se_tx_power_ofdm[] = { + 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 +}; + +static const u32 rtl8225se_chan[] = { + 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, +}; + +static const u8 rtl8225sez2_tx_power_cck_ch14[] = { + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225sez2_tx_power_cck_B[] = { + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 +}; + +static const u8 rtl8225sez2_tx_power_cck_A[] = { + 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 +}; + +static const u8 rtl8225sez2_tx_power_cck[] = { + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 +}; + +static const u8 ZEBRA_AGC[] = { + 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, + 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, + 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, + 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, + 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, + 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, + 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, + 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, + 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24, + 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F +}; + +static const u8 OFDM_CONFIG[] = { + 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, + 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, + 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, + 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, + 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, + 0xD8, 0x3C, 0x7B, 0x10, 0x10 +}; + +static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data, + u8 len, bool write) +{ + struct rtl8180_priv *priv = dev->priv; + int i; + u8 tmp; + + do { + for (i = 0; i < 5; i++) { + tmp = rtl818x_ioread8(priv, SW_3W_CMD1); + if (!(tmp & 0x3)) + break; + udelay(10); + } + if (i == 5) + wiphy_err(dev->wiphy, PFX + "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp); + + tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02; + rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp); + + tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7; + rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp); + if (write) { + if (len == 16) { + rtl818x_iowrite16(priv, SW_3W_DB0, + *(u16 *)data); + } else if (len == 64) { + rtl818x_iowrite32(priv, SW_3W_DB0_4, + *((u32 *)data)); + rtl818x_iowrite32(priv, SW_3W_DB1_4, + *((u32 *)(data + 4))); + } else + wiphy_err(dev->wiphy, PFX + "Unimplemented length\n"); + } else { + rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data); + } + if (write) + tmp = 2; + else + tmp = 1; + rtl818x_iowrite8(priv, SW_3W_CMD1, tmp); + for (i = 0; i < 5; i++) { + tmp = rtl818x_ioread8(priv, SW_3W_CMD1); + if (!(tmp & 0x3)) + break; + udelay(10); + } + rtl818x_iowrite8(priv, SW_3W_CMD1, 0); + if (!write) { + *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG); + *((u16 *)data) &= 0x0FFF; + } + } while (0); +} + +static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) +{ + u32 dataread = addr & 0x0F; + rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0); + return dataread; +} + +static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + u32 outdata = (data << 4) | (u32)(addr & 0x0F); + rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1); +} + + +static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev) +{ + int i; + + for (i = 0; i < 128; i++) { + rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]); + rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80); + rtl8225se_write_phy_ofdm(dev, 0xE, 0); + } +} + +static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev) +{ + /* write OFDM_CONFIG table */ + int i; + + for (i = 0; i < 60; i++) + rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]); + +} + +static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8180_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + if (cck_power > 35) + cck_power = 35; + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + cck_ofdm_gain_settings[cck_power]); + + usleep_range(1000, 5000); + ofdm_power = priv->channels[channel - 1].hw_value >> 8; + if (ofdm_power > 35) + ofdm_power = 35; + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + cck_ofdm_gain_settings[ofdm_power]); + if (ofdm_power < 12) { + rtl8225se_write_phy_ofdm(dev, 7, 0x5C); + rtl8225se_write_phy_ofdm(dev, 9, 0x5C); + } + if (ofdm_power < 18) { + rtl8225se_write_phy_ofdm(dev, 7, 0x54); + rtl8225se_write_phy_ofdm(dev, 9, 0x54); + } else { + rtl8225se_write_phy_ofdm(dev, 7, 0x50); + rtl8225se_write_phy_ofdm(dev, 9, 0x50); + } + + usleep_range(1000, 5000); +} + +static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev) +{ + int i; + + for (i = 0; i <= 36; i++) { + rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1); + } +} + +static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev, + int init_gain) +{ + switch (init_gain) { + default: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); + break; + case 2: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); + break; + case 3: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 4: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 5: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 6: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + case 7: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + case 8: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + } +} + +void rtl8225se_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u32 rf23, rf24; + u8 d_cut = 0; + u8 tmp; + + /* Page 1 */ + rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); + rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1); + rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1); + if (rf23 == 0x0818 && rf24 == 0x070C) + d_cut = 1; + + wiphy_info(dev->wiphy, "RTL8225-SE version %s\n", + d_cut ? "D" : "not-D"); + + /* Page 0: reg 0 - 15 */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1); + rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1); + rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1); + /* page 1: reg 16-30 */ + rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1); + if (d_cut) + rtl8187se_rf_writereg(dev, 0x0E, 0x0807); + else + rtl8187se_rf_writereg(dev, 0x0E, 0x0806); + mdelay(1); + rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1); + rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1); + + rtl8187se_write_rf_gain(dev); + + rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1); + rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); + rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11); + rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11); + rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11); + rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11); + rtl8187se_rf_writereg(dev, 0x02, 0x088D); mdelay(221); + rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); + rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); + if (priv->xtal_cal) { + tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) | + (1 << 11) | (1 << 9); + rtl8187se_rf_writereg(dev, 0x0F, tmp); + wiphy_info(dev->wiphy, "Xtal cal\n"); + mdelay(1); + } else { + wiphy_info(dev->wiphy, "NO Xtal cal\n"); + rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); + mdelay(1); + } + /* page 0 */ + rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(31); + rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1); + + rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1); + /* power save parameters */ + /* TODO: move to dev.c */ + rtl818x_iowrite8(priv, REG_ADDR1(0x024E), + rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F); + rtl8225se_write_phy_cck(dev, 0x00, 0xC8); + rtl8225se_write_phy_cck(dev, 0x06, 0x1C); + rtl8225se_write_phy_cck(dev, 0x10, 0x78); + rtl8225se_write_phy_cck(dev, 0x2E, 0xD0); + rtl8225se_write_phy_cck(dev, 0x2F, 0x06); + rtl8225se_write_phy_cck(dev, 0x01, 0x46); + + /* power control */ + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B); + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225se_write_phy_ofdm(dev, 0x00, 0x12); + + rtl8225se_write_zebra_agc(dev); + + rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); + + rtl8187se_write_ofdm_config(dev); + + /* turn on RF */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); + rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); + /* turn on RF again */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); + rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); + /* turn on BB */ + rtl8225se_write_phy_ofdm(dev, 0x10, 0x40); + rtl8225se_write_phy_ofdm(dev, 0x12, 0x40); + + rtl8187se_write_initial_gain(dev, 4); +} + +void rtl8225se_rf_stop(struct ieee80211_hw *dev) +{ + /* checked for 8187se */ + struct rtl8180_priv *priv = dev->priv; + + /* turn off BB RXIQ matrix to cut off rx signal */ + rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); + rtl8225se_write_phy_ofdm(dev, 0x12, 0x00); + /* turn off RF */ + rtl8187se_rf_writereg(dev, 0x04, 0x0000); + rtl8187se_rf_writereg(dev, 0x00, 0x0000); + + usleep_range(1000, 5000); + /* turn off A/D and D/A */ + rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF); + rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF); +} + +void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + int chan = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + + rtl8225sez2_rf_set_tx_power(dev, chan); + rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); + if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) != + rtl8225se_chan[chan - 1]) + rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); + usleep_range(10000, 20000); +} + +static const struct rtl818x_rf_ops rtl8225se_ops = { + .name = "rtl8225-se", + .init = rtl8225se_rf_init, + .stop = rtl8225se_rf_stop, + .set_chan = rtl8225se_rf_set_channel, +}; + +const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev) +{ + return &rtl8225se_ops; +} diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h new file mode 100644 index 000000000000..229400264088 --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h @@ -0,0 +1,61 @@ + +/* Definitions for RTL8187SE hardware + * + * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net> + * Copyright 2014 Andrea Merello <andrea.merello@gmail.com> + * + * Based on the r8180 and Realtek r8187se drivers, which are: + * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. + * + * Also based on the rtl8187 driver, which is: + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andrea.merello@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187SE_RTL8225_H +#define RTL8187SE_RTL8225_H + +#define RTL8225SE_ANAPARAM_ON 0xb0054d00 +#define RTL8225SE_ANAPARAM2_ON 0x000004c6 + +/* all off except PLL */ +#define RTL8225SE_ANAPARAM_OFF 0xb0054dec +/* all on including PLL */ +#define RTL8225SE_ANAPARAM_OFF2 0xb0054dfc + +#define RTL8225SE_ANAPARAM2_OFF 0x00ff04c6 + +#define RTL8225SE_ANAPARAM3 0x10 + +enum rtl8187se_power_state { + RTL8187SE_POWER_ON, + RTL8187SE_POWER_OFF, + RTL8187SE_POWER_SLEEP +}; + +static inline void rtl8225se_write_phy_ofdm(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data); +} + +static inline void rtl8225se_write_phy_cck(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data | 0x10000); +} + + +const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *); +void rtl8225se_rf_stop(struct ieee80211_hw *dev); +void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf); +void rtl8225se_rf_conf_erp(struct ieee80211_hw *dev, + struct ieee80211_bss_conf *info); +void rtl8225se_rf_init(struct ieee80211_hw *dev); + +#endif /* RTL8187SE_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index c981bcfb6cef..0ca17cda48fa 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -592,7 +592,7 @@ static void rtl8187_set_anaparam(struct rtl8187_priv *priv, bool rfon) rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); if (priv->is_rtl8187b) - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, anaparam3); + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3A, anaparam3); reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, @@ -1636,10 +1636,10 @@ static int rtl8187_probe(struct usb_interface *intf, err_free_dmabuf: kfree(priv->io_dmabuf); - err_free_dev: - ieee80211_free_hw(dev); usb_set_intfdata(intf, NULL); usb_put_dev(udev); + err_free_dev: + ieee80211_free_hw(dev); return err; } diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index 1815b15d03b1..45ea4e1c4abe 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h @@ -16,30 +16,82 @@ #define RTL818X_H struct rtl818x_csr { + u8 MAC[6]; u8 reserved_0[2]; - __le32 MAR[2]; - u8 RX_FIFO_COUNT; - u8 reserved_1; - u8 TX_FIFO_COUNT; - u8 BQREQ; - u8 reserved_2[4]; + + union { + __le32 MAR[2]; /* 0x8 */ + + struct{ /* rtl8187se */ + u8 rf_sw_config; /* 0x8 */ + u8 reserved_01[3]; + __le32 TMGDA; /* 0xc */ + } __packed; + } __packed; + + union { /* 0x10 */ + struct { + u8 RX_FIFO_COUNT; + u8 reserved_1; + u8 TX_FIFO_COUNT; + u8 BQREQ; + } __packed; + + __le32 TBKDA; /* for 8187se */ + } __packed; + + __le32 TBEDA; /* 0x14 - for rtl8187se */ + __le32 TSFT[2]; - __le32 TLPDA; - __le32 TNPDA; - __le32 THPDA; - __le16 BRSR; - u8 BSSID[6]; - u8 RESP_RATE; - u8 EIFS; - u8 reserved_3[1]; - u8 CMD; + + union { /* 0x20 */ + __le32 TLPDA; + __le32 TVIDA; /* for 8187se */ + } __packed; + + union { /* 0x24 */ + __le32 TNPDA; + __le32 TVODA; /* for 8187se */ + } __packed; + + /* hi pri ring for all cards */ + __le32 THPDA; /* 0x28 */ + + union { /* 0x2c */ + struct { + u8 reserved_2a; + u8 EIFS_8187SE; + } __packed; + + __le16 BRSR; + } __packed; + + u8 BSSID[6]; /* 0x2e */ + + union { /* 0x34 */ + struct { + u8 RESP_RATE; + u8 EIFS; + } __packed; + __le16 BRSR_8187SE; + } __packed; + + u8 reserved_3[1]; /* 0x36 */ + u8 CMD; /* 0x37 */ #define RTL818X_CMD_TX_ENABLE (1 << 2) #define RTL818X_CMD_RX_ENABLE (1 << 3) #define RTL818X_CMD_RESET (1 << 4) - u8 reserved_4[4]; - __le16 INT_MASK; - __le16 INT_STATUS; + u8 reserved_4[4]; /* 0x38 */ + union { + struct { + __le16 INT_MASK; + __le16 INT_STATUS; + } __packed; + + __le32 INT_STATUS_SE; /* 0x3c */ + } __packed; +/* status bits for rtl8187 and rtl8180/8185 */ #define RTL818X_INT_RX_OK (1 << 0) #define RTL818X_INT_RX_ERR (1 << 1) #define RTL818X_INT_TXL_OK (1 << 2) @@ -56,7 +108,34 @@ struct rtl818x_csr { #define RTL818X_INT_BEACON (1 << 13) #define RTL818X_INT_TIME_OUT (1 << 14) #define RTL818X_INT_TX_FO (1 << 15) - __le32 TX_CONF; +/* status bits for rtl8187se */ +#define RTL818X_INT_SE_TIMER3 (1 << 0) +#define RTL818X_INT_SE_TIMER2 (1 << 1) +#define RTL818X_INT_SE_RQ0SOR (1 << 2) +#define RTL818X_INT_SE_TXBED_OK (1 << 3) +#define RTL818X_INT_SE_TXBED_ERR (1 << 4) +#define RTL818X_INT_SE_TXBE_OK (1 << 5) +#define RTL818X_INT_SE_TXBE_ERR (1 << 6) +#define RTL818X_INT_SE_RX_OK (1 << 7) +#define RTL818X_INT_SE_RX_ERR (1 << 8) +#define RTL818X_INT_SE_TXL_OK (1 << 9) +#define RTL818X_INT_SE_TXL_ERR (1 << 10) +#define RTL818X_INT_SE_RX_DU (1 << 11) +#define RTL818X_INT_SE_RX_FIFO (1 << 12) +#define RTL818X_INT_SE_TXN_OK (1 << 13) +#define RTL818X_INT_SE_TXN_ERR (1 << 14) +#define RTL818X_INT_SE_TXH_OK (1 << 15) +#define RTL818X_INT_SE_TXH_ERR (1 << 16) +#define RTL818X_INT_SE_TXB_OK (1 << 17) +#define RTL818X_INT_SE_TXB_ERR (1 << 18) +#define RTL818X_INT_SE_ATIM_TO (1 << 19) +#define RTL818X_INT_SE_BK_TO (1 << 20) +#define RTL818X_INT_SE_TIMER1 (1 << 21) +#define RTL818X_INT_SE_TX_FIFO (1 << 22) +#define RTL818X_INT_SE_WAKEUP (1 << 23) +#define RTL818X_INT_SE_BK_DMA (1 << 24) +#define RTL818X_INT_SE_TMGD_OK (1 << 30) + __le32 TX_CONF; /* 0x40 */ #define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17) #define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17) #define RTL818X_TX_CONF_NO_ICV (1 << 19) @@ -68,6 +147,7 @@ struct rtl818x_csr { #define RTL818X_TX_CONF_R8185_D (5 << 25) #define RTL818X_TX_CONF_R8187vD (5 << 25) #define RTL818X_TX_CONF_R8187vD_B (6 << 25) +#define RTL818X_TX_CONF_RTL8187SE (6 << 25) #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) #define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) @@ -122,28 +202,64 @@ struct rtl818x_csr { u8 PGSELECT; u8 SECURITY; __le32 ANAPARAM2; - u8 reserved_10[12]; - __le16 BEACON_INTERVAL; - __le16 ATIM_WND; - __le16 BEACON_INTERVAL_TIME; - __le16 ATIMTR_INTERVAL; - u8 PHY_DELAY; - u8 CARRIER_SENSE_COUNTER; - u8 reserved_11[2]; - u8 PHY[4]; - __le16 RFPinsOutput; - __le16 RFPinsEnable; - __le16 RFPinsSelect; - __le16 RFPinsInput; - __le32 RF_PARA; - __le32 RF_TIMING; - u8 GP_ENABLE; - u8 GPIO0; - u8 GPIO1; - u8 reserved_12; - __le32 HSSI_PARA; - u8 reserved_13[4]; - u8 TX_AGC_CTL; + u8 reserved_10[8]; + __le32 IMR; /* 0x6c - Interrupt mask reg for 8187se */ +#define IMR_TMGDOK ((1 << 30)) +#define IMR_DOT11HINT ((1 << 25)) /* 802.11h Measurement Interrupt */ +#define IMR_BCNDMAINT ((1 << 24)) /* Beacon DMA Interrupt */ +#define IMR_WAKEINT ((1 << 23)) /* Wake Up Interrupt */ +#define IMR_TXFOVW ((1 << 22)) /* Tx FIFO Overflow */ +#define IMR_TIMEOUT1 ((1 << 21)) /* Time Out Interrupt 1 */ +#define IMR_BCNINT ((1 << 20)) /* Beacon Time out */ +#define IMR_ATIMINT ((1 << 19)) /* ATIM Time Out */ +#define IMR_TBDER ((1 << 18)) /* Tx Beacon Descriptor Error */ +#define IMR_TBDOK ((1 << 17)) /* Tx Beacon Descriptor OK */ +#define IMR_THPDER ((1 << 16)) /* Tx High Priority Descriptor Error */ +#define IMR_THPDOK ((1 << 15)) /* Tx High Priority Descriptor OK */ +#define IMR_TVODER ((1 << 14)) /* Tx AC_VO Descriptor Error Int */ +#define IMR_TVODOK ((1 << 13)) /* Tx AC_VO Descriptor OK Interrupt */ +#define IMR_FOVW ((1 << 12)) /* Rx FIFO Overflow Interrupt */ +#define IMR_RDU ((1 << 11)) /* Rx Descriptor Unavailable */ +#define IMR_TVIDER ((1 << 10)) /* Tx AC_VI Descriptor Error */ +#define IMR_TVIDOK ((1 << 9)) /* Tx AC_VI Descriptor OK Interrupt */ +#define IMR_RER ((1 << 8)) /* Rx Error Interrupt */ +#define IMR_ROK ((1 << 7)) /* Receive OK Interrupt */ +#define IMR_TBEDER ((1 << 6)) /* Tx AC_BE Descriptor Error */ +#define IMR_TBEDOK ((1 << 5)) /* Tx AC_BE Descriptor OK */ +#define IMR_TBKDER ((1 << 4)) /* Tx AC_BK Descriptor Error */ +#define IMR_TBKDOK ((1 << 3)) /* Tx AC_BK Descriptor OK */ +#define IMR_RQOSOK ((1 << 2)) /* Rx QoS OK Interrupt */ +#define IMR_TIMEOUT2 ((1 << 1)) /* Time Out Interrupt 2 */ +#define IMR_TIMEOUT3 ((1 << 0)) /* Time Out Interrupt 3 */ + __le16 BEACON_INTERVAL; /* 0x70 */ + __le16 ATIM_WND; /* 0x72 */ + __le16 BEACON_INTERVAL_TIME; /* 0x74 */ + __le16 ATIMTR_INTERVAL; /* 0x76 */ + u8 PHY_DELAY; /* 0x78 */ + u8 CARRIER_SENSE_COUNTER; /* 0x79 */ + u8 reserved_11[2]; /* 0x7a */ + u8 PHY[4]; /* 0x7c */ + __le16 RFPinsOutput; /* 0x80 */ + __le16 RFPinsEnable; /* 0x82 */ + __le16 RFPinsSelect; /* 0x84 */ + __le16 RFPinsInput; /* 0x86 */ + __le32 RF_PARA; /* 0x88 */ + __le32 RF_TIMING; /* 0x8c */ + u8 GP_ENABLE; /* 0x90 */ + u8 GPIO0; /* 0x91 */ + u8 GPIO1; /* 0x92 */ + u8 TPPOLL_STOP; /* 0x93 - rtl8187se only */ +#define RTL818x_TPPOLL_STOP_BQ (1 << 7) +#define RTL818x_TPPOLL_STOP_VI (1 << 4) +#define RTL818x_TPPOLL_STOP_VO (1 << 5) +#define RTL818x_TPPOLL_STOP_BE (1 << 3) +#define RTL818x_TPPOLL_STOP_BK (1 << 2) +#define RTL818x_TPPOLL_STOP_MG (1 << 1) +#define RTL818x_TPPOLL_STOP_HI (1 << 6) + + __le32 HSSI_PARA; /* 0x94 */ + u8 reserved_13[4]; /* 0x98 */ + u8 TX_AGC_CTL; /* 0x9c */ #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN (1 << 0) #define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL (1 << 1) #define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2) @@ -167,7 +283,8 @@ struct rtl818x_csr { u8 reserved_17[24]; u8 CONFIG5; u8 TX_DMA_POLLING; - u8 reserved_18[2]; + u8 PHY_PR; + u8 reserved_18; __le16 CWR; u8 RETRY_CTR; u8 reserved_19[3]; @@ -179,14 +296,59 @@ struct rtl818x_csr { __le32 RDSAR; __le16 TID_AC_MAP; u8 reserved_20[4]; - u8 ANAPARAM3; - u8 reserved_21[5]; - __le16 FEMR; - u8 reserved_22[4]; - __le16 TALLY_CNT; - u8 TALLY_SEL; + union { + __le16 ANAPARAM3; /* 0xee */ + u8 ANAPARAM3A; /* for rtl8187 */ + }; + +#define AC_PARAM_TXOP_LIMIT_SHIFT 16 +#define AC_PARAM_ECW_MAX_SHIFT 12 +#define AC_PARAM_ECW_MIN_SHIFT 8 +#define AC_PARAM_AIFS_SHIFT 0 + + __le32 AC_VO_PARAM; /* 0xf0 */ + + union { /* 0xf4 */ + __le32 AC_VI_PARAM; + __le16 FEMR; + } __packed; + + union{ /* 0xf8 */ + __le32 AC_BE_PARAM; /* rtl8187se */ + struct{ + u8 reserved_21[2]; + __le16 TALLY_CNT; /* 0xfa */ + } __packed; + } __packed; + + union { + u8 TALLY_SEL; /* 0xfc */ + __le32 AC_BK_PARAM; + + } __packed; + } __packed; +/* These are addresses with NON-standard usage. + * They have offsets very far from this struct. + * I don't like to introduce a ton of "reserved".. + * They are for RTL8187SE + */ +#define REG_ADDR1(addr) ((u8 __iomem *)priv->map + addr) +#define REG_ADDR2(addr) ((__le16 __iomem *)priv->map + (addr >> 1)) +#define REG_ADDR4(addr) ((__le32 __iomem *)priv->map + (addr >> 2)) + +#define FEMR_SE REG_ADDR2(0x1D4) +#define ARFR REG_ADDR2(0x1E0) +#define RFSW_CTRL REG_ADDR2(0x272) +#define SW_3W_DB0 REG_ADDR2(0x274) +#define SW_3W_DB0_4 REG_ADDR4(0x274) +#define SW_3W_DB1 REG_ADDR2(0x278) +#define SW_3W_DB1_4 REG_ADDR4(0x278) +#define SW_3W_CMD1 REG_ADDR1(0x27D) +#define PI_DATA_REG REG_ADDR2(0x360) +#define SI_DATA_REG REG_ADDR2(0x362) + struct rtl818x_rf_ops { char *name; void (*init)(struct ieee80211_hw *); diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index ded691f76f2f..4ec424f26672 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -982,7 +982,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, u8 keep_alive = 10; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_KEEP_ALIVE, - (u8 *)(&keep_alive)); + &keep_alive); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_JOINBSSRPT, diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index f26f4ffc771d..dae55257f0e8 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1509,10 +1509,10 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, if (rtlpriv->use_new_trx_flow) { rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, - HW_DESC_OWN, (u8 *)&hw_queue); + HW_DESC_OWN, &hw_queue); } else { rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, - HW_DESC_OWN, (u8 *)&temp_one); + HW_DESC_OWN, &temp_one); } if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && @@ -1853,6 +1853,65 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, return true; } +static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + ret = pci_enable_msi(rtlpci->pdev); + if (ret < 0) + return ret; + + ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hw); + if (ret < 0) { + pci_disable_msi(rtlpci->pdev); + return ret; + } + + rtlpci->using_msi = true; + + RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, + "MSI Interrupt Mode!\n"); + return 0; +} + +static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hw); + if (ret < 0) + return ret; + + rtlpci->using_msi = false; + RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, + "Pin-based Interrupt Mode!\n"); + return 0; +} + +static int rtl_pci_intr_mode_decide(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + if (rtlpci->msi_support) { + ret = rtl_pci_intr_mode_msi(hw); + if (ret < 0) + ret = rtl_pci_intr_mode_legacy(hw); + } else { + ret = rtl_pci_intr_mode_legacy(hw); + } + return ret; +} + int rtl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1995,8 +2054,7 @@ int rtl_pci_probe(struct pci_dev *pdev, } rtlpci = rtl_pcidev(pcipriv); - err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, - IRQF_SHARED, KBUILD_MODNAME, hw); + err = rtl_pci_intr_mode_decide(hw); if (err) { RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s: failed to register IRQ handler\n", @@ -2064,6 +2122,9 @@ void rtl_pci_disconnect(struct pci_dev *pdev) rtlpci->irq_alloc = 0; } + if (rtlpci->using_msi) + pci_disable_msi(rtlpci->pdev); + list_del(&rtlpriv->list); if (rtlpriv->io.pci_mem_start != 0) { pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index de7f05f848ef..50504942ded1 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -759,7 +759,7 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, unsigned int len) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_mgmt *mgmt = (void *)data; + struct ieee80211_mgmt *mgmt = data; struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); u8 *pos, *end, *ie; u16 noa_len; @@ -858,7 +858,7 @@ static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, unsigned int len) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_mgmt *mgmt = (void *)data; + struct ieee80211_mgmt *mgmt = data; struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); u8 noa_num, index, i, noa_index = 0; u8 *pos, *end, *ie; @@ -950,9 +950,8 @@ void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) switch (p2p_ps_state) { case P2P_PS_DISABLE: p2pinfo->p2p_ps_state = p2p_ps_state; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - (u8 *)(&p2p_ps_state)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, + &p2p_ps_state); p2pinfo->noa_index = 0; p2pinfo->ctwindow = 0; @@ -964,7 +963,7 @@ void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) rtlps->smart_ps = 2; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&rtlps->pwr_mode)); + &rtlps->pwr_mode); } } break; @@ -977,12 +976,12 @@ void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) rtlps->smart_ps = 0; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&rtlps->pwr_mode)); + &rtlps->pwr_mode); } } rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - (u8 *)(&p2p_ps_state)); + &p2p_ps_state); } break; case P2P_PS_SCAN: @@ -992,7 +991,7 @@ void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) p2pinfo->p2p_ps_state = p2p_ps_state; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - (u8 *)(&p2p_ps_state)); + &p2p_ps_state); } break; default: @@ -1012,7 +1011,7 @@ void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (void *)data; + struct ieee80211_hdr *hdr = data; if (!mac->p2p) return; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c index 97bc9aa5e1d1..f8daa61cf1c3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c @@ -851,9 +851,8 @@ static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw) } else { if (rtlpriv->dm.current_turbo_edca) { u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *)(&tmp)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &tmp); rtlpriv->dm.current_turbo_edca = false; } } diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c index 557bc5b8327e..4f9376ad4739 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c @@ -119,7 +119,7 @@ static void _rtl88e_write_fw(struct ieee80211_hw *hw, enum version_8188e version, u8 *buffer, u32 size) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *buf_ptr = (u8 *)buffer; + u8 *buf_ptr = buffer; u32 page_no, remain; u32 page, offset; @@ -213,7 +213,7 @@ int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) return 1; pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; - pfwdata = (u8 *)rtlhal->pfirmware; + pfwdata = rtlhal->pfirmware; fwsize = rtlhal->fwsize; RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "normal Firmware SIZE %d\n", fwsize); diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c index bd2a26bafb69..94cd9df98381 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c @@ -147,8 +147,7 @@ static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, } if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); if (FW_PS_IS_ACK(rpwm_val)) { isr_regaddr = REG_HISR; content = rtl_read_dword(rtlpriv, isr_regaddr); @@ -225,7 +224,7 @@ static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); rtl_write_word(rtlpriv, REG_HISR, 0x0100); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + &rpwm_val); spin_lock_bh(&rtlpriv->locks.fw_ps_lock); rtlhal->fw_clk_change_in_progress = false; spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); @@ -273,15 +272,14 @@ static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); rtlhal->allow_sw_to_change_hwclc = false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); } else { rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); } @@ -300,7 +298,7 @@ static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); + &ppsc->fwctrl_psmode); rtlhal->allow_sw_to_change_hwclc = true; _rtl88ee_set_fw_clock_off(hw, rpwm_val); } else { @@ -308,9 +306,8 @@ static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + &ppsc->fwctrl_psmode); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); } } @@ -419,12 +416,12 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) for (e_aci = 0; e_aci < AC_MAX; e_aci++) { rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); + &e_aci); } break; } case HW_VAR_ACK_PREAMBLE:{ u8 reg_tmp; - u8 short_preamble = (bool) (*(u8 *)val); + u8 short_preamble = (bool)*val; reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); if (short_preamble) { reg_tmp |= 0x02; @@ -435,13 +432,13 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } break; } case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + rtl_write_byte(rtlpriv, REG_SECCFG, *val); break; case HW_VAR_AMPDU_MIN_SPACE:{ u8 min_spacing_to_set; u8 sec_min_space; - min_spacing_to_set = *((u8 *)val); + min_spacing_to_set = *val; if (min_spacing_to_set <= 7) { sec_min_space = 0; @@ -464,7 +461,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_SHORTGI_DENSITY:{ u8 density_to_set; - density_to_set = *((u8 *)val); + density_to_set = *val; mac->min_space_cfg |= (density_to_set << 3); RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, @@ -482,7 +479,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) reg = regtoset_normal; - factor = *((u8 *)val); + factor = *val; if (factor <= 3) { factor = (1 << (factor + 2)); if (factor > 0xf) @@ -505,15 +502,15 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } break; } case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *)val); + u8 e_aci = *val; rtl88e_dm_init_edca_turbo(hw); if (rtlpci->acm_method != EACMWAY2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); + &e_aci); break; } case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *)val); + u8 e_aci = *val; union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&(mac->ac[0].aifs)); u8 acm = p_aci_aifsn->f.acm; @@ -566,7 +563,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlpci->receive_config = ((u32 *)(val))[0]; break; case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *)(val))[0]; + u8 retry_limit = *val; rtl_write_word(rtlpriv, REG_RL, retry_limit << RETRY_LIMIT_SHORT_SHIFT | @@ -579,7 +576,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlefuse->efuse_usedbytes = *((u16 *)val); break; case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *)val); + rtlefuse->efuse_usedpercentage = *val; break; case HW_VAR_IO_CMD: rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); @@ -591,15 +588,13 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) udelay(1); if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - (*(u8 *)val)); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val | BIT(7)); } break; } case HW_VAR_H2C_FW_PWRMODE: - rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + rtl88e_set_fw_pwrmode_cmd(hw, *val); break; case HW_VAR_FW_PSMODE_STATUS: ppsc->fw_current_inpsmode = *((bool *)val); @@ -616,7 +611,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) _rtl88ee_fwlps_leave(hw); break; } case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *)val); + u8 mstatus = *val; u8 tmp, tmp_reg422, uval; u8 count = 0, dlbcn_count = 0; bool recover = false; @@ -667,10 +662,10 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & ~(BIT(0)))); } - rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); + rtl88e_set_fw_joinbss_report_cmd(hw, *val); break; } case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl88e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + rtl88e_set_p2p_ps_offload_cmd(hw, *val); break; case HW_VAR_AID:{ u16 u2btmp; @@ -680,7 +675,7 @@ void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) mac->assoc_id)); break; } case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *)(val))[0]; + u8 btype_ibss = *val; if (btype_ibss == true) _rtl88ee_stop_tx_beacon(hw); @@ -1828,7 +1823,7 @@ static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); /*customer ID*/ - rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; if (rtlefuse->eeprom_oemid == 0xFF) rtlefuse->eeprom_oemid = 0; @@ -1845,7 +1840,7 @@ static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "dev_addr: %pM\n", rtlefuse->dev_addr); /*channel plan */ - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; /* set channel paln to world wide 13 */ rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; /*tx power*/ @@ -1857,7 +1852,7 @@ static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) rtlefuse->autoload_failflag, hwinfo); /*board type*/ - rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5); + rtlefuse->board_type = (hwinfo[jj] & 0xE0) >> 5; /*Wake on wlan*/ rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6); /*parse xtal*/ @@ -2223,8 +2218,7 @@ void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u16 sifs_timer; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)&mac->slot_time); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); if (!mac->ht_enable) sifs_timer = 0x0a0a; else diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c index 347af1e4f438..1b4101bf9974 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c @@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw) u8 tid; rtl8188ee_bt_reg_init(hw); + rtlpci->msi_support = true; rtlpriv->dm.dm_initialgain_enable = 1; rtlpriv->dm.dm_flag = 0; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c index 2ba6f510d884..06ef47cd6203 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c @@ -497,7 +497,7 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; + u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; unsigned int buf_len = 0; @@ -716,7 +716,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_OWN(pdesc, 1); - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 4ae51d5b436f..55adf043aef7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -476,7 +476,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl92c_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + rtl92c_set_p2p_ps_offload_cmd(hw, *val); break; case HW_VAR_AID:{ u16 u2btmp; @@ -521,21 +521,21 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); + &ppsc->fwctrl_psmode); rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + HW_VAR_SET_RPWM, + &rpwm_val); } else { rpwm_val = 0x0C; /* RF on */ fw_pwrmode = FW_PS_ACTIVE_MODE; fw_current_inps = false; rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + HW_VAR_SET_RPWM, + &rpwm_val); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 3015af167b2b..9098558d916d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -413,20 +413,18 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); + &ppsc->fwctrl_psmode); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + &rpwm_val); } else { rpwm_val = 0x0C; /* RF on */ fw_pwrmode = FW_PS_ACTIVE_MODE; fw_current_inps = false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &rpwm_val); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c index 863ddb3e2888..25cc83058b01 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c @@ -647,9 +647,8 @@ static void rtl8723ae_dm_check_edca_turbo(struct ieee80211_hw *hw) } else { if (rtlpriv->dm.current_turbo_edca) { u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *) (&tmp)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &tmp); rtlpriv->dm.current_turbo_edca = false; } } diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index f4c9852d1e1e..65c9e80e1f78 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c @@ -207,14 +207,13 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_byte(rtlpriv, REG_SLOT, val[0]); for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *) (&e_aci)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &e_aci); } break; } case HW_VAR_ACK_PREAMBLE:{ u8 reg_tmp; - u8 short_preamble = (bool) (*(u8 *) val); + u8 short_preamble = (bool)*val; reg_tmp = (mac->cur_40_prime_sc) << 5; if (short_preamble) reg_tmp |= 0x80; @@ -225,7 +224,7 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) u8 min_spacing_to_set; u8 sec_min_space; - min_spacing_to_set = *((u8 *) val); + min_spacing_to_set = *val; if (min_spacing_to_set <= 7) { sec_min_space = 0; @@ -249,7 +248,7 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_SHORTGI_DENSITY:{ u8 density_to_set; - density_to_set = *((u8 *) val); + density_to_set = *val; mac->min_space_cfg |= (density_to_set << 3); RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, @@ -273,7 +272,7 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) else p_regtoset = regtoset_normal; - factor_toset = *((u8 *) val); + factor_toset = *val; if (factor_toset <= 3) { factor_toset = (1 << (factor_toset + 2)); if (factor_toset > 0xf) @@ -304,16 +303,15 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } break; } case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *) val); + u8 e_aci = *val; rtl8723_dm_init_edca_turbo(hw); if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - (u8 *) (&e_aci)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, + &e_aci); break; } case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *) val); + u8 e_aci = *val; union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&(mac->ac[0].aifs)); u8 acm = p_aci_aifsn->f.acm; @@ -366,7 +364,7 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlpci->receive_config = ((u32 *) (val))[0]; break; case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *) (val))[0]; + u8 retry_limit = *val; rtl_write_word(rtlpriv, REG_RL, retry_limit << RETRY_LIMIT_SHORT_SHIFT | @@ -379,13 +377,13 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlefuse->efuse_usedbytes = *((u16 *) val); break; case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *) val); + rtlefuse->efuse_usedpercentage = *val; break; case HW_VAR_IO_CMD: rtl8723ae_phy_set_io_cmd(hw, (*(enum io_type *)val)); break; case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val)); + rtl_write_byte(rtlpriv, REG_SECCFG, *val); break; case HW_VAR_SET_RPWM:{ u8 rpwm_val; @@ -394,27 +392,25 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) udelay(1); if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - (*(u8 *) val)); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *) val) | BIT(7))); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val | BIT(7)); } break; } case HW_VAR_H2C_FW_PWRMODE:{ - u8 psmode = (*(u8 *) val); + u8 psmode = *val; if (psmode != FW_PS_ACTIVE_MODE) rtl8723ae_dm_rf_saving(hw, true); - rtl8723ae_set_fw_pwrmode_cmd(hw, (*(u8 *) val)); + rtl8723ae_set_fw_pwrmode_cmd(hw, *val); break; } case HW_VAR_FW_PSMODE_STATUS: ppsc->fw_current_inpsmode = *((bool *) val); break; case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *) val); + u8 mstatus = *val; u8 tmp_regcr, tmp_reg422; bool recover = false; @@ -447,11 +443,11 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); } - rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); + rtl8723ae_set_fw_joinbss_report_cmd(hw, *val); break; } case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl8723ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + rtl8723ae_set_p2p_ps_offload_cmd(hw, *val); break; case HW_VAR_AID:{ u16 u2btmp; @@ -461,7 +457,7 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) mac->assoc_id)); break; } case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *) (val))[0]; + u8 btype_ibss = *val; if (btype_ibss == true) _rtl8723ae_stop_tx_beacon(hw); @@ -491,20 +487,18 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); + &ppsc->fwctrl_psmode); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + &rpwm_val); } else { rpwm_val = 0x0C; /* RF on */ fw_pwrmode = FW_PS_ACTIVE_MODE; fw_current_inps = false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &rpwm_val); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, @@ -1628,10 +1622,10 @@ static void _rtl8723ae_read_adapter_info(struct ieee80211_hw *hw, rtl8723ae_read_bt_coexist_info_from_hwpg(hw, rtlefuse->autoload_failflag, hwinfo); - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); @@ -2051,8 +2045,7 @@ void rtl8723ae_update_channel_access_setting(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u16 sifs_timer; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)&mac->slot_time); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); if (!mac->ht_enable) sifs_timer = 0x0a0a; else diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index 29adf55c6fd3..10b7577b6ae5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c @@ -375,7 +375,7 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - u8 *pdesc = (u8 *) pdesc_tx; + u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; u8 fw_qsel = _rtl8723ae_map_hwqueue_to_fwqueue(skb, hw_queue); @@ -577,7 +577,7 @@ void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw, SET_TX_DESC_OWN(pdesc, 1); - SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/rtlwifi/rtl8723be/dm.c index 736bfcb7938a..13d53a1df789 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/dm.c @@ -1083,7 +1083,7 @@ static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) if (rtlpriv->dm.current_turbo_edca) { u8 tmp = AC0_BE; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&tmp)); + &tmp); } rtlpriv->dm.current_turbo_edca = false; } diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c index 7e70c7108d91..0fdf0909321f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c @@ -147,7 +147,7 @@ static void _rtl8723be_set_fw_clock_on(struct ieee80211_hw *hw, u8 rpwm_val, } if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + &rpwm_val); if (FW_PS_IS_ACK(rpwm_val)) { isr_regaddr = REG_HISR; content = rtl_read_dword(rtlpriv, isr_regaddr); @@ -221,7 +221,7 @@ static void _rtl8723be_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val) rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); rtl_write_word(rtlpriv, REG_HISR, 0x0100); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + &rpwm_val); spin_lock_bh(&rtlpriv->locks.fw_ps_lock); rtlhal->fw_clk_change_in_progress = false; spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); @@ -253,15 +253,14 @@ static void _rtl8723be_fwlps_leave(struct ieee80211_hw *hw) _rtl8723be_set_fw_clock_on(hw, rpwm_val, false); rtlhal->allow_sw_to_change_hwclc = false; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); } else { rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); + &fw_pwrmode); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); } @@ -280,7 +279,7 @@ static void _rtl8723be_fwlps_enter(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); + &ppsc->fwctrl_psmode); rtlhal->allow_sw_to_change_hwclc = true; _rtl8723be_set_fw_clock_off(hw, rpwm_val); @@ -289,9 +288,8 @@ static void _rtl8723be_fwlps_enter(struct ieee80211_hw *hw) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, (u8 *)(&fw_current_inps)); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); + &ppsc->fwctrl_psmode); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); } } @@ -400,12 +398,12 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) for (e_aci = 0; e_aci < AC_MAX; e_aci++) { rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); + &e_aci); } break; } case HW_VAR_ACK_PREAMBLE: { u8 reg_tmp; - u8 short_preamble = (bool) (*(u8 *)val); + u8 short_preamble = (bool)*val; reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL + 2); if (short_preamble) { reg_tmp |= 0x02; @@ -416,13 +414,13 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } break; } case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + rtl_write_byte(rtlpriv, REG_SECCFG, *val); break; case HW_VAR_AMPDU_MIN_SPACE: { u8 min_spacing_to_set; u8 sec_min_space; - min_spacing_to_set = *((u8 *)val); + min_spacing_to_set = *val; if (min_spacing_to_set <= 7) { sec_min_space = 0; @@ -445,7 +443,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_SHORTGI_DENSITY: { u8 density_to_set; - density_to_set = *((u8 *)val); + density_to_set = *val; mac->min_space_cfg |= (density_to_set << 3); RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, @@ -463,7 +461,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) p_regtoset = regtoset_normal; - factor_toset = *((u8 *)val); + factor_toset = *val; if (factor_toset <= 3) { factor_toset = (1 << (factor_toset + 2)); if (factor_toset > 0xf) @@ -491,15 +489,15 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } break; } case HW_VAR_AC_PARAM: { - u8 e_aci = *((u8 *)val); + u8 e_aci = *val; rtl8723_dm_init_edca_turbo(hw); if (rtlpci->acm_method != EACMWAY2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); + &e_aci); break; } case HW_VAR_ACM_CTRL: { - u8 e_aci = *((u8 *)val); + u8 e_aci = *val; union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&(mac->ac[0].aifs)); u8 acm = p_aci_aifsn->f.acm; @@ -552,7 +550,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlpci->receive_config = ((u32 *)(val))[0]; break; case HW_VAR_RETRY_LIMIT: { - u8 retry_limit = ((u8 *)(val))[0]; + u8 retry_limit = *val; rtl_write_word(rtlpriv, REG_RL, retry_limit << RETRY_LIMIT_SHORT_SHIFT | @@ -565,7 +563,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtlefuse->efuse_usedbytes = *((u16 *)val); break; case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *)val); + rtlefuse->efuse_usedpercentage = *val; break; case HW_VAR_IO_CMD: rtl8723be_phy_set_io_cmd(hw, (*(enum io_type *)val)); @@ -577,14 +575,13 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) udelay(1); if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val)); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val | BIT(7)); } break; } case HW_VAR_H2C_FW_PWRMODE: - rtl8723be_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + rtl8723be_set_fw_pwrmode_cmd(hw, *val); break; case HW_VAR_FW_PSMODE_STATUS: ppsc->fw_current_inpsmode = *((bool *)val); @@ -602,7 +599,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; } case HW_VAR_H2C_FW_JOINBSSRPT: { - u8 mstatus = (*(u8 *)val); + u8 mstatus = *val; u8 tmp_regcr, tmp_reg422, bcnvalid_reg; u8 count = 0, dlbcn_count = 0; bool recover = false; @@ -657,10 +654,10 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); } - rtl8723be_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); + rtl8723be_set_fw_joinbss_report_cmd(hw, *val); break; } case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl8723be_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + rtl8723be_set_p2p_ps_offload_cmd(hw, *val); break; case HW_VAR_AID: { u16 u2btmp; @@ -670,7 +667,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) (u2btmp | mac->assoc_id)); break; } case HW_VAR_CORRECT_TSF: { - u8 btype_ibss = ((u8 *)(val))[0]; + u8 btype_ibss = *val; if (btype_ibss) _rtl8723be_stop_tx_beacon(hw); @@ -690,7 +687,7 @@ void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_KEEP_ALIVE: { u8 array[2]; array[0] = 0xff; - array[1] = *((u8 *)val); + array[1] = *val; rtl8723be_fill_h2c_cmd(hw, H2C_8723BE_KEEP_ALIVE_CTRL, 2, array); break; } @@ -1783,10 +1780,10 @@ static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw, rtlefuse->autoload_failflag, hwinfo); - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); @@ -2252,8 +2249,7 @@ void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw) struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u16 sifs_timer; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)&mac->slot_time); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); if (!mac->ht_enable) sifs_timer = 0x0a0a; else diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/rtlwifi/rtl8723be/trx.c index 74a75dceab08..e0a0d8c8fed5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/trx.c @@ -647,7 +647,7 @@ void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; + u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; unsigned int buf_len = 0; @@ -850,7 +850,7 @@ void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, SET_TX_DESC_OWN(pdesc, 1); - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c index c12da552b7f7..540278ff462b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c @@ -115,7 +115,7 @@ void rtl8723_write_fw(struct ieee80211_hw *hw, u8 *buffer, u32 size) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *bufferptr = (u8 *)buffer; + u8 *bufferptr = buffer; u32 pagenums, remainsize; u32 page, offset; @@ -257,7 +257,7 @@ int rtl8723_download_fw(struct ieee80211_hw *hw, return 1; pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; - pfwdata = (u8 *)rtlhal->pfirmware; + pfwdata = rtlhal->pfirmware; fwsize = rtlhal->fwsize; RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "normal Firmware SIZE %d\n", fwsize); diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b8cc39a4a9a5..5f8bc05694ac 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -189,6 +189,7 @@ struct hci_dev { __u16 page_scan_window; __u8 page_scan_type; __u8 le_adv_channel_map; + __u8 le_scan_type; __u16 le_scan_interval; __u16 le_scan_window; __u16 le_conn_min_interval; @@ -1236,7 +1237,7 @@ void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, __le32 value, + u8 link_type, u8 addr_type, u32 value, u8 confirm_hint); int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a6a3d32553c5..49774912cb01 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -199,6 +199,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); hdev->scan_rsp_data_len = 0; + hdev->le_scan_type = LE_SCAN_PASSIVE; + hdev->ssp_debug_mode = 0; } @@ -997,6 +999,25 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } +static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_cp_le_set_scan_param *cp; + __u8 status = *((__u8 *) skb->data); + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); + if (!cp) + return; + + hci_dev_lock(hdev); + + if (!status) + hdev->le_scan_type = cp->type; + + hci_dev_unlock(hdev); +} + static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { @@ -1704,6 +1725,36 @@ unlock: hci_dev_unlock(hdev); } +static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) +{ + struct hci_cp_le_start_enc *cp; + struct hci_conn *conn; + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + if (!status) + return; + + hci_dev_lock(hdev); + + cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); + if (!cp) + goto unlock; + + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); + if (!conn) + goto unlock; + + if (conn->state != BT_CONNECTED) + goto unlock; + + hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); + hci_conn_drop(conn); + +unlock: + hci_dev_unlock(hdev); +} + static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); @@ -2488,6 +2539,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cc_le_set_adv_enable(hdev, skb); break; + case HCI_OP_LE_SET_SCAN_PARAM: + hci_cc_le_set_scan_param(hdev, skb); + break; + case HCI_OP_LE_SET_SCAN_ENABLE: hci_cc_le_set_scan_enable(hdev, skb); break; @@ -2611,6 +2666,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_le_create_conn(hdev, ev->status); break; + case HCI_OP_LE_START_ENC: + hci_cs_le_start_enc(hdev, ev->status); + break; + default: BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); break; @@ -3459,8 +3518,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, } confirm: - mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, - confirm_hint); + mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, + le32_to_cpu(ev->passkey), confirm_hint); unlock: hci_dev_unlock(hdev); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 33cd5615ff1e..f59e00c2daa9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -360,7 +360,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, BT_DBG("sock %p, sk %p", sock, sk); - if (peer && sk->sk_state != BT_CONNECTED) + if (peer && sk->sk_state != BT_CONNECTED && + sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) return -ENOTCONN; memset(la, 0, sizeof(struct sockaddr_l2)); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 96670f581bb0..d2d4e0d5aed0 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2762,23 +2762,11 @@ static struct pending_cmd *find_pairing(struct hci_conn *conn) static void pairing_complete(struct pending_cmd *cmd, u8 status) { - const struct mgmt_cp_pair_device *cp = cmd->param; struct mgmt_rp_pair_device rp; struct hci_conn *conn = cmd->user_data; - /* If we had a pairing failure we might have already received - * the remote Identity Address Information and updated the - * hci_conn variables with it, however we would not yet have - * notified user space of the resolved identity. Therefore, use - * the address given in the Pair Device command in case the - * pairing failed. - */ - if (status) { - memcpy(&rp.addr, &cp->addr, sizeof(rp.addr)); - } else { - bacpy(&rp.addr.bdaddr, &conn->dst); - rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); - } + bacpy(&rp.addr.bdaddr, &conn->dst); + rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status, &rp, sizeof(rp)); @@ -5338,7 +5326,7 @@ void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, } int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, __le32 value, + u8 link_type, u8 addr_type, u32 value, u8 confirm_hint) { struct mgmt_ev_user_confirm_request ev; @@ -5348,7 +5336,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, bacpy(&ev.addr.bdaddr, bdaddr); ev.addr.type = link_to_bdaddr(link_type, addr_type); ev.confirm_hint = confirm_hint; - ev.value = value; + ev.value = cpu_to_le32(value); return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev), NULL); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c024e715512f..eabd25ab5ad9 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -534,7 +534,8 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * BT_DBG("sock %p, sk %p", sock, sk); - if (peer && sk->sk_state != BT_CONNECTED) + if (peer && sk->sk_state != BT_CONNECTED && + sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) return -ENOTCONN; memset(sa, 0, sizeof(*sa)); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 2a7ee7f6cd8b..dfb4e1161c10 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -387,6 +387,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) method = JUST_WORKS; + /* Don't confirm locally initiated pairing attempts */ + if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, + &smp->smp_flags)) + method = JUST_WORKS; + /* If Just Works, Continue with Zero TK */ if (method == JUST_WORKS) { set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); @@ -422,10 +427,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, if (method == REQ_PASSKEY) ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type); + else if (method == JUST_CFM) + ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, + hcon->type, hcon->dst_type, + passkey, 1); else ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, - cpu_to_le32(passkey), 0); + passkey, 0); hci_dev_unlock(hcon->hdev); @@ -547,20 +556,6 @@ error: smp_failure(conn, reason); } -static void smp_reencrypt(struct work_struct *work) -{ - struct smp_chan *smp = container_of(work, struct smp_chan, - reencrypt.work); - struct l2cap_conn *conn = smp->conn; - struct hci_conn *hcon = conn->hcon; - struct smp_ltk *ltk = smp->ltk; - - BT_DBG(""); - - hci_le_start_enc(hcon, ltk->ediv, ltk->rand, ltk->val); - hcon->enc_key_size = ltk->enc_size; -} - static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) { struct smp_chan *smp; @@ -571,7 +566,6 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) INIT_WORK(&smp->confirm, confirm_work); INIT_WORK(&smp->random, random_work); - INIT_DELAYED_WORK(&smp->reencrypt, smp_reencrypt); smp->conn = conn; conn->smp_chan = smp; @@ -589,8 +583,6 @@ void smp_chan_destroy(struct l2cap_conn *conn) BUG_ON(!smp); - cancel_delayed_work_sync(&smp->reencrypt); - complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); mgmt_smp_complete(conn->hcon, complete); @@ -712,6 +704,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) if (ret) return SMP_UNSPECIFIED; + clear_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); + return 0; } @@ -867,6 +861,8 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); + clear_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); + return 0; } @@ -884,11 +880,15 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) { struct l2cap_conn *conn = hcon->l2cap_data; - struct smp_chan *smp = conn->smp_chan; + struct smp_chan *smp; __u8 authreq; BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); + /* This may be NULL if there's an unexpected disconnection */ + if (!conn) + return 1; + if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) return 1; @@ -928,6 +928,8 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); } + set_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); + done: hcon->pending_sec_level = sec_level; @@ -1058,12 +1060,6 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, smp->id_addr_type, smp->irk, &rpa); - /* Track the connection based on the Identity Address from now on */ - bacpy(&hcon->dst, &smp->id_addr); - hcon->dst_type = smp->id_addr_type; - - l2cap_conn_update_id_addr(hcon); - smp_distribute_keys(conn); return 0; @@ -1214,8 +1210,16 @@ static void smp_notify_keys(struct l2cap_conn *conn) struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1]; bool persistent; - if (smp->remote_irk) + if (smp->remote_irk) { mgmt_new_irk(hdev, smp->remote_irk); + /* Now that user space can be considered to know the + * identity address track the connection based on it + * from now on. + */ + bacpy(&hcon->dst, &smp->remote_irk->bdaddr); + hcon->dst_type = smp->remote_irk->addr_type; + l2cap_conn_update_id_addr(hcon); + } /* The LTKs and CSRKs should be persistent only if both sides * had the bonding bit set in their authentication requests. @@ -1253,7 +1257,6 @@ int smp_distribute_keys(struct l2cap_conn *conn) struct smp_chan *smp = conn->smp_chan; struct hci_conn *hcon = conn->hcon; struct hci_dev *hdev = hcon->hdev; - bool ltk_encrypt; __u8 *keydist; BT_DBG("conn %p", conn); @@ -1353,32 +1356,12 @@ int smp_distribute_keys(struct l2cap_conn *conn) if ((smp->remote_key_dist & 0x07)) return 0; - /* Check if we should try to re-encrypt the link with the LTK. - * SMP_FLAG_LTK_ENCRYPT flag is used to track whether we've - * already tried this (in which case we shouldn't try again). - * - * The request will trigger an encryption key refresh event - * which will cause a call to auth_cfm and eventually lead to - * l2cap_core.c calling this smp_distribute_keys function again - * and thereby completing the process. - */ - if (smp->ltk) - ltk_encrypt = !test_and_set_bit(SMP_FLAG_LTK_ENCRYPT, - &smp->smp_flags); - else - ltk_encrypt = false; + clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags); + cancel_delayed_work_sync(&conn->security_timer); + set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); + smp_notify_keys(conn); - /* Re-encrypt the link with LTK if possible */ - if (ltk_encrypt && hcon->out) { - queue_delayed_work(hdev->req_workqueue, &smp->reencrypt, - SMP_REENCRYPT_TIMEOUT); - } else { - clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags); - cancel_delayed_work_sync(&conn->security_timer); - set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); - smp_notify_keys(conn); - smp_chan_destroy(conn); - } + smp_chan_destroy(conn); return 0; } diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h index b6913471815a..1277147a9150 100644 --- a/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h @@ -118,10 +118,8 @@ struct smp_cmd_security_req { #define SMP_FLAG_TK_VALID 1 #define SMP_FLAG_CFM_PENDING 2 #define SMP_FLAG_MITM_AUTH 3 -#define SMP_FLAG_LTK_ENCRYPT 4 -#define SMP_FLAG_COMPLETE 5 - -#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(500) +#define SMP_FLAG_COMPLETE 4 +#define SMP_FLAG_INITIATOR 5 struct smp_chan { struct l2cap_conn *conn; @@ -144,7 +142,6 @@ struct smp_chan { unsigned long smp_flags; struct work_struct confirm; struct work_struct random; - struct delayed_work reencrypt; }; /* SMP Commands */ |