aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2200.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2006-04-13 05:19:11 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-04-24 16:15:54 -0400
commita5cf4fe65144ff2f35de37c7b58e7ab8ffd84d19 (patch)
tree405454d2816152c41e0e40d7846c9de18ae927d2 /drivers/net/wireless/ipw2200.c
parent00d21de5c685ab450ef376acdd1b733badb6b50d (diff)
[PATCH] ipw2200: Fix TX QoS enabled frames problem
This patch works with the ieee80211 stack to set the correct QoS bit to the ipw2200 card. It fixed the TX failure problem for using WPA with QoS. Signed-off-by: Hong Liu <hong.liu@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
-rw-r--r--drivers/net/wireless/ipw2200.c71
1 files changed, 33 insertions, 38 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index a879edba5fac..0500e8006a14 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -6859,61 +6859,55 @@ static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority)
6859 return from_priority_to_tx_queue[priority] - 1; 6859 return from_priority_to_tx_queue[priority] - 1;
6860} 6860}
6861 6861
6862/* 6862static int ipw_is_qos_active(struct net_device *dev,
6863* add QoS parameter to the TX command 6863 struct sk_buff *skb)
6864*/
6865static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
6866 u16 priority,
6867 struct tfd_data *tfd, u8 unicast)
6868{ 6864{
6869 int ret = 0; 6865 struct ipw_priv *priv = ieee80211_priv(dev);
6870 int tx_queue_id = 0;
6871 struct ieee80211_qos_data *qos_data = NULL; 6866 struct ieee80211_qos_data *qos_data = NULL;
6872 int active, supported; 6867 int active, supported;
6873 unsigned long flags; 6868 u8 *daddr = skb->data + ETH_ALEN;
6869 int unicast = !is_multicast_ether_addr(daddr);
6874 6870
6875 if (!(priv->status & STATUS_ASSOCIATED)) 6871 if (!(priv->status & STATUS_ASSOCIATED))
6876 return 0; 6872 return 0;
6877 6873
6878 qos_data = &priv->assoc_network->qos_data; 6874 qos_data = &priv->assoc_network->qos_data;
6879 6875
6880 spin_lock_irqsave(&priv->ieee->lock, flags);
6881
6882 if (priv->ieee->iw_mode == IW_MODE_ADHOC) { 6876 if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
6883 if (unicast == 0) 6877 if (unicast == 0)
6884 qos_data->active = 0; 6878 qos_data->active = 0;
6885 else 6879 else
6886 qos_data->active = qos_data->supported; 6880 qos_data->active = qos_data->supported;
6887 } 6881 }
6888
6889 active = qos_data->active; 6882 active = qos_data->active;
6890 supported = qos_data->supported; 6883 supported = qos_data->supported;
6891
6892 spin_unlock_irqrestore(&priv->ieee->lock, flags);
6893
6894 IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " 6884 IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d "
6895 "unicast %d\n", 6885 "unicast %d\n",
6896 priv->qos_data.qos_enable, active, supported, unicast); 6886 priv->qos_data.qos_enable, active, supported, unicast);
6897 if (active && priv->qos_data.qos_enable) { 6887 if (active && priv->qos_data.qos_enable)
6898 ret = from_priority_to_tx_queue[priority]; 6888 return 1;
6899 tx_queue_id = ret - 1;
6900 IPW_DEBUG_QOS("QoS packet priority is %d \n", priority);
6901 if (priority <= 7) {
6902 tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
6903 tfd->tfd.tfd_26.mchdr.qos_ctrl = priority;
6904 tfd->tfd.tfd_26.mchdr.frame_ctl |=
6905 IEEE80211_STYPE_QOS_DATA;
6906
6907 if (priv->qos_data.qos_no_ack_mask &
6908 (1UL << tx_queue_id)) {
6909 tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
6910 tfd->tfd.tfd_26.mchdr.qos_ctrl |=
6911 CTRL_QOS_NO_ACK;
6912 }
6913 }
6914 }
6915 6889
6916 return ret; 6890 return 0;
6891
6892}
6893/*
6894* add QoS parameter to the TX command
6895*/
6896static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
6897 u16 priority,
6898 struct tfd_data *tfd)
6899{
6900 int tx_queue_id = 0;
6901
6902
6903 tx_queue_id = from_priority_to_tx_queue[priority] - 1;
6904 tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
6905
6906 if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) {
6907 tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
6908 tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK;
6909 }
6910 return 0;
6917} 6911}
6918 6912
6919/* 6913/*
@@ -9653,7 +9647,7 @@ we need to heavily modify the ieee80211_skb_to_txb.
9653static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, 9647static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
9654 int pri) 9648 int pri)
9655{ 9649{
9656 struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) 9650 struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *)
9657 txb->fragments[0]->data; 9651 txb->fragments[0]->data;
9658 int i = 0; 9652 int i = 0;
9659 struct tfd_frame *tfd; 9653 struct tfd_frame *tfd;
@@ -9668,9 +9662,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
9668 u16 remaining_bytes; 9662 u16 remaining_bytes;
9669 int fc; 9663 int fc;
9670 9664
9665 hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
9671 switch (priv->ieee->iw_mode) { 9666 switch (priv->ieee->iw_mode) {
9672 case IW_MODE_ADHOC: 9667 case IW_MODE_ADHOC:
9673 hdr_len = IEEE80211_3ADDR_LEN;
9674 unicast = !is_multicast_ether_addr(hdr->addr1); 9668 unicast = !is_multicast_ether_addr(hdr->addr1);
9675 id = ipw_find_station(priv, hdr->addr1); 9669 id = ipw_find_station(priv, hdr->addr1);
9676 if (id == IPW_INVALID_STATION) { 9670 if (id == IPW_INVALID_STATION) {
@@ -9687,7 +9681,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
9687 case IW_MODE_INFRA: 9681 case IW_MODE_INFRA:
9688 default: 9682 default:
9689 unicast = !is_multicast_ether_addr(hdr->addr3); 9683 unicast = !is_multicast_ether_addr(hdr->addr3);
9690 hdr_len = IEEE80211_3ADDR_LEN;
9691 id = 0; 9684 id = 0;
9692 break; 9685 break;
9693 } 9686 }
@@ -9766,7 +9759,8 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
9766 tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; 9759 tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP;
9767 9760
9768#ifdef CONFIG_IPW_QOS 9761#ifdef CONFIG_IPW_QOS
9769 ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); 9762 if (fc & IEEE80211_STYPE_QOS_DATA)
9763 ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data));
9770#endif /* CONFIG_IPW_QOS */ 9764#endif /* CONFIG_IPW_QOS */
9771 9765
9772 /* payload */ 9766 /* payload */
@@ -10966,6 +10960,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
10966 priv->ieee->is_queue_full = ipw_net_is_queue_full; 10960 priv->ieee->is_queue_full = ipw_net_is_queue_full;
10967 10961
10968#ifdef CONFIG_IPW_QOS 10962#ifdef CONFIG_IPW_QOS
10963 priv->ieee->is_qos_active = ipw_is_qos_active;
10969 priv->ieee->handle_probe_response = ipw_handle_beacon; 10964 priv->ieee->handle_probe_response = ipw_handle_beacon;
10970 priv->ieee->handle_beacon = ipw_handle_probe_response; 10965 priv->ieee->handle_beacon = ipw_handle_probe_response;
10971 priv->ieee->handle_assoc_response = ipw_handle_assoc_response; 10966 priv->ieee->handle_assoc_response = ipw_handle_assoc_response;