Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.6-rc3 293 lines 6.6 kB view raw
1/* 2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * 16 * File: usbpipe.c 17 * 18 * Purpose: Handle USB control endpoint 19 * 20 * Author: Warren Hsu 21 * 22 * Date: Mar. 29, 2005 23 * 24 * Functions: 25 * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM 26 * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM 27 * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM 28 * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM 29 * 30 * Revision History: 31 * 04-05-2004 Jerry Chen: Initial release 32 * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte 33 * 34 */ 35 36#include "int.h" 37#include "rxtx.h" 38#include "dpc.h" 39#include "desc.h" 40#include "device.h" 41#include "usbpipe.h" 42 43#define USB_CTL_WAIT 500 /* ms */ 44 45int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, 46 u16 index, u16 length, u8 *buffer) 47{ 48 int status = 0; 49 50 if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) 51 return STATUS_FAILURE; 52 53 mutex_lock(&priv->usb_lock); 54 55 status = usb_control_msg(priv->usb, 56 usb_sndctrlpipe(priv->usb, 0), request, 0x40, value, 57 index, buffer, length, USB_CTL_WAIT); 58 59 mutex_unlock(&priv->usb_lock); 60 61 if (status < (int)length) 62 return STATUS_FAILURE; 63 64 return STATUS_SUCCESS; 65} 66 67void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data) 68{ 69 vnt_control_out(priv, MESSAGE_TYPE_WRITE, 70 reg_off, reg, sizeof(u8), &data); 71} 72 73int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, 74 u16 index, u16 length, u8 *buffer) 75{ 76 int status; 77 78 if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) 79 return STATUS_FAILURE; 80 81 mutex_lock(&priv->usb_lock); 82 83 status = usb_control_msg(priv->usb, 84 usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value, 85 index, buffer, length, USB_CTL_WAIT); 86 87 mutex_unlock(&priv->usb_lock); 88 89 if (status < (int)length) 90 return STATUS_FAILURE; 91 92 return STATUS_SUCCESS; 93} 94 95void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data) 96{ 97 vnt_control_in(priv, MESSAGE_TYPE_READ, 98 reg_off, reg, sizeof(u8), data); 99} 100 101static void vnt_start_interrupt_urb_complete(struct urb *urb) 102{ 103 struct vnt_private *priv = urb->context; 104 int status = urb->status; 105 106 switch (status) { 107 case 0: 108 case -ETIMEDOUT: 109 break; 110 case -ECONNRESET: 111 case -ENOENT: 112 case -ESHUTDOWN: 113 priv->int_buf.in_use = false; 114 return; 115 default: 116 break; 117 } 118 119 if (status) { 120 priv->int_buf.in_use = false; 121 122 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status); 123 } else { 124 vnt_int_process_data(priv); 125 } 126 127 status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC); 128 if (status) 129 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status); 130 else 131 priv->int_buf.in_use = true; 132} 133 134int vnt_start_interrupt_urb(struct vnt_private *priv) 135{ 136 int status = STATUS_FAILURE; 137 138 if (priv->int_buf.in_use) 139 return STATUS_FAILURE; 140 141 priv->int_buf.in_use = true; 142 143 usb_fill_int_urb(priv->interrupt_urb, 144 priv->usb, 145 usb_rcvintpipe(priv->usb, 1), 146 priv->int_buf.data_buf, 147 MAX_INTERRUPT_SIZE, 148 vnt_start_interrupt_urb_complete, 149 priv, 150 priv->int_interval); 151 152 status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC); 153 if (status) { 154 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status); 155 priv->int_buf.in_use = false; 156 } 157 158 return status; 159} 160 161static void vnt_submit_rx_urb_complete(struct urb *urb) 162{ 163 struct vnt_rcb *rcb = urb->context; 164 struct vnt_private *priv = rcb->priv; 165 166 switch (urb->status) { 167 case 0: 168 break; 169 case -ECONNRESET: 170 case -ENOENT: 171 case -ESHUTDOWN: 172 return; 173 case -ETIMEDOUT: 174 default: 175 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status); 176 break; 177 } 178 179 if (urb->actual_length) { 180 if (vnt_rx_data(priv, rcb, urb->actual_length)) { 181 rcb->skb = dev_alloc_skb(priv->rx_buf_sz); 182 if (!rcb->skb) { 183 dev_dbg(&priv->usb->dev, 184 "Failed to re-alloc rx skb\n"); 185 186 rcb->in_use = false; 187 return; 188 } 189 } else { 190 skb_push(rcb->skb, skb_headroom(rcb->skb)); 191 skb_trim(rcb->skb, 0); 192 } 193 194 urb->transfer_buffer = skb_put(rcb->skb, 195 skb_tailroom(rcb->skb)); 196 } 197 198 if (usb_submit_urb(urb, GFP_ATOMIC)) { 199 dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n"); 200 201 rcb->in_use = false; 202 } 203} 204 205int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb) 206{ 207 int status = 0; 208 struct urb *urb = rcb->urb; 209 210 if (!rcb->skb) { 211 dev_dbg(&priv->usb->dev, "rcb->skb is null\n"); 212 return status; 213 } 214 215 usb_fill_bulk_urb(urb, 216 priv->usb, 217 usb_rcvbulkpipe(priv->usb, 2), 218 skb_put(rcb->skb, skb_tailroom(rcb->skb)), 219 MAX_TOTAL_SIZE_WITH_ALL_HEADERS, 220 vnt_submit_rx_urb_complete, 221 rcb); 222 223 status = usb_submit_urb(urb, GFP_ATOMIC); 224 if (status) { 225 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status); 226 return STATUS_FAILURE; 227 } 228 229 rcb->in_use = true; 230 231 return status; 232} 233 234static void vnt_tx_context_complete(struct urb *urb) 235{ 236 struct vnt_usb_send_context *context = urb->context; 237 struct vnt_private *priv = context->priv; 238 239 switch (urb->status) { 240 case 0: 241 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len); 242 break; 243 case -ECONNRESET: 244 case -ENOENT: 245 case -ESHUTDOWN: 246 context->in_use = false; 247 return; 248 case -ETIMEDOUT: 249 default: 250 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status); 251 break; 252 } 253 254 if (context->type == CONTEXT_DATA_PACKET) 255 ieee80211_wake_queues(priv->hw); 256 257 if (urb->status || context->type == CONTEXT_BEACON_PACKET) { 258 if (context->skb) 259 ieee80211_free_txskb(priv->hw, context->skb); 260 261 context->in_use = false; 262 } 263} 264 265int vnt_tx_context(struct vnt_private *priv, 266 struct vnt_usb_send_context *context) 267{ 268 int status; 269 struct urb *urb = context->urb; 270 271 if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) { 272 context->in_use = false; 273 return STATUS_RESOURCES; 274 } 275 276 usb_fill_bulk_urb(urb, 277 priv->usb, 278 usb_sndbulkpipe(priv->usb, 3), 279 context->data, 280 context->buf_len, 281 vnt_tx_context_complete, 282 context); 283 284 status = usb_submit_urb(urb, GFP_ATOMIC); 285 if (status) { 286 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status); 287 288 context->in_use = false; 289 return STATUS_FAILURE; 290 } 291 292 return STATUS_PENDING; 293}