diff options
-rw-r--r-- | drivers/net/wireless/rtl8187_dev.c | 208 |
1 files changed, 168 insertions, 40 deletions
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index b17f237c9e28..3bc4a1c39258 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -155,9 +155,11 @@ static void rtl8187_tx_cb(struct urb *urb) | |||
155 | struct sk_buff *skb = (struct sk_buff *)urb->context; | 155 | struct sk_buff *skb = (struct sk_buff *)urb->context; |
156 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 156 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
157 | struct ieee80211_hw *hw = info->driver_data[0]; | 157 | struct ieee80211_hw *hw = info->driver_data[0]; |
158 | struct rtl8187_priv *priv = hw->priv; | ||
158 | 159 | ||
159 | usb_free_urb(info->driver_data[1]); | 160 | usb_free_urb(info->driver_data[1]); |
160 | skb_pull(skb, sizeof(struct rtl8187_tx_hdr)); | 161 | skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : |
162 | sizeof(struct rtl8187_tx_hdr)); | ||
161 | memset(&info->status, 0, sizeof(info->status)); | 163 | memset(&info->status, 0, sizeof(info->status)); |
162 | info->flags |= IEEE80211_TX_STAT_ACK; | 164 | info->flags |= IEEE80211_TX_STAT_ACK; |
163 | ieee80211_tx_status_irqsafe(hw, skb); | 165 | ieee80211_tx_status_irqsafe(hw, skb); |
@@ -167,7 +169,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
167 | { | 169 | { |
168 | struct rtl8187_priv *priv = dev->priv; | 170 | struct rtl8187_priv *priv = dev->priv; |
169 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 171 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
170 | struct rtl8187_tx_hdr *hdr; | 172 | unsigned int ep; |
173 | void *buf; | ||
171 | struct urb *urb; | 174 | struct urb *urb; |
172 | __le16 rts_dur = 0; | 175 | __le16 rts_dur = 0; |
173 | u32 flags; | 176 | u32 flags; |
@@ -195,16 +198,47 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
195 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 198 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
196 | } | 199 | } |
197 | 200 | ||
198 | hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); | 201 | if (!priv->is_rtl8187b) { |
199 | hdr->flags = cpu_to_le32(flags); | 202 | struct rtl8187_tx_hdr *hdr = |
200 | hdr->len = 0; | 203 | (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); |
201 | hdr->rts_duration = rts_dur; | 204 | hdr->flags = cpu_to_le32(flags); |
202 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | 205 | hdr->len = 0; |
206 | hdr->rts_duration = rts_dur; | ||
207 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | ||
208 | buf = hdr; | ||
209 | |||
210 | ep = 2; | ||
211 | } else { | ||
212 | /* fc needs to be calculated before skb_push() */ | ||
213 | unsigned int epmap[4] = { 6, 7, 5, 4 }; | ||
214 | struct ieee80211_hdr *tx_hdr = | ||
215 | (struct ieee80211_hdr *)(skb->data); | ||
216 | u16 fc = le16_to_cpu(tx_hdr->frame_control); | ||
217 | |||
218 | struct rtl8187b_tx_hdr *hdr = | ||
219 | (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); | ||
220 | struct ieee80211_rate *txrate = | ||
221 | ieee80211_get_tx_rate(dev, info); | ||
222 | memset(hdr, 0, sizeof(*hdr)); | ||
223 | hdr->flags = cpu_to_le32(flags); | ||
224 | hdr->rts_duration = rts_dur; | ||
225 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | ||
226 | hdr->tx_duration = | ||
227 | ieee80211_generic_frame_duration(dev, priv->vif, | ||
228 | skb->len, txrate); | ||
229 | buf = hdr; | ||
230 | |||
231 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | ||
232 | ep = 12; | ||
233 | else | ||
234 | ep = epmap[skb_get_queue_mapping(skb)]; | ||
235 | } | ||
203 | 236 | ||
204 | info->driver_data[0] = dev; | 237 | info->driver_data[0] = dev; |
205 | info->driver_data[1] = urb; | 238 | info->driver_data[1] = urb; |
206 | usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), | 239 | |
207 | hdr, skb->len, rtl8187_tx_cb, skb); | 240 | usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), |
241 | buf, skb->len, rtl8187_tx_cb, skb); | ||
208 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 242 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
209 | if (rc < 0) { | 243 | if (rc < 0) { |
210 | usb_free_urb(urb); | 244 | usb_free_urb(urb); |
@@ -220,7 +254,6 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
220 | struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; | 254 | struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; |
221 | struct ieee80211_hw *dev = info->dev; | 255 | struct ieee80211_hw *dev = info->dev; |
222 | struct rtl8187_priv *priv = dev->priv; | 256 | struct rtl8187_priv *priv = dev->priv; |
223 | struct rtl8187_rx_hdr *hdr; | ||
224 | struct ieee80211_rx_status rx_status = { 0 }; | 257 | struct ieee80211_rx_status rx_status = { 0 }; |
225 | int rate, signal; | 258 | int rate, signal; |
226 | u32 flags; | 259 | u32 flags; |
@@ -241,11 +274,33 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
241 | } | 274 | } |
242 | 275 | ||
243 | skb_put(skb, urb->actual_length); | 276 | skb_put(skb, urb->actual_length); |
244 | hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); | 277 | if (!priv->is_rtl8187b) { |
245 | flags = le32_to_cpu(hdr->flags); | 278 | struct rtl8187_rx_hdr *hdr = |
246 | skb_trim(skb, flags & 0x0FFF); | 279 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
280 | flags = le32_to_cpu(hdr->flags); | ||
281 | signal = hdr->signal & 0x7f; | ||
282 | rx_status.antenna = (hdr->signal >> 7) & 1; | ||
283 | rx_status.signal = signal; | ||
284 | rx_status.noise = hdr->noise; | ||
285 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
286 | priv->signal = signal; | ||
287 | priv->quality = signal; | ||
288 | priv->noise = hdr->noise; | ||
289 | } else { | ||
290 | struct rtl8187b_rx_hdr *hdr = | ||
291 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); | ||
292 | flags = le32_to_cpu(hdr->flags); | ||
293 | signal = hdr->agc >> 1; | ||
294 | rx_status.antenna = (hdr->signal >> 7) & 1; | ||
295 | rx_status.signal = 64 - min(hdr->noise, (u8)64); | ||
296 | rx_status.noise = hdr->noise; | ||
297 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
298 | priv->signal = hdr->signal; | ||
299 | priv->quality = hdr->agc >> 1; | ||
300 | priv->noise = hdr->noise; | ||
301 | } | ||
247 | 302 | ||
248 | signal = hdr->agc >> 1; | 303 | skb_trim(skb, flags & 0x0FFF); |
249 | rate = (flags >> 20) & 0xF; | 304 | rate = (flags >> 20) & 0xF; |
250 | if (rate > 3) { /* OFDM rate */ | 305 | if (rate > 3) { /* OFDM rate */ |
251 | if (signal > 90) | 306 | if (signal > 90) |
@@ -261,13 +316,11 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
261 | signal = 95 - signal; | 316 | signal = 95 - signal; |
262 | } | 317 | } |
263 | 318 | ||
264 | rx_status.antenna = (hdr->signal >> 7) & 1; | 319 | rx_status.qual = priv->quality; |
265 | rx_status.qual = 64 - min(hdr->noise, (u8)64); | ||
266 | rx_status.signal = signal; | 320 | rx_status.signal = signal; |
267 | rx_status.rate_idx = rate; | 321 | rx_status.rate_idx = rate; |
268 | rx_status.freq = dev->conf.channel->center_freq; | 322 | rx_status.freq = dev->conf.channel->center_freq; |
269 | rx_status.band = dev->conf.channel->band; | 323 | rx_status.band = dev->conf.channel->band; |
270 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
271 | rx_status.flag |= RX_FLAG_TSFT; | 324 | rx_status.flag |= RX_FLAG_TSFT; |
272 | if (flags & (1 << 13)) | 325 | if (flags & (1 << 13)) |
273 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 326 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
@@ -307,7 +360,8 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) | |||
307 | break; | 360 | break; |
308 | } | 361 | } |
309 | usb_fill_bulk_urb(entry, priv->udev, | 362 | usb_fill_bulk_urb(entry, priv->udev, |
310 | usb_rcvbulkpipe(priv->udev, 1), | 363 | usb_rcvbulkpipe(priv->udev, |
364 | priv->is_rtl8187b ? 3 : 1), | ||
311 | skb_tail_pointer(skb), | 365 | skb_tail_pointer(skb), |
312 | RTL8187_MAX_RX, rtl8187_rx_cb, skb); | 366 | RTL8187_MAX_RX, rtl8187_rx_cb, skb); |
313 | info = (struct rtl8187_rx_info *)skb->cb; | 367 | info = (struct rtl8187_rx_info *)skb->cb; |
@@ -786,18 +840,20 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) | |||
786 | msleep(10); | 840 | msleep(10); |
787 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); | 841 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); |
788 | 842 | ||
789 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | 843 | if (!priv->is_rtl8187b) { |
790 | 844 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | |
791 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { | 845 | |
792 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); | 846 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { |
793 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); | 847 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); |
794 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); | 848 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); |
795 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); | 849 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); |
796 | } else { | 850 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); |
797 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); | 851 | } else { |
798 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); | 852 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); |
799 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); | 853 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); |
800 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | 854 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); |
855 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | ||
856 | } | ||
801 | } | 857 | } |
802 | 858 | ||
803 | rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); | 859 | rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); |
@@ -813,14 +869,20 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, | |||
813 | { | 869 | { |
814 | struct rtl8187_priv *priv = dev->priv; | 870 | struct rtl8187_priv *priv = dev->priv; |
815 | int i; | 871 | int i; |
872 | u8 reg; | ||
816 | 873 | ||
817 | for (i = 0; i < ETH_ALEN; i++) | 874 | for (i = 0; i < ETH_ALEN; i++) |
818 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); | 875 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); |
819 | 876 | ||
820 | if (is_valid_ether_addr(conf->bssid)) | 877 | if (is_valid_ether_addr(conf->bssid)) { |
821 | rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); | 878 | reg = RTL818X_MSR_INFRA; |
822 | else | 879 | if (priv->is_rtl8187b) |
823 | rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); | 880 | reg |= RTL818X_MSR_ENEDCA; |
881 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
882 | } else { | ||
883 | reg = RTL818X_MSR_NO_LINK; | ||
884 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
885 | } | ||
824 | 886 | ||
825 | return 0; | 887 | return 0; |
826 | } | 888 | } |
@@ -907,6 +969,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
907 | struct rtl8187_priv *priv; | 969 | struct rtl8187_priv *priv; |
908 | struct eeprom_93cx6 eeprom; | 970 | struct eeprom_93cx6 eeprom; |
909 | struct ieee80211_channel *channel; | 971 | struct ieee80211_channel *channel; |
972 | const char *chip_name; | ||
910 | u16 txpwr, reg; | 973 | u16 txpwr, reg; |
911 | int err, i; | 974 | int err, i; |
912 | DECLARE_MAC_BUF(mac); | 975 | DECLARE_MAC_BUF(mac); |
@@ -918,6 +981,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
918 | } | 981 | } |
919 | 982 | ||
920 | priv = dev->priv; | 983 | priv = dev->priv; |
984 | priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) || | ||
985 | !memcmp(udev->product, "RTL8187B", 8); | ||
921 | 986 | ||
922 | SET_IEEE80211_DEV(dev, &intf->dev); | 987 | SET_IEEE80211_DEV(dev, &intf->dev); |
923 | usb_set_intfdata(intf, dev); | 988 | usb_set_intfdata(intf, dev); |
@@ -946,8 +1011,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
946 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1011 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
947 | IEEE80211_HW_RX_INCLUDES_FCS | | 1012 | IEEE80211_HW_RX_INCLUDES_FCS | |
948 | IEEE80211_HW_SIGNAL_UNSPEC; | 1013 | IEEE80211_HW_SIGNAL_UNSPEC; |
949 | dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); | 1014 | dev->extra_tx_headroom = (!priv->is_rtl8187b) ? |
950 | dev->queues = 1; | 1015 | sizeof(struct rtl8187_tx_hdr) : |
1016 | sizeof(struct rtl8187b_tx_hdr); | ||
1017 | if (!priv->is_rtl8187b) | ||
1018 | dev->queues = 1; | ||
1019 | else | ||
1020 | dev->queues = 4; | ||
951 | dev->max_signal = 65; | 1021 | dev->max_signal = 65; |
952 | 1022 | ||
953 | eeprom.data = dev; | 1023 | eeprom.data = dev; |
@@ -982,10 +1052,24 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
982 | (*channel++).hw_value = txpwr & 0xFF; | 1052 | (*channel++).hw_value = txpwr & 0xFF; |
983 | (*channel++).hw_value = txpwr >> 8; | 1053 | (*channel++).hw_value = txpwr >> 8; |
984 | } | 1054 | } |
985 | for (i = 0; i < 2; i++) { | 1055 | if (!priv->is_rtl8187b) { |
986 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, | 1056 | for (i = 0; i < 2; i++) { |
1057 | eeprom_93cx6_read(&eeprom, | ||
1058 | RTL8187_EEPROM_TXPWR_CHAN_6 + i, | ||
1059 | &txpwr); | ||
1060 | (*channel++).hw_value = txpwr & 0xFF; | ||
1061 | (*channel++).hw_value = txpwr >> 8; | ||
1062 | } | ||
1063 | } else { | ||
1064 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, | ||
987 | &txpwr); | 1065 | &txpwr); |
988 | (*channel++).hw_value = txpwr & 0xFF; | 1066 | (*channel++).hw_value = txpwr & 0xFF; |
1067 | |||
1068 | eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); | ||
1069 | (*channel++).hw_value = txpwr & 0xFF; | ||
1070 | |||
1071 | eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); | ||
1072 | (*channel++).hw_value = txpwr & 0xFF; | ||
989 | (*channel++).hw_value = txpwr >> 8; | 1073 | (*channel++).hw_value = txpwr >> 8; |
990 | } | 1074 | } |
991 | 1075 | ||
@@ -1001,6 +1085,50 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1001 | rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); | 1085 | rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); |
1002 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1086 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
1003 | 1087 | ||
1088 | if (!priv->is_rtl8187b) { | ||
1089 | u32 reg32; | ||
1090 | reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); | ||
1091 | reg32 &= RTL818X_TX_CONF_HWVER_MASK; | ||
1092 | switch (reg32) { | ||
1093 | case RTL818X_TX_CONF_R8187vD_1: | ||
1094 | case RTL818X_TX_CONF_R8187vD_2: | ||
1095 | chip_name = "RTL8187vD"; | ||
1096 | break; | ||
1097 | default: | ||
1098 | chip_name = "RTL8187vB (default)"; | ||
1099 | } | ||
1100 | } else { | ||
1101 | printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " | ||
1102 | "is EXPERIMENTAL, and could damage your\n" | ||
1103 | " hardware, use at your own risk\n"); | ||
1104 | /* | ||
1105 | * Force USB request to write radio registers for 8187B, Realtek | ||
1106 | * only uses it in their sources | ||
1107 | */ | ||
1108 | /*if (priv->asic_rev == 0) { | ||
1109 | printk(KERN_WARNING "rtl8187: Forcing use of USB " | ||
1110 | "requests to write to radio registers\n"); | ||
1111 | priv->asic_rev = 1; | ||
1112 | }*/ | ||
1113 | switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { | ||
1114 | case RTL818X_R8187B_B: | ||
1115 | chip_name = "RTL8187BvB"; | ||
1116 | priv->hw_rev = RTL8187BvB; | ||
1117 | break; | ||
1118 | case RTL818X_R8187B_D: | ||
1119 | chip_name = "RTL8187BvD"; | ||
1120 | priv->hw_rev = RTL8187BvD; | ||
1121 | break; | ||
1122 | case RTL818X_R8187B_E: | ||
1123 | chip_name = "RTL8187BvE"; | ||
1124 | priv->hw_rev = RTL8187BvE; | ||
1125 | break; | ||
1126 | default: | ||
1127 | chip_name = "RTL8187BvB (default)"; | ||
1128 | priv->hw_rev = RTL8187BvB; | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1004 | priv->rf = rtl8187_detect_rf(dev); | 1132 | priv->rf = rtl8187_detect_rf(dev); |
1005 | 1133 | ||
1006 | err = ieee80211_register_hw(dev); | 1134 | err = ieee80211_register_hw(dev); |
@@ -1009,9 +1137,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1009 | goto err_free_dev; | 1137 | goto err_free_dev; |
1010 | } | 1138 | } |
1011 | 1139 | ||
1012 | printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", | 1140 | printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", |
1013 | wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), | 1141 | wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), |
1014 | priv->asic_rev, priv->rf->name); | 1142 | chip_name, priv->asic_rev, priv->rf->name); |
1015 | 1143 | ||
1016 | return 0; | 1144 | return 0; |
1017 | 1145 | ||