aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/p54/p54usb.c151
-rw-r--r--drivers/net/wireless/p54/p54usb.h1
2 files changed, 102 insertions, 50 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 2dd3cd41d0fe..c2789e53b984 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -86,13 +86,13 @@ static void p54u_rx_cb(struct urb *urb)
86 struct ieee80211_hw *dev = info->dev; 86 struct ieee80211_hw *dev = info->dev;
87 struct p54u_priv *priv = dev->priv; 87 struct p54u_priv *priv = dev->priv;
88 88
89 skb_unlink(skb, &priv->rx_queue);
90
89 if (unlikely(urb->status)) { 91 if (unlikely(urb->status)) {
90 info->urb = NULL; 92 dev_kfree_skb_irq(skb);
91 usb_free_urb(urb);
92 return; 93 return;
93 } 94 }
94 95
95 skb_unlink(skb, &priv->rx_queue);
96 skb_put(skb, urb->actual_length); 96 skb_put(skb, urb->actual_length);
97 97
98 if (priv->hw_type == P54U_NET2280) 98 if (priv->hw_type == P54U_NET2280)
@@ -105,7 +105,6 @@ static void p54u_rx_cb(struct urb *urb)
105 if (p54_rx(dev, skb)) { 105 if (p54_rx(dev, skb)) {
106 skb = dev_alloc_skb(priv->common.rx_mtu + 32); 106 skb = dev_alloc_skb(priv->common.rx_mtu + 32);
107 if (unlikely(!skb)) { 107 if (unlikely(!skb)) {
108 usb_free_urb(urb);
109 /* TODO check rx queue length and refill *somewhere* */ 108 /* TODO check rx queue length and refill *somewhere* */
110 return; 109 return;
111 } 110 }
@@ -115,7 +114,6 @@ static void p54u_rx_cb(struct urb *urb)
115 info->dev = dev; 114 info->dev = dev;
116 urb->transfer_buffer = skb_tail_pointer(skb); 115 urb->transfer_buffer = skb_tail_pointer(skb);
117 urb->context = skb; 116 urb->context = skb;
118 skb_queue_tail(&priv->rx_queue, skb);
119 } else { 117 } else {
120 if (priv->hw_type == P54U_NET2280) 118 if (priv->hw_type == P54U_NET2280)
121 skb_push(skb, priv->common.tx_hdr_len); 119 skb_push(skb, priv->common.tx_hdr_len);
@@ -130,11 +128,14 @@ static void p54u_rx_cb(struct urb *urb)
130 WARN_ON(1); 128 WARN_ON(1);
131 urb->transfer_buffer = skb_tail_pointer(skb); 129 urb->transfer_buffer = skb_tail_pointer(skb);
132 } 130 }
133
134 skb_queue_tail(&priv->rx_queue, skb);
135 } 131 }
136 132 skb_queue_tail(&priv->rx_queue, skb);
137 usb_submit_urb(urb, GFP_ATOMIC); 133 usb_anchor_urb(urb, &priv->submitted);
134 if (usb_submit_urb(urb, GFP_ATOMIC)) {
135 skb_unlink(skb, &priv->rx_queue);
136 usb_unanchor_urb(urb);
137 dev_kfree_skb_irq(skb);
138 }
138} 139}
139 140
140static void p54u_tx_reuse_skb_cb(struct urb *urb) 141static void p54u_tx_reuse_skb_cb(struct urb *urb)
@@ -144,18 +145,6 @@ static void p54u_tx_reuse_skb_cb(struct urb *urb)
144 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv; 145 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
145 146
146 skb_pull(skb, priv->common.tx_hdr_len); 147 skb_pull(skb, priv->common.tx_hdr_len);
147 usb_free_urb(urb);
148}
149
150static void p54u_tx_cb(struct urb *urb)
151{
152 usb_free_urb(urb);
153}
154
155static void p54u_tx_free_cb(struct urb *urb)
156{
157 kfree(urb->transfer_buffer);
158 usb_free_urb(urb);
159} 148}
160 149
161static void p54u_tx_free_skb_cb(struct urb *urb) 150static void p54u_tx_free_skb_cb(struct urb *urb)
@@ -165,25 +154,36 @@ static void p54u_tx_free_skb_cb(struct urb *urb)
165 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); 154 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
166 155
167 p54_free_skb(dev, skb); 156 p54_free_skb(dev, skb);
168 usb_free_urb(urb); 157}
158
159static void p54u_tx_dummy_cb(struct urb *urb) { }
160
161static void p54u_free_urbs(struct ieee80211_hw *dev)
162{
163 struct p54u_priv *priv = dev->priv;
164 usb_kill_anchored_urbs(&priv->submitted);
169} 165}
170 166
171static int p54u_init_urbs(struct ieee80211_hw *dev) 167static int p54u_init_urbs(struct ieee80211_hw *dev)
172{ 168{
173 struct p54u_priv *priv = dev->priv; 169 struct p54u_priv *priv = dev->priv;
174 struct urb *entry; 170 struct urb *entry = NULL;
175 struct sk_buff *skb; 171 struct sk_buff *skb;
176 struct p54u_rx_info *info; 172 struct p54u_rx_info *info;
173 int ret = 0;
177 174
178 while (skb_queue_len(&priv->rx_queue) < 32) { 175 while (skb_queue_len(&priv->rx_queue) < 32) {
179 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL); 176 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
180 if (!skb) 177 if (!skb) {
181 break; 178 ret = -ENOMEM;
179 goto err;
180 }
182 entry = usb_alloc_urb(0, GFP_KERNEL); 181 entry = usb_alloc_urb(0, GFP_KERNEL);
183 if (!entry) { 182 if (!entry) {
184 kfree_skb(skb); 183 ret = -ENOMEM;
185 break; 184 goto err;
186 } 185 }
186
187 usb_fill_bulk_urb(entry, priv->udev, 187 usb_fill_bulk_urb(entry, priv->udev,
188 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), 188 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
189 skb_tail_pointer(skb), 189 skb_tail_pointer(skb),
@@ -192,26 +192,25 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
192 info->urb = entry; 192 info->urb = entry;
193 info->dev = dev; 193 info->dev = dev;
194 skb_queue_tail(&priv->rx_queue, skb); 194 skb_queue_tail(&priv->rx_queue, skb);
195 usb_submit_urb(entry, GFP_KERNEL); 195
196 usb_anchor_urb(entry, &priv->submitted);
197 ret = usb_submit_urb(entry, GFP_KERNEL);
198 if (ret) {
199 skb_unlink(skb, &priv->rx_queue);
200 usb_unanchor_urb(entry);
201 goto err;
202 }
203 usb_free_urb(entry);
204 entry = NULL;
196 } 205 }
197 206
198 return 0; 207 return 0;
199}
200 208
201static void p54u_free_urbs(struct ieee80211_hw *dev) 209 err:
202{ 210 usb_free_urb(entry);
203 struct p54u_priv *priv = dev->priv; 211 kfree_skb(skb);
204 struct p54u_rx_info *info; 212 p54u_free_urbs(dev);
205 struct sk_buff *skb; 213 return ret;
206
207 while ((skb = skb_dequeue(&priv->rx_queue))) {
208 info = (struct p54u_rx_info *) skb->cb;
209 if (!info->urb)
210 continue;
211
212 usb_kill_urb(info->urb);
213 kfree_skb(skb);
214 }
215} 214}
216 215
217static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb, 216static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
@@ -219,6 +218,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
219{ 218{
220 struct p54u_priv *priv = dev->priv; 219 struct p54u_priv *priv = dev->priv;
221 struct urb *addr_urb, *data_urb; 220 struct urb *addr_urb, *data_urb;
221 int err = 0;
222 222
223 addr_urb = usb_alloc_urb(0, GFP_ATOMIC); 223 addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
224 if (!addr_urb) 224 if (!addr_urb)
@@ -233,15 +233,31 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
233 usb_fill_bulk_urb(addr_urb, priv->udev, 233 usb_fill_bulk_urb(addr_urb, priv->udev,
234 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 234 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
235 &((struct p54_hdr *)skb->data)->req_id, 4, 235 &((struct p54_hdr *)skb->data)->req_id, 4,
236 p54u_tx_cb, dev); 236 p54u_tx_dummy_cb, dev);
237 usb_fill_bulk_urb(data_urb, priv->udev, 237 usb_fill_bulk_urb(data_urb, priv->udev,
238 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 238 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
239 skb->data, skb->len, 239 skb->data, skb->len,
240 free_on_tx ? p54u_tx_free_skb_cb : 240 free_on_tx ? p54u_tx_free_skb_cb :
241 p54u_tx_reuse_skb_cb, skb); 241 p54u_tx_reuse_skb_cb, skb);
242 242
243 usb_submit_urb(addr_urb, GFP_ATOMIC); 243 usb_anchor_urb(addr_urb, &priv->submitted);
244 usb_submit_urb(data_urb, GFP_ATOMIC); 244 err = usb_submit_urb(addr_urb, GFP_ATOMIC);
245 if (err) {
246 usb_unanchor_urb(addr_urb);
247 goto out;
248 }
249
250 usb_anchor_urb(addr_urb, &priv->submitted);
251 err = usb_submit_urb(data_urb, GFP_ATOMIC);
252 if (err)
253 usb_unanchor_urb(data_urb);
254
255 out:
256 usb_free_urb(addr_urb);
257 usb_free_urb(data_urb);
258
259 if (err)
260 p54_free_skb(dev, skb);
245} 261}
246 262
247static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) 263static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
@@ -281,7 +297,13 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
281 free_on_tx ? p54u_tx_free_skb_cb : 297 free_on_tx ? p54u_tx_free_skb_cb :
282 p54u_tx_reuse_skb_cb, skb); 298 p54u_tx_reuse_skb_cb, skb);
283 299
284 usb_submit_urb(data_urb, GFP_ATOMIC); 300 usb_anchor_urb(data_urb, &priv->submitted);
301 if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
302 usb_unanchor_urb(data_urb);
303 skb_pull(skb, sizeof(*hdr));
304 p54_free_skb(dev, skb);
305 }
306 usb_free_urb(data_urb);
285} 307}
286 308
287static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb, 309static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
@@ -291,6 +313,7 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
291 struct urb *int_urb, *data_urb; 313 struct urb *int_urb, *data_urb;
292 struct net2280_tx_hdr *hdr; 314 struct net2280_tx_hdr *hdr;
293 struct net2280_reg_write *reg; 315 struct net2280_reg_write *reg;
316 int err = 0;
294 317
295 reg = kmalloc(sizeof(*reg), GFP_ATOMIC); 318 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
296 if (!reg) 319 if (!reg)
@@ -320,15 +343,42 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
320 343
321 usb_fill_bulk_urb(int_urb, priv->udev, 344 usb_fill_bulk_urb(int_urb, priv->udev,
322 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), 345 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
323 p54u_tx_free_cb, dev); 346 p54u_tx_dummy_cb, dev);
324 usb_submit_urb(int_urb, GFP_ATOMIC); 347
348 /*
349 * This flag triggers a code path in the USB subsystem that will
350 * free what's inside the transfer_buffer after the callback routine
351 * has completed.
352 */
353 int_urb->transfer_flags |= URB_FREE_BUFFER;
325 354
326 usb_fill_bulk_urb(data_urb, priv->udev, 355 usb_fill_bulk_urb(data_urb, priv->udev,
327 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), 356 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
328 skb->data, skb->len, 357 skb->data, skb->len,
329 free_on_tx ? p54u_tx_free_skb_cb : 358 free_on_tx ? p54u_tx_free_skb_cb :
330 p54u_tx_reuse_skb_cb, skb); 359 p54u_tx_reuse_skb_cb, skb);
331 usb_submit_urb(data_urb, GFP_ATOMIC); 360
361 usb_anchor_urb(int_urb, &priv->submitted);
362 err = usb_submit_urb(int_urb, GFP_ATOMIC);
363 if (err) {
364 usb_unanchor_urb(int_urb);
365 goto out;
366 }
367
368 usb_anchor_urb(data_urb, &priv->submitted);
369 err = usb_submit_urb(data_urb, GFP_ATOMIC);
370 if (err) {
371 usb_unanchor_urb(data_urb);
372 goto out;
373 }
374 out:
375 usb_free_urb(int_urb);
376 usb_free_urb(data_urb);
377
378 if (err) {
379 skb_pull(skb, sizeof(*hdr));
380 p54_free_skb(dev, skb);
381 }
332} 382}
333 383
334static int p54u_write(struct p54u_priv *priv, 384static int p54u_write(struct p54u_priv *priv,
@@ -885,6 +935,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
885 goto err_free_dev; 935 goto err_free_dev;
886 936
887 skb_queue_head_init(&priv->rx_queue); 937 skb_queue_head_init(&priv->rx_queue);
938 init_usb_anchor(&priv->submitted);
888 939
889 p54u_open(dev); 940 p54u_open(dev);
890 err = p54_read_eeprom(dev); 941 err = p54_read_eeprom(dev);
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index 5b8fe91379c3..54ee738bf2af 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -133,6 +133,7 @@ struct p54u_priv {
133 133
134 spinlock_t lock; 134 spinlock_t lock;
135 struct sk_buff_head rx_queue; 135 struct sk_buff_head rx_queue;
136 struct usb_anchor submitted;
136}; 137};
137 138
138#endif /* P54USB_H */ 139#endif /* P54USB_H */