rtlwifi: Fix endian error in extracting packet type
All of the rtlwifi drivers have an error in the routine that tests if the data is "special". If it is, the subsequant transmission will be at the lowest rate to enhance reliability. The 16-bit quantity is big-endian, but was being extracted in native CPU mode. One of the effects of this bug is to inhibit association under some conditions as the TX rate is too high. Based on suggestions by Joe Perches, the entire routine is rewritten. One of the local headers contained duplicates of some of the ETH_P_XXX definitions. These are deleted. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Cc: Stable <stable@vger.kernel.org> [2.6.38+] Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4be6718c66
commit
0c5d63f0ab
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/udp.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*NOTICE!!!: This file will be very big, we should
|
*NOTICE!!!: This file will be very big, we should
|
||||||
|
@ -1074,64 +1075,52 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
|
||||||
if (!ieee80211_is_data(fc))
|
if (!ieee80211_is_data(fc))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ip = (const struct iphdr *)(skb->data + mac_hdr_len +
|
||||||
ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
|
|
||||||
SNAP_SIZE + PROTOC_TYPE_SIZE);
|
SNAP_SIZE + PROTOC_TYPE_SIZE);
|
||||||
ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
|
ether_type = be16_to_cpup((__be16 *)
|
||||||
/* ether_type = ntohs(ether_type); */
|
(skb->data + mac_hdr_len + SNAP_SIZE));
|
||||||
|
|
||||||
if (ETH_P_IP == ether_type) {
|
switch (ether_type) {
|
||||||
if (IPPROTO_UDP == ip->protocol) {
|
case ETH_P_IP: {
|
||||||
struct udphdr *udp = (struct udphdr *)((u8 *) ip +
|
struct udphdr *udp;
|
||||||
(ip->ihl << 2));
|
u16 src;
|
||||||
if (((((u8 *) udp)[1] == 68) &&
|
u16 dst;
|
||||||
(((u8 *) udp)[3] == 67)) ||
|
|
||||||
((((u8 *) udp)[1] == 67) &&
|
if (ip->protocol != IPPROTO_UDP)
|
||||||
(((u8 *) udp)[3] == 68))) {
|
return false;
|
||||||
/*
|
udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
|
||||||
* 68 : UDP BOOTP client
|
src = be16_to_cpu(udp->source);
|
||||||
* 67 : UDP BOOTP server
|
dst = be16_to_cpu(udp->dest);
|
||||||
|
|
||||||
|
/* If this case involves port 68 (UDP BOOTP client) connecting
|
||||||
|
* with port 67 (UDP BOOTP server), then return true so that
|
||||||
|
* the lowest speed is used.
|
||||||
*/
|
*/
|
||||||
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
|
if (!((src == 68 && dst == 67) || (src == 67 && dst == 68)))
|
||||||
DBG_DMESG, "dhcp %s !!\n",
|
return false;
|
||||||
is_tx ? "Tx" : "Rx");
|
|
||||||
|
|
||||||
if (is_tx) {
|
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
||||||
rtlpriv->enter_ps = false;
|
"dhcp %s !!\n", is_tx ? "Tx" : "Rx");
|
||||||
schedule_work(&rtlpriv->
|
break;
|
||||||
works.lps_change_work);
|
|
||||||
ppsc->last_delaylps_stamp_jiffies =
|
|
||||||
jiffies;
|
|
||||||
}
|
}
|
||||||
|
case ETH_P_ARP:
|
||||||
return true;
|
break;
|
||||||
}
|
case ETH_P_PAE:
|
||||||
}
|
|
||||||
} else if (ETH_P_ARP == ether_type) {
|
|
||||||
if (is_tx) {
|
|
||||||
rtlpriv->enter_ps = false;
|
|
||||||
schedule_work(&rtlpriv->works.lps_change_work);
|
|
||||||
ppsc->last_delaylps_stamp_jiffies = jiffies;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else if (ETH_P_PAE == ether_type) {
|
|
||||||
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
||||||
"802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
|
"802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
|
||||||
|
break;
|
||||||
|
case ETH_P_IPV6:
|
||||||
|
/* TODO: Is this right? */
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (is_tx) {
|
if (is_tx) {
|
||||||
rtlpriv->enter_ps = false;
|
rtlpriv->enter_ps = false;
|
||||||
schedule_work(&rtlpriv->works.lps_change_work);
|
schedule_work(&rtlpriv->works.lps_change_work);
|
||||||
ppsc->last_delaylps_stamp_jiffies = jiffies;
|
ppsc->last_delaylps_stamp_jiffies = jiffies;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (ETH_P_IPV6 == ether_type) {
|
|
||||||
/* IPv6 */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rtl_is_special_data);
|
EXPORT_SYMBOL_GPL(rtl_is_special_data);
|
||||||
|
|
||||||
|
|
|
@ -77,11 +77,7 @@
|
||||||
#define RTL_SLOT_TIME_9 9
|
#define RTL_SLOT_TIME_9 9
|
||||||
#define RTL_SLOT_TIME_20 20
|
#define RTL_SLOT_TIME_20 20
|
||||||
|
|
||||||
/*related with tcp/ip. */
|
/*related to tcp/ip. */
|
||||||
/*if_ehther.h*/
|
|
||||||
#define ETH_P_PAE 0x888E /*Port Access Entity (IEEE 802.1X) */
|
|
||||||
#define ETH_P_IP 0x0800 /*Internet Protocol packet */
|
|
||||||
#define ETH_P_ARP 0x0806 /*Address Resolution packet */
|
|
||||||
#define SNAP_SIZE 6
|
#define SNAP_SIZE 6
|
||||||
#define PROTOC_TYPE_SIZE 2
|
#define PROTOC_TYPE_SIZE 2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue