Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: drivers/net/usb/gobi/qmidevice.c

Issue 6731086: CHROMIUM: gobi: resubmit interrupt urb on failed reads (Closed) Base URL: ssh://gitrw.chromium.org:9222/kernel.git@master
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* qmidevice.c - gobi QMI device 1 /* qmidevice.c - gobi QMI device
2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved. 2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3 3
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation. 6 * only version 2 as published by the Free Software Foundation.
7 7
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 static struct client *client_bycid(struct qcusbnet *dev, u16 cid); 61 static struct client *client_bycid(struct qcusbnet *dev, u16 cid);
62 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data, u 16 size); 62 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data, u 16 size);
63 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data, u16 *size); 63 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data, u16 *size);
64 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid, 64 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid,
65 void (*hook)(struct qcusbnet *, u16 cid, void *), 65 void (*hook)(struct qcusbnet *, u16 cid, void *),
66 void *data); 66 void *data);
67 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid); 67 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid);
68 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb); 68 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb);
69 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid); 69 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid);
70 70
71 static int resubmit_int_urb(struct urb *urb);
72
71 static int devqmi_open(struct inode *inode, struct file *file); 73 static int devqmi_open(struct inode *inode, struct file *file);
72 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg); 74 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg);
73 static int devqmi_release(struct inode *inode, struct file *file); 75 static int devqmi_release(struct inode *inode, struct file *file);
74 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size, 76 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size,
75 loff_t *pos); 77 loff_t *pos);
76 static ssize_t devqmi_write(struct file *file, const char __user *buf, 78 static ssize_t devqmi_write(struct file *file, const char __user *buf,
77 size_t size, loff_t *pos); 79 size_t size, loff_t *pos);
78 80
79 static bool qmi_ready(struct qcusbnet *dev, u16 timeout); 81 static bool qmi_ready(struct qcusbnet *dev, u16 timeout);
80 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data); 82 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 clear_bit(reason, &dev->down); 127 clear_bit(reason, &dev->down);
126 if (!dev->down) 128 if (!dev->down)
127 netif_carrier_on(dev->usbnet->net); 129 netif_carrier_on(dev->usbnet->net);
128 } 130 }
129 131
130 bool qc_isdown(struct qcusbnet *dev, u8 reason) 132 bool qc_isdown(struct qcusbnet *dev, u8 reason)
131 { 133 {
132 return test_bit(reason, &dev->down); 134 return test_bit(reason, &dev->down);
133 } 135 }
134 136
137 static int resubmit_int_urb(struct urb *urb)
138 {
139 int status;
140 int interval;
141 if (!urb || !urb->dev)
142 return -EINVAL;
143 interval = urb->dev->speed == USB_SPEED_HIGH ? 7 : 3;
144 usb_fill_int_urb(urb, urb->dev, urb->pipe, urb->transfer_buffer,
145 urb->transfer_buffer_length, urb->complete,
146 urb->context, interval);
147 status = usb_submit_urb(urb, GFP_ATOMIC);
148 if (status)
149 DBG("status %d", status);
150 return status;
151 }
152
135 static void read_callback(struct urb *urb) 153 static void read_callback(struct urb *urb)
136 { 154 {
137 struct list_head *node; 155 struct list_head *node;
138 int result; 156 int result;
139 u16 cid; 157 u16 cid;
140 struct client *client; 158 struct client *client;
141 void *data; 159 void *data;
142 void *copy; 160 void *copy;
143 u16 size; 161 u16 size;
144 struct qcusbnet *dev; 162 struct qcusbnet *dev;
145 unsigned long flags; 163 unsigned long flags;
146 u16 tid; 164 u16 tid;
147 165
148 if (!urb) { 166 if (!urb) {
149 DBG("bad read URB\n"); 167 DBG("bad read URB\n");
150 return; 168 return;
151 } 169 }
152 170
153 dev = urb->context; 171 dev = urb->context;
154 if (!device_valid(dev)) { 172 if (!device_valid(dev)) {
155 DBG("Invalid device!\n"); 173 DBG("Invalid device!\n");
156 return; 174 return;
157 } 175 }
158 176
159 if (urb->status) { 177 if (urb->status) {
160 DBG("Read status = %d\n", urb->status); 178 DBG("Read status = %d\n", urb->status);
179 resubmit_int_urb(dev->qmi.inturb);
161 return; 180 return;
162 } 181 }
163 182
164 DBG("Read %d bytes\n", urb->actual_length); 183 DBG("Read %d bytes\n", urb->actual_length);
165 184
166 data = urb->transfer_buffer; 185 data = urb->transfer_buffer;
167 size = urb->actual_length; 186 size = urb->actual_length;
168 187
169 if (qcusbnet_debug) 188 if (qcusbnet_debug)
170 print_hex_dump(KERN_INFO, "gobi-read: ", DUMP_PREFIX_OFFSET, 189 print_hex_dump(KERN_INFO, "gobi-read: ", DUMP_PREFIX_OFFSET,
171 16, 1, data, size, true); 190 16, 1, data, size, true);
172 191
173 result = qmux_parse(&cid, data, size); 192 result = qmux_parse(&cid, data, size);
174 if (result < 0) { 193 if (result < 0) {
175 DBG("Read error parsing QMUX %d\n", result); 194 DBG("Read error parsing QMUX %d\n", result);
195 resubmit_int_urb(dev->qmi.inturb);
176 return; 196 return;
177 } 197 }
178 198
179 if (size < result + 3) { 199 if (size < result + 3) {
180 DBG("Data buffer too small to parse\n"); 200 DBG("Data buffer too small to parse\n");
201 resubmit_int_urb(dev->qmi.inturb);
181 return; 202 return;
182 } 203 }
183 204
184 if (cid == QMICTL) 205 if (cid == QMICTL)
185 tid = *(u8 *)(data + result + 1); 206 tid = *(u8 *)(data + result + 1);
186 else 207 else
187 tid = *(u16 *)(data + result + 1); 208 tid = *(u16 *)(data + result + 1);
188 spin_lock_irqsave(&dev->qmi.clients_lock, flags); 209 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
189 210
190 list_for_each(node, &dev->qmi.clients) { 211 list_for_each(node, &dev->qmi.clients) {
191 client = list_entry(node, struct client, node); 212 client = list_entry(node, struct client, node);
192 if (client->cid == cid || (client->cid | 0xff00) == cid) { 213 if (client->cid == cid || (client->cid | 0xff00) == cid) {
193 copy = kmalloc(size, GFP_ATOMIC); 214 copy = kmalloc(size, GFP_ATOMIC);
194 memcpy(copy, data, size); 215 memcpy(copy, data, size);
195 if (!client_addread(dev, client->cid, tid, copy, size)) { 216 if (!client_addread(dev, client->cid, tid, copy, size)) {
196 DBG("Error allocating pReadMemListEntry " 217 DBG("Error allocating pReadMemListEntry "
197 "read will be discarded\n"); 218 "read will be discarded\n");
198 kfree(copy); 219 kfree(copy);
199 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags); 220 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
221 resubmit_int_urb(dev->qmi.inturb);
200 return; 222 return;
201 } 223 }
202 224
203 DBG("Creating new readListEntry for client 0x%04X, TID % x\n", 225 DBG("Creating new readListEntry for client 0x%04X, TID % x\n",
204 cid, tid); 226 cid, tid);
205 227
206 client_notify(dev, client->cid, tid); 228 client_notify(dev, client->cid, tid);
207 229
208 if (cid >> 8 != 0xff) 230 if (cid >> 8 != 0xff)
209 break; 231 break;
210 } 232 }
211 } 233 }
212 234
213 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags); 235 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
236 resubmit_int_urb(dev->qmi.inturb);
214 } 237 }
215 238
216 static void int_callback(struct urb *urb) 239 static void int_callback(struct urb *urb)
217 { 240 {
218 int status; 241 int status;
219 int interval; 242 int interval;
220 struct qcusbnet *dev = (struct qcusbnet *)urb->context; 243 struct qcusbnet *dev = (struct qcusbnet *)urb->context;
221 244
222 if (!device_valid(dev)) { 245 if (!device_valid(dev)) {
223 DBG("Invalid device!\n"); 246 DBG("Invalid device!\n");
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } else { 280 } else {
258 DBG("ignoring invalid interrupt in packet\n"); 281 DBG("ignoring invalid interrupt in packet\n");
259 if (qcusbnet_debug) 282 if (qcusbnet_debug)
260 print_hex_dump(KERN_INFO, "gobi-int: ", 283 print_hex_dump(KERN_INFO, "gobi-int: ",
261 DUMP_PREFIX_OFFSET, 16, 1, 284 DUMP_PREFIX_OFFSET, 16, 1,
262 urb->transfer_buffer, 285 urb->transfer_buffer,
263 urb->actual_length, true); 286 urb->actual_length, true);
264 } 287 }
265 } 288 }
266 289
267 » interval = (dev->usbnet->udev->speed == USB_SPEED_HIGH) ? 7 : 3; 290 » resubmit_int_urb(dev->qmi.inturb);
268
269 » usb_fill_int_urb(urb, urb->dev,»urb->pipe, urb->transfer_buffer,
270 » » » urb->transfer_buffer_length, urb->complete,
271 » » » urb->context, interval);
272 » status = usb_submit_urb(urb, GFP_ATOMIC);
273 » if (status)
274 » » DBG("Error re-submitting Int URB %d\n", status);
275 return; 291 return;
276 } 292 }
277 293
278 int qc_startread(struct qcusbnet *dev) 294 int qc_startread(struct qcusbnet *dev)
279 { 295 {
280 int interval; 296 int interval;
281 297
282 if (!device_valid(dev)) { 298 if (!device_valid(dev)) {
283 DBG("Invalid device!\n"); 299 DBG("Invalid device!\n");
284 return -ENXIO; 300 return -ENXIO;
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 DBG("bad get MEID resp\n"); 1553 DBG("bad get MEID resp\n");
1538 memset(&dev->meid[0], '0', 14); 1554 memset(&dev->meid[0], '0', 14);
1539 } 1555 }
1540 1556
1541 client_free(dev, cid); 1557 client_free(dev, cid);
1542 return 0; 1558 return 0;
1543 } 1559 }
1544 1560
1545 module_param(qcusbnet2k_fwdelay, int, S_IRUGO | S_IWUSR); 1561 module_param(qcusbnet2k_fwdelay, int, S_IRUGO | S_IWUSR);
1546 MODULE_PARM_DESC(qcusbnet2k_fwdelay, "Delay for old firmware"); 1562 MODULE_PARM_DESC(qcusbnet2k_fwdelay, "Delay for old firmware");
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698