Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  4 * All rights reserved.
  5 *
 
 
  6 * Purpose: Handle USB control endpoint
  7 *
  8 * Author: Warren Hsu
  9 *
 10 * Date: Mar. 29, 2005
 11 *
 12 * Functions:
 13 *	vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
 14 *	vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
 15 *	vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
 16 *	vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
 17 *
 18 * Revision History:
 19 *      04-05-2004 Jerry Chen: Initial release
 20 *      11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
 21 *                             ControlvMaskByte
 22 *
 23 */
 24
 
 25#include "rxtx.h"
 
 26#include "desc.h"
 27#include "device.h"
 28#include "usbpipe.h"
 29#include "mac.h"
 30#include "rf.h"
 31
 32#define USB_CTL_WAIT	500 /* ms */
 33
 34int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
 35		    u16 index, u16 length, const u8 *buffer)
 36{
 37	int ret = 0;
 38	u8 *usb_buffer;
 39
 40	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 41		ret = -EINVAL;
 42		goto end;
 43	}
 44
 45	mutex_lock(&priv->usb_lock);
 46
 47	usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
 48	if (!usb_buffer) {
 49		ret = -ENOMEM;
 50		goto end_unlock;
 51	}
 52
 53	ret = usb_control_msg(priv->usb,
 54			      usb_sndctrlpipe(priv->usb, 0),
 55			      request, 0x40, value,
 56			      index, usb_buffer, length, USB_CTL_WAIT);
 57
 58	kfree(usb_buffer);
 59
 60	if (ret == (int)length)
 61		ret = 0;
 62	else
 63		ret = -EIO;
 64
 65end_unlock:
 66	mutex_unlock(&priv->usb_lock);
 67end:
 68	return ret;
 69}
 70
 71int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
 72{
 73	return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
 74			       reg_off, reg, sizeof(u8), &data);
 75}
 76
 77int vnt_control_out_blocks(struct vnt_private *priv,
 78			   u16 block, u8 reg, u16 length, const u8 *data)
 79{
 80	int ret = 0, i;
 81
 82	for (i = 0; i < length; i += block) {
 83		u16 len = min_t(int, length - i, block);
 84
 85		ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
 86				      i, reg, len, data + i);
 87		if (ret)
 88			goto end;
 89	}
 90end:
 91	return ret;
 92}
 93
 94int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 95		   u16 index, u16 length, u8 *buffer)
 96{
 97	int ret = 0;
 98	u8 *usb_buffer;
 99
100	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
101		ret = -EINVAL;
102		goto end;
103	}
104
105	mutex_lock(&priv->usb_lock);
106
107	usb_buffer = kmalloc(length, GFP_KERNEL);
108	if (!usb_buffer) {
109		ret = -ENOMEM;
110		goto end_unlock;
111	}
112
113	ret = usb_control_msg(priv->usb,
114			      usb_rcvctrlpipe(priv->usb, 0),
115			      request, 0xc0, value,
116			      index, usb_buffer, length, USB_CTL_WAIT);
117
118	if (ret == length)
119		memcpy(buffer, usb_buffer, length);
120
121	kfree(usb_buffer);
122
123	if (ret == (int)length)
124		ret = 0;
125	else
126		ret = -EIO;
127
128end_unlock:
129	mutex_unlock(&priv->usb_lock);
130end:
131	return ret;
132}
133
134int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
135{
136	return vnt_control_in(priv, MESSAGE_TYPE_READ,
137			      reg_off, reg, sizeof(u8), data);
138}
139
140static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
141{
142	struct vnt_usb_send_context *context;
143	struct ieee80211_tx_info *info;
144	u8 tx_retry = (tsr & 0xf0) >> 4;
145	s8 idx;
146
147	if (pkt_no >= priv->num_tx_context)
148		return -EINVAL;
149
150	context = priv->tx_context[pkt_no];
151
152	if (!context->skb)
153		return -EINVAL;
154
155	info = IEEE80211_SKB_CB(context->skb);
156	idx = info->control.rates[0].idx;
157
158	ieee80211_tx_info_clear_status(info);
159
160	info->status.rates[0].count = tx_retry;
161
162	if (!(tsr & TSR_TMO)) {
163		info->status.rates[0].idx = idx;
164
165		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
166			info->flags |= IEEE80211_TX_STAT_ACK;
167	}
168
169	ieee80211_tx_status_irqsafe(priv->hw, context->skb);
170
171	context->in_use = false;
172
173	return 0;
174}
175
176static void vnt_int_process_data(struct vnt_private *priv)
177{
178	struct vnt_interrupt_data *int_data;
179	struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
180
181	dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n");
182
183	int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
184
185	if (int_data->tsr0 & TSR_VALID)
186		vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0);
187
188	if (int_data->tsr1 & TSR_VALID)
189		vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1);
190
191	if (int_data->tsr2 & TSR_VALID)
192		vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2);
193
194	if (int_data->tsr3 & TSR_VALID)
195		vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3);
196
197	if (!int_data->isr0)
198		return;
199
200	if (int_data->isr0 & ISR_BNTX && priv->op_mode == NL80211_IFTYPE_AP)
201		vnt_schedule_command(priv, WLAN_CMD_BECON_SEND);
202
203	priv->current_tsf = le64_to_cpu(int_data->tsf);
204
205	low_stats->dot11RTSSuccessCount += int_data->rts_success;
206	low_stats->dot11RTSFailureCount += int_data->rts_fail;
207	low_stats->dot11ACKFailureCount += int_data->ack_fail;
208	low_stats->dot11FCSErrorCount += int_data->fcs_err;
209}
210
211static void vnt_start_interrupt_urb_complete(struct urb *urb)
212{
213	struct vnt_private *priv = urb->context;
214	int status = urb->status;
215
216	switch (status) {
217	case 0:
218	case -ETIMEDOUT:
219		break;
220	case -ECONNRESET:
221	case -ENOENT:
222	case -ESHUTDOWN:
 
223		return;
224	default:
225		break;
226	}
227
228	if (status)
 
 
229		dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
230	else
231		vnt_int_process_data(priv);
 
232
233	if (!test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
234		status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
235
236	if (status)
237		dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
 
 
238}
239
240int vnt_start_interrupt_urb(struct vnt_private *priv)
241{
242	int ret = 0;
243
244	dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
 
 
 
 
 
245
246	usb_fill_int_urb(priv->interrupt_urb,
247			 priv->usb,
248			 usb_rcvintpipe(priv->usb, 1),
249			 priv->int_buf.data_buf,
250			 MAX_INTERRUPT_SIZE,
251			 vnt_start_interrupt_urb_complete,
252			 priv,
253			 priv->int_interval);
254
255	ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
256	if (ret)
257		dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
258
259	return ret;
260}
261
262static int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
263		       unsigned long bytes_received)
264{
265	struct ieee80211_hw *hw = priv->hw;
266	struct ieee80211_supported_band *sband;
267	struct sk_buff *skb;
268	struct ieee80211_rx_status *rx_status;
269	struct vnt_rx_header *head;
270	struct vnt_rx_tail *tail;
271	u32 frame_size;
272	int ii;
273	u16 rx_bitrate, pay_load_with_padding;
274	u8 rate_idx = 0;
275	long rx_dbm;
276
277	skb = ptr_rcb->skb;
278	rx_status = IEEE80211_SKB_RXCB(skb);
279
280	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
281	head = (struct vnt_rx_header *)skb->data;
282	frame_size = head->wbk_status >> 16;
283	frame_size += 4;
284
285	if (bytes_received != frame_size) {
286		dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n");
287		return false;
288	}
289
290	if ((bytes_received > 2372) || (bytes_received <= 40)) {
291		/* Frame Size error drop this packet.*/
292		dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n");
293		return false;
294	}
295
296	/* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */
297	/* -8TSF - 4RSR - 4SQ3 - ?Padding */
298
299	/* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */
300
301	/*Fix hardware bug => PLCP_Length error */
302	if (((bytes_received - head->pay_load_len) > 27) ||
303	    ((bytes_received - head->pay_load_len) < 24) ||
304	    (bytes_received < head->pay_load_len)) {
305		dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n",
306			head->pay_load_len);
307		return false;
308	}
309
310	sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
311	rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */
312
313	for (ii = 0; ii < sband->n_bitrates; ii++) {
314		if (sband->bitrates[ii].bitrate == rx_bitrate) {
315			rate_idx = ii;
316				break;
317		}
318	}
319
320	if (ii == sband->n_bitrates) {
321		dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate);
322		return false;
323	}
324
325	pay_load_with_padding = ((head->pay_load_len / 4) +
326		((head->pay_load_len % 4) ? 1 : 0)) * 4;
327
328	tail = (struct vnt_rx_tail *)(skb->data +
329				      sizeof(*head) + pay_load_with_padding);
330	priv->tsf_time = le64_to_cpu(tail->tsf_time);
331
332	if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
333		return false;
334
335	vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
336
337	priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
338	priv->current_rssi = priv->bb_pre_ed_rssi;
339
340	skb_pull(skb, sizeof(*head));
341	skb_trim(skb, head->pay_load_len);
342
343	rx_status->mactime = priv->tsf_time;
344	rx_status->band = hw->conf.chandef.chan->band;
345	rx_status->signal = rx_dbm;
346	rx_status->flag = 0;
347	rx_status->freq = hw->conf.chandef.chan->center_freq;
348
349	if (!(tail->rsr & RSR_CRCOK))
350		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
351
352	rx_status->rate_idx = rate_idx;
353
354	if (tail->new_rsr & NEWRSR_DECRYPTOK)
355		rx_status->flag |= RX_FLAG_DECRYPTED;
356
357	ieee80211_rx_irqsafe(priv->hw, skb);
358
359	return true;
 
 
 
360}
361
362static void vnt_submit_rx_urb_complete(struct urb *urb)
363{
364	struct vnt_rcb *rcb = urb->context;
365	struct vnt_private *priv = rcb->priv;
366
367	switch (urb->status) {
368	case 0:
369		break;
370	case -ECONNRESET:
371	case -ENOENT:
372	case -ESHUTDOWN:
373		return;
374	case -ETIMEDOUT:
375	default:
376		dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
377		break;
378	}
379
380	if (urb->actual_length) {
381		if (vnt_rx_data(priv, rcb, urb->actual_length)) {
382			rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
383			if (!rcb->skb)
 
384				return;
 
385		} else {
386			skb_push(rcb->skb, skb_headroom(rcb->skb));
387			skb_trim(rcb->skb, 0);
388		}
389
390		urb->transfer_buffer = skb_put(rcb->skb,
391					       skb_tailroom(rcb->skb));
392	}
393
394	if (usb_submit_urb(urb, GFP_ATOMIC))
395		dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
 
 
 
396}
397
398int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
399{
400	int ret = 0;
401	struct urb *urb = rcb->urb;
402
403	if (!rcb->skb) {
404		dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
405		ret = -EINVAL;
406		goto end;
407	}
408
409	usb_fill_bulk_urb(urb,
410			  priv->usb,
411			  usb_rcvbulkpipe(priv->usb, 2),
412			  skb_put(rcb->skb, skb_tailroom(rcb->skb)),
413			  MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
414			  vnt_submit_rx_urb_complete,
415			  rcb);
416
417	ret = usb_submit_urb(urb, GFP_ATOMIC);
418	if (ret)
419		dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
 
 
 
 
 
420end:
421	return ret;
422}
423
424static void vnt_tx_context_complete(struct urb *urb)
425{
426	struct vnt_usb_send_context *context = urb->context;
427	struct vnt_private *priv = context->priv;
428
429	switch (urb->status) {
430	case 0:
431		dev_dbg(&priv->usb->dev,
432			"Write %d bytes\n", urb->actual_length);
433		break;
434	case -ECONNRESET:
435	case -ENOENT:
436	case -ESHUTDOWN:
437		context->in_use = false;
438		return;
439	case -ETIMEDOUT:
440	default:
441		dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
442		break;
443	}
444
445	if (context->type == CONTEXT_DATA_PACKET)
446		ieee80211_wake_queues(priv->hw);
447
448	if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
449		if (context->skb)
450			ieee80211_free_txskb(priv->hw, context->skb);
451
452		context->in_use = false;
453	}
454}
455
456int vnt_tx_context(struct vnt_private *priv,
457		   struct vnt_usb_send_context *context,
458		   struct sk_buff *skb)
459{
460	struct vnt_tx_usb_header *usb;
461	struct urb *urb;
462	int status;
463	u16 count = skb->len;
464
465	usb = skb_push(skb, sizeof(*usb));
466	usb->tx_byte_count = cpu_to_le16(count);
467	usb->pkt_no = context->pkt_no;
468	usb->type = context->type;
469
470	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
471		context->in_use = false;
472		return -ENODEV;
473	}
474
475	if (skb->len > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) {
476		context->in_use = false;
477		return -E2BIG;
478	}
479
480	urb = usb_alloc_urb(0, GFP_ATOMIC);
481	if (!urb) {
482		context->in_use = false;
483		return -ENOMEM;
484	}
485
486	usb_fill_bulk_urb(urb,
487			  priv->usb,
488			  usb_sndbulkpipe(priv->usb, 3),
489			  skb->data,
490			  skb->len,
491			  vnt_tx_context_complete,
492			  context);
493
494	usb_anchor_urb(urb, &priv->tx_submitted);
495
496	status = usb_submit_urb(urb, GFP_ATOMIC);
497	if (status) {
498		dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
499		usb_unanchor_urb(urb);
500		context->in_use = false;
 
501	}
502
503	usb_free_urb(urb);
504
505	return status;
506}
v5.4
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  4 * All rights reserved.
  5 *
  6 * File: usbpipe.c
  7 *
  8 * Purpose: Handle USB control endpoint
  9 *
 10 * Author: Warren Hsu
 11 *
 12 * Date: Mar. 29, 2005
 13 *
 14 * Functions:
 15 *	vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
 16 *	vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
 17 *	vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
 18 *	vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
 19 *
 20 * Revision History:
 21 *      04-05-2004 Jerry Chen: Initial release
 22 *      11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
 23 *                             ControlvMaskByte
 24 *
 25 */
 26
 27#include "int.h"
 28#include "rxtx.h"
 29#include "dpc.h"
 30#include "desc.h"
 31#include "device.h"
 32#include "usbpipe.h"
 
 
 33
 34#define USB_CTL_WAIT	500 /* ms */
 35
 36int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
 37		    u16 index, u16 length, u8 *buffer)
 38{
 39	int ret = 0;
 40	u8 *usb_buffer;
 41
 42	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 43		ret = -EINVAL;
 44		goto end;
 45	}
 46
 47	mutex_lock(&priv->usb_lock);
 48
 49	usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
 50	if (!usb_buffer) {
 51		ret = -ENOMEM;
 52		goto end_unlock;
 53	}
 54
 55	ret = usb_control_msg(priv->usb,
 56			      usb_sndctrlpipe(priv->usb, 0),
 57			      request, 0x40, value,
 58			      index, usb_buffer, length, USB_CTL_WAIT);
 59
 60	kfree(usb_buffer);
 61
 62	if (ret >= 0 && ret < (int)length)
 
 
 63		ret = -EIO;
 64
 65end_unlock:
 66	mutex_unlock(&priv->usb_lock);
 67end:
 68	return ret;
 69}
 70
 71int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
 72{
 73	return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
 74			       reg_off, reg, sizeof(u8), &data);
 75}
 76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 77int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 78		   u16 index, u16 length, u8 *buffer)
 79{
 80	int ret = 0;
 81	u8 *usb_buffer;
 82
 83	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 84		ret = -EINVAL;
 85		goto end;
 86	}
 87
 88	mutex_lock(&priv->usb_lock);
 89
 90	usb_buffer = kmalloc(length, GFP_KERNEL);
 91	if (!usb_buffer) {
 92		ret = -ENOMEM;
 93		goto end_unlock;
 94	}
 95
 96	ret = usb_control_msg(priv->usb,
 97			      usb_rcvctrlpipe(priv->usb, 0),
 98			      request, 0xc0, value,
 99			      index, usb_buffer, length, USB_CTL_WAIT);
100
101	if (ret == length)
102		memcpy(buffer, usb_buffer, length);
103
104	kfree(usb_buffer);
105
106	if (ret >= 0 && ret < (int)length)
 
 
107		ret = -EIO;
108
109end_unlock:
110	mutex_unlock(&priv->usb_lock);
111end:
112	return ret;
113}
114
115int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
116{
117	return vnt_control_in(priv, MESSAGE_TYPE_READ,
118			      reg_off, reg, sizeof(u8), data);
119}
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121static void vnt_start_interrupt_urb_complete(struct urb *urb)
122{
123	struct vnt_private *priv = urb->context;
124	int status = urb->status;
125
126	switch (status) {
127	case 0:
128	case -ETIMEDOUT:
129		break;
130	case -ECONNRESET:
131	case -ENOENT:
132	case -ESHUTDOWN:
133		priv->int_buf.in_use = false;
134		return;
135	default:
136		break;
137	}
138
139	if (status) {
140		priv->int_buf.in_use = false;
141
142		dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
143	} else {
144		vnt_int_process_data(priv);
145	}
146
147	status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 
 
148	if (status)
149		dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
150	else
151		priv->int_buf.in_use = true;
152}
153
154int vnt_start_interrupt_urb(struct vnt_private *priv)
155{
156	int ret = 0;
157
158	if (priv->int_buf.in_use) {
159		ret = -EBUSY;
160		goto err;
161	}
162
163	priv->int_buf.in_use = true;
164
165	usb_fill_int_urb(priv->interrupt_urb,
166			 priv->usb,
167			 usb_rcvintpipe(priv->usb, 1),
168			 priv->int_buf.data_buf,
169			 MAX_INTERRUPT_SIZE,
170			 vnt_start_interrupt_urb_complete,
171			 priv,
172			 priv->int_interval);
173
174	ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
175	if (ret) {
176		dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
177		goto err_submit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178	}
179
180	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
182err_submit:
183	priv->int_buf.in_use = false;
184err:
185	return ret;
186}
187
188static void vnt_submit_rx_urb_complete(struct urb *urb)
189{
190	struct vnt_rcb *rcb = urb->context;
191	struct vnt_private *priv = rcb->priv;
192
193	switch (urb->status) {
194	case 0:
195		break;
196	case -ECONNRESET:
197	case -ENOENT:
198	case -ESHUTDOWN:
199		return;
200	case -ETIMEDOUT:
201	default:
202		dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
203		break;
204	}
205
206	if (urb->actual_length) {
207		if (vnt_rx_data(priv, rcb, urb->actual_length)) {
208			rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
209			if (!rcb->skb) {
210				rcb->in_use = false;
211				return;
212			}
213		} else {
214			skb_push(rcb->skb, skb_headroom(rcb->skb));
215			skb_trim(rcb->skb, 0);
216		}
217
218		urb->transfer_buffer = skb_put(rcb->skb,
219					       skb_tailroom(rcb->skb));
220	}
221
222	if (usb_submit_urb(urb, GFP_ATOMIC)) {
223		dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
224
225		rcb->in_use = false;
226	}
227}
228
229int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
230{
231	int ret = 0;
232	struct urb *urb = rcb->urb;
233
234	if (!rcb->skb) {
235		dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
236		ret = -EINVAL;
237		goto end;
238	}
239
240	usb_fill_bulk_urb(urb,
241			  priv->usb,
242			  usb_rcvbulkpipe(priv->usb, 2),
243			  skb_put(rcb->skb, skb_tailroom(rcb->skb)),
244			  MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
245			  vnt_submit_rx_urb_complete,
246			  rcb);
247
248	ret = usb_submit_urb(urb, GFP_ATOMIC);
249	if (ret) {
250		dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
251		goto end;
252	}
253
254	rcb->in_use = true;
255
256end:
257	return ret;
258}
259
260static void vnt_tx_context_complete(struct urb *urb)
261{
262	struct vnt_usb_send_context *context = urb->context;
263	struct vnt_private *priv = context->priv;
264
265	switch (urb->status) {
266	case 0:
267		dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
 
268		break;
269	case -ECONNRESET:
270	case -ENOENT:
271	case -ESHUTDOWN:
272		context->in_use = false;
273		return;
274	case -ETIMEDOUT:
275	default:
276		dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
277		break;
278	}
279
280	if (context->type == CONTEXT_DATA_PACKET)
281		ieee80211_wake_queues(priv->hw);
282
283	if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
284		if (context->skb)
285			ieee80211_free_txskb(priv->hw, context->skb);
286
287		context->in_use = false;
288	}
289}
290
291int vnt_tx_context(struct vnt_private *priv,
292		   struct vnt_usb_send_context *context)
 
293{
 
 
294	int status;
295	struct urb *urb = context->urb;
 
 
 
 
 
296
297	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
298		context->in_use = false;
299		return STATUS_RESOURCES;
 
 
 
 
 
 
 
 
 
 
 
300	}
301
302	usb_fill_bulk_urb(urb,
303			  priv->usb,
304			  usb_sndbulkpipe(priv->usb, 3),
305			  context->data,
306			  context->buf_len,
307			  vnt_tx_context_complete,
308			  context);
309
 
 
310	status = usb_submit_urb(urb, GFP_ATOMIC);
311	if (status) {
312		dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
313
314		context->in_use = false;
315		return STATUS_FAILURE;
316	}
317
318	return STATUS_PENDING;
 
 
319}