diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-05-15 06:55:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:11 -0400 |
commit | e039fa4a4195ac4ee895e6f3d1334beed63256fe (patch) | |
tree | cfd0762d73df96b73052378be7b157c4ac6e7035 /drivers/net/wireless/rt2x00/rt2x00mac.c | |
parent | e24549485f859be6518929bb1c9c0257d79f033d (diff) |
mac80211: move TX info into skb->cb
This patch converts mac80211 and all drivers to have transmit
information and status in skb->cb rather than allocating extra
memory for it and copying all the data around. To make it fit,
a union is used where only data that is necessary for all steps
is kept outside of the union.
A number of fixes were done by Ivo, as well as the rt2x00 part
of this patch.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c5cedb29b87d..b5379b027b18 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -31,14 +31,15 @@ | |||
31 | 31 | ||
32 | static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | 32 | static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, |
33 | struct data_queue *queue, | 33 | struct data_queue *queue, |
34 | struct sk_buff *frag_skb, | 34 | struct sk_buff *frag_skb) |
35 | struct ieee80211_tx_control *control) | ||
36 | { | 35 | { |
36 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); | ||
37 | struct skb_frame_desc *skbdesc; | 37 | struct skb_frame_desc *skbdesc; |
38 | struct ieee80211_tx_info *rts_info; | ||
38 | struct sk_buff *skb; | 39 | struct sk_buff *skb; |
39 | int size; | 40 | int size; |
40 | 41 | ||
41 | if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) | 42 | if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) |
42 | size = sizeof(struct ieee80211_cts); | 43 | size = sizeof(struct ieee80211_cts); |
43 | else | 44 | else |
44 | size = sizeof(struct ieee80211_rts); | 45 | size = sizeof(struct ieee80211_rts); |
@@ -52,13 +53,33 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
52 | skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); | 53 | skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); |
53 | skb_put(skb, size); | 54 | skb_put(skb, size); |
54 | 55 | ||
55 | if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) | 56 | /* |
56 | ieee80211_ctstoself_get(rt2x00dev->hw, control->vif, | 57 | * Copy TX information over from original frame to |
57 | frag_skb->data, frag_skb->len, control, | 58 | * RTS/CTS frame. Note that we set the no encryption flag |
59 | * since we don't want this frame to be encrypted. | ||
60 | * RTS frames should be acked, while CTS-to-self frames | ||
61 | * should not. The ready for TX flag is cleared to prevent | ||
62 | * it being automatically send when the descriptor is | ||
63 | * written to the hardware. | ||
64 | */ | ||
65 | memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); | ||
66 | rts_info = IEEE80211_SKB_CB(skb); | ||
67 | rts_info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
68 | rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; | ||
69 | rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
70 | |||
71 | if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) | ||
72 | rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
73 | else | ||
74 | rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; | ||
75 | |||
76 | if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) | ||
77 | ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, | ||
78 | frag_skb->data, size, tx_info, | ||
58 | (struct ieee80211_cts *)(skb->data)); | 79 | (struct ieee80211_cts *)(skb->data)); |
59 | else | 80 | else |
60 | ieee80211_rts_get(rt2x00dev->hw, control->vif, | 81 | ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif, |
61 | frag_skb->data, frag_skb->len, control, | 82 | frag_skb->data, size, tx_info, |
62 | (struct ieee80211_rts *)(skb->data)); | 83 | (struct ieee80211_rts *)(skb->data)); |
63 | 84 | ||
64 | /* | 85 | /* |
@@ -68,7 +89,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
68 | memset(skbdesc, 0, sizeof(*skbdesc)); | 89 | memset(skbdesc, 0, sizeof(*skbdesc)); |
69 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; | 90 | skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; |
70 | 91 | ||
71 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { | 92 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { |
72 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); | 93 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); |
73 | return NETDEV_TX_BUSY; | 94 | return NETDEV_TX_BUSY; |
74 | } | 95 | } |
@@ -76,14 +97,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
76 | return NETDEV_TX_OK; | 97 | return NETDEV_TX_OK; |
77 | } | 98 | } |
78 | 99 | ||
79 | int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | 100 | int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
80 | struct ieee80211_tx_control *control) | ||
81 | { | 101 | { |
82 | struct rt2x00_dev *rt2x00dev = hw->priv; | 102 | struct rt2x00_dev *rt2x00dev = hw->priv; |
103 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
83 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; | 104 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; |
84 | enum data_queue_qid qid = mac80211_queue_to_qid(control->queue); | 105 | enum data_queue_qid qid = mac80211_queue_to_qid(tx_info->queue); |
85 | struct data_queue *queue; | 106 | struct data_queue *queue; |
86 | struct skb_frame_desc *skbdesc; | ||
87 | u16 frame_control; | 107 | u16 frame_control; |
88 | 108 | ||
89 | /* | 109 | /* |
@@ -100,7 +120,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
100 | /* | 120 | /* |
101 | * Determine which queue to put packet on. | 121 | * Determine which queue to put packet on. |
102 | */ | 122 | */ |
103 | if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM && | 123 | if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && |
104 | test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) | 124 | test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) |
105 | queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM); | 125 | queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM); |
106 | else | 126 | else |
@@ -125,33 +145,27 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
125 | */ | 145 | */ |
126 | frame_control = le16_to_cpu(ieee80211hdr->frame_control); | 146 | frame_control = le16_to_cpu(ieee80211hdr->frame_control); |
127 | if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) && | 147 | if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) && |
128 | (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS | | 148 | (tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | |
129 | IEEE80211_TXCTL_USE_CTS_PROTECT)) && | 149 | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && |
130 | !rt2x00dev->ops->hw->set_rts_threshold) { | 150 | !rt2x00dev->ops->hw->set_rts_threshold) { |
131 | if (rt2x00queue_available(queue) <= 1) { | 151 | if (rt2x00queue_available(queue) <= 1) { |
132 | ieee80211_stop_queue(rt2x00dev->hw, control->queue); | 152 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); |
133 | return NETDEV_TX_BUSY; | 153 | return NETDEV_TX_BUSY; |
134 | } | 154 | } |
135 | 155 | ||
136 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) { | 156 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) { |
137 | ieee80211_stop_queue(rt2x00dev->hw, control->queue); | 157 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); |
138 | return NETDEV_TX_BUSY; | 158 | return NETDEV_TX_BUSY; |
139 | } | 159 | } |
140 | } | 160 | } |
141 | 161 | ||
142 | /* | 162 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) { |
143 | * Initialize skb descriptor | 163 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); |
144 | */ | ||
145 | skbdesc = get_skb_frame_desc(skb); | ||
146 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
147 | |||
148 | if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { | ||
149 | ieee80211_stop_queue(rt2x00dev->hw, control->queue); | ||
150 | return NETDEV_TX_BUSY; | 164 | return NETDEV_TX_BUSY; |
151 | } | 165 | } |
152 | 166 | ||
153 | if (rt2x00queue_full(queue)) | 167 | if (rt2x00queue_full(queue)) |
154 | ieee80211_stop_queue(rt2x00dev->hw, control->queue); | 168 | ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue); |
155 | 169 | ||
156 | if (rt2x00dev->ops->lib->kick_tx_queue) | 170 | if (rt2x00dev->ops->lib->kick_tx_queue) |
157 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid); | 171 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid); |
@@ -380,9 +394,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, | |||
380 | if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) | 394 | if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) |
381 | return 0; | 395 | return 0; |
382 | 396 | ||
383 | status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, | 397 | status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon); |
384 | conf->beacon, | ||
385 | conf->beacon_control); | ||
386 | if (status) | 398 | if (status) |
387 | dev_kfree_skb(conf->beacon); | 399 | dev_kfree_skb(conf->beacon); |
388 | 400 | ||