Commit | Line | Data |
---|---|---|
1dac4186 | 1 | /* Driver for Realtek RTS51xx USB card reader |
2 | * | |
3 | * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2, or (at your option) any | |
8 | * later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, see <http://www.gnu.org/licenses/>. | |
17 | * | |
18 | * Author: | |
19 | * wwang (wei_wang@realsil.com.cn) | |
20 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | |
21 | * Maintainer: | |
22 | * Edwin Rong (edwin_rong@realsil.com.cn) | |
23 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | |
24 | */ | |
25 | ||
26 | #include <linux/blkdev.h> | |
27 | #include <linux/kthread.h> | |
28 | #include <linux/sched.h> | |
29 | #include <linux/slab.h> | |
30 | ||
31 | #include <scsi/scsi.h> | |
32 | #include <scsi/scsi_eh.h> | |
33 | #include <scsi/scsi_device.h> | |
34 | ||
35 | #include "debug.h" | |
36 | #include "rts51x.h" | |
37 | #include "rts51x_chip.h" | |
38 | #include "rts51x_card.h" | |
39 | #include "rts51x_scsi.h" | |
40 | #include "rts51x_transport.h" | |
41 | #include "trace.h" | |
42 | ||
43 | /*********************************************************************** | |
44 | * Scatter-gather transfer buffer access routines | |
45 | ***********************************************************************/ | |
46 | ||
47 | /* Copy a buffer of length buflen to/from the srb's transfer buffer. | |
48 | * Update the **sgptr and *offset variables so that the next copy will | |
49 | * pick up from where this one left off. | |
50 | */ | |
51 | ||
52 | unsigned int rts51x_access_sglist(unsigned char *buffer, | |
53 | unsigned int buflen, void *sglist, | |
54 | void **sgptr, unsigned int *offset, | |
55 | enum xfer_buf_dir dir) | |
56 | { | |
57 | unsigned int cnt; | |
58 | struct scatterlist *sg = (struct scatterlist *)*sgptr; | |
59 | ||
60 | /* We have to go through the list one entry | |
61 | * at a time. Each s-g entry contains some number of pages, and | |
62 | * each page has to be kmap()'ed separately. If the page is already | |
63 | * in kernel-addressable memory then kmap() will return its address. | |
64 | * If the page is not directly accessible -- such as a user buffer | |
65 | * located in high memory -- then kmap() will map it to a temporary | |
66 | * position in the kernel's virtual address space. | |
67 | */ | |
68 | ||
69 | if (!sg) | |
70 | sg = (struct scatterlist *)sglist; | |
71 | ||
72 | /* This loop handles a single s-g list entry, which may | |
73 | * include multiple pages. Find the initial page structure | |
74 | * and the starting offset within the page, and update | |
75 | * the *offset and **sgptr values for the next loop. | |
76 | */ | |
77 | cnt = 0; | |
78 | while (cnt < buflen && sg) { | |
79 | struct page *page = sg_page(sg) + | |
80 | ((sg->offset + *offset) >> PAGE_SHIFT); | |
81 | unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE - 1); | |
82 | unsigned int sglen = sg->length - *offset; | |
83 | ||
84 | if (sglen > buflen - cnt) { | |
85 | ||
86 | /* Transfer ends within this s-g entry */ | |
87 | sglen = buflen - cnt; | |
88 | *offset += sglen; | |
89 | } else { | |
90 | ||
91 | /* Transfer continues to next s-g entry */ | |
92 | *offset = 0; | |
93 | sg = sg_next(sg); | |
94 | } | |
95 | ||
96 | /* Transfer the data for all the pages in this | |
97 | * s-g entry. For each page: call kmap(), do the | |
98 | * transfer, and call kunmap() immediately after. */ | |
99 | while (sglen > 0) { | |
100 | unsigned int plen = min(sglen, (unsigned int) | |
101 | PAGE_SIZE - poff); | |
102 | unsigned char *ptr = kmap(page); | |
103 | ||
104 | if (dir == TO_XFER_BUF) | |
105 | memcpy(ptr + poff, buffer + cnt, plen); | |
106 | else | |
107 | memcpy(buffer + cnt, ptr + poff, plen); | |
108 | kunmap(page); | |
109 | ||
110 | /* Start at the beginning of the next page */ | |
111 | poff = 0; | |
112 | ++page; | |
113 | cnt += plen; | |
114 | sglen -= plen; | |
115 | } | |
116 | } | |
117 | *sgptr = sg; | |
118 | ||
119 | /* Return the amount actually transferred */ | |
120 | return cnt; | |
121 | } | |
122 | ||
5085d127 | 123 | static unsigned int rts51x_access_xfer_buf(unsigned char *buffer, |
1dac4186 | 124 | unsigned int buflen, struct scsi_cmnd *srb, |
125 | struct scatterlist **sgptr, | |
126 | unsigned int *offset, enum xfer_buf_dir dir) | |
127 | { | |
128 | return rts51x_access_sglist(buffer, buflen, (void *)scsi_sglist(srb), | |
129 | (void **)sgptr, offset, dir); | |
130 | } | |
131 | ||
132 | /* Store the contents of buffer into srb's transfer buffer and set the | |
133 | * SCSI residue. | |
134 | */ | |
135 | void rts51x_set_xfer_buf(unsigned char *buffer, | |
136 | unsigned int buflen, struct scsi_cmnd *srb) | |
137 | { | |
138 | unsigned int offset = 0; | |
139 | struct scatterlist *sg = NULL; | |
140 | ||
141 | buflen = min(buflen, scsi_bufflen(srb)); | |
142 | buflen = rts51x_access_xfer_buf(buffer, buflen, srb, &sg, &offset, | |
143 | TO_XFER_BUF); | |
144 | if (buflen < scsi_bufflen(srb)) | |
145 | scsi_set_resid(srb, scsi_bufflen(srb) - buflen); | |
146 | } | |
147 | ||
148 | void rts51x_get_xfer_buf(unsigned char *buffer, | |
149 | unsigned int buflen, struct scsi_cmnd *srb) | |
150 | { | |
151 | unsigned int offset = 0; | |
152 | struct scatterlist *sg = NULL; | |
153 | ||
154 | buflen = min(buflen, scsi_bufflen(srb)); | |
155 | buflen = rts51x_access_xfer_buf(buffer, buflen, srb, &sg, &offset, | |
156 | FROM_XFER_BUF); | |
157 | if (buflen < scsi_bufflen(srb)) | |
158 | scsi_set_resid(srb, scsi_bufflen(srb) - buflen); | |
159 | } | |
160 | ||
161 | /* This is the completion handler which will wake us up when an URB | |
162 | * completes. | |
163 | */ | |
164 | static void urb_done_completion(struct urb *urb) | |
165 | { | |
166 | struct completion *urb_done_ptr = urb->context; | |
167 | ||
168 | if (urb_done_ptr) | |
169 | complete(urb_done_ptr); | |
170 | } | |
171 | ||
172 | /* This is the common part of the URB message submission code | |
173 | * | |
174 | * All URBs from the driver involved in handling a queued scsi | |
175 | * command _must_ pass through this function (or something like it) for the | |
176 | * abort mechanisms to work properly. | |
177 | */ | |
178 | static int rts51x_msg_common(struct rts51x_chip *chip, struct urb *urb, | |
179 | int timeout) | |
180 | { | |
181 | struct rts51x_usb *rts51x = chip->usb; | |
182 | struct completion urb_done; | |
183 | long timeleft; | |
184 | int status; | |
185 | ||
186 | /* don't submit URBs during abort processing */ | |
187 | if (test_bit(FLIDX_ABORTING, &rts51x->dflags)) | |
188 | TRACE_RET(chip, -EIO); | |
189 | ||
190 | /* set up data structures for the wakeup system */ | |
191 | init_completion(&urb_done); | |
192 | ||
193 | /* fill the common fields in the URB */ | |
194 | urb->context = &urb_done; | |
195 | urb->actual_length = 0; | |
196 | urb->error_count = 0; | |
197 | urb->status = 0; | |
198 | ||
199 | /* we assume that if transfer_buffer isn't us->iobuf then it | |
200 | * hasn't been mapped for DMA. Yes, this is clunky, but it's | |
201 | * easier than always having the caller tell us whether the | |
202 | * transfer buffer has already been mapped. */ | |
203 | urb->transfer_flags = URB_NO_SETUP_DMA_MAP; | |
204 | if (urb->transfer_buffer == rts51x->iobuf) { | |
205 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
206 | urb->transfer_dma = rts51x->iobuf_dma; | |
207 | } | |
208 | urb->setup_dma = rts51x->cr_dma; | |
209 | ||
210 | /* submit the URB */ | |
211 | status = usb_submit_urb(urb, GFP_NOIO); | |
212 | if (status) { | |
213 | /* something went wrong */ | |
214 | TRACE_RET(chip, status); | |
215 | } | |
216 | ||
217 | /* since the URB has been submitted successfully, it's now okay | |
218 | * to cancel it */ | |
219 | set_bit(FLIDX_URB_ACTIVE, &rts51x->dflags); | |
220 | ||
221 | /* did an abort occur during the submission? */ | |
222 | if (test_bit(FLIDX_ABORTING, &rts51x->dflags)) { | |
223 | ||
224 | /* cancel the URB, if it hasn't been cancelled already */ | |
225 | if (test_and_clear_bit(FLIDX_URB_ACTIVE, &rts51x->dflags)) { | |
226 | RTS51X_DEBUGP("-- cancelling URB\n"); | |
227 | usb_unlink_urb(urb); | |
228 | } | |
229 | } | |
230 | ||
231 | /* wait for the completion of the URB */ | |
232 | timeleft = | |
233 | wait_for_completion_interruptible_timeout(&urb_done, | |
234 | (timeout * HZ / | |
235 | 1000) ? : | |
236 | MAX_SCHEDULE_TIMEOUT); | |
237 | ||
238 | clear_bit(FLIDX_URB_ACTIVE, &rts51x->dflags); | |
239 | ||
240 | if (timeleft <= 0) { | |
241 | RTS51X_DEBUGP("%s -- cancelling URB\n", | |
242 | timeleft == 0 ? "Timeout" : "Signal"); | |
243 | usb_kill_urb(urb); | |
244 | if (timeleft == 0) | |
245 | status = -ETIMEDOUT; | |
246 | else | |
247 | status = -EINTR; | |
248 | } else { | |
249 | status = urb->status; | |
250 | } | |
251 | ||
252 | return status; | |
253 | } | |
254 | ||
5085d127 OR |
255 | static int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe); |
256 | ||
1dac4186 | 257 | /* |
258 | * Interpret the results of a URB transfer | |
259 | */ | |
260 | static int interpret_urb_result(struct rts51x_chip *chip, unsigned int pipe, | |
261 | unsigned int length, int result, | |
262 | unsigned int partial) | |
263 | { | |
264 | int retval = STATUS_SUCCESS; | |
265 | ||
266 | /* RTS51X_DEBUGP("Status code %d; transferred %u/%u\n", | |
267 | result, partial, length); */ | |
268 | switch (result) { | |
269 | /* no error code; did we send all the data? */ | |
270 | case 0: | |
271 | if (partial != length) { | |
272 | RTS51X_DEBUGP("-- short transfer\n"); | |
273 | TRACE_RET(chip, STATUS_TRANS_SHORT); | |
274 | } | |
275 | /* RTS51X_DEBUGP("-- transfer complete\n"); */ | |
276 | return STATUS_SUCCESS; | |
277 | /* stalled */ | |
278 | case -EPIPE: | |
279 | /* for control endpoints, (used by CB[I]) a stall indicates | |
280 | * a failed command */ | |
281 | if (usb_pipecontrol(pipe)) { | |
282 | RTS51X_DEBUGP("-- stall on control pipe\n"); | |
283 | TRACE_RET(chip, STATUS_STALLED); | |
284 | } | |
285 | /* for other sorts of endpoint, clear the stall */ | |
286 | RTS51X_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); | |
287 | if (rts51x_clear_halt(chip, pipe) < 0) | |
288 | TRACE_RET(chip, STATUS_ERROR); | |
289 | retval = STATUS_STALLED; | |
290 | TRACE_GOTO(chip, Exit); | |
291 | ||
292 | /* babble - the device tried to send more than | |
293 | * we wanted to read */ | |
294 | case -EOVERFLOW: | |
295 | RTS51X_DEBUGP("-- babble\n"); | |
296 | retval = STATUS_TRANS_LONG; | |
297 | TRACE_GOTO(chip, Exit); | |
298 | ||
299 | /* the transfer was cancelled by abort, | |
300 | * disconnect, or timeout */ | |
301 | case -ECONNRESET: | |
302 | RTS51X_DEBUGP("-- transfer cancelled\n"); | |
303 | retval = STATUS_ERROR; | |
304 | TRACE_GOTO(chip, Exit); | |
305 | ||
306 | /* short scatter-gather read transfer */ | |
307 | case -EREMOTEIO: | |
308 | RTS51X_DEBUGP("-- short read transfer\n"); | |
309 | retval = STATUS_TRANS_SHORT; | |
310 | TRACE_GOTO(chip, Exit); | |
311 | ||
312 | /* abort or disconnect in progress */ | |
313 | case -EIO: | |
314 | RTS51X_DEBUGP("-- abort or disconnect in progress\n"); | |
315 | retval = STATUS_ERROR; | |
316 | TRACE_GOTO(chip, Exit); | |
317 | ||
318 | case -ETIMEDOUT: | |
319 | RTS51X_DEBUGP("-- time out\n"); | |
320 | retval = STATUS_TIMEDOUT; | |
321 | TRACE_GOTO(chip, Exit); | |
322 | ||
323 | /* the catch-all error case */ | |
324 | default: | |
325 | RTS51X_DEBUGP("-- unknown error\n"); | |
326 | retval = STATUS_ERROR; | |
327 | TRACE_GOTO(chip, Exit); | |
328 | } | |
329 | ||
330 | Exit: | |
331 | if ((retval != STATUS_SUCCESS) && !usb_pipecontrol(pipe)) | |
332 | rts51x_clear_hw_error(chip); | |
333 | ||
334 | return retval; | |
335 | } | |
336 | ||
337 | int rts51x_ctrl_transfer(struct rts51x_chip *chip, unsigned int pipe, | |
338 | u8 request, u8 requesttype, u16 value, u16 index, | |
339 | void *data, u16 size, int timeout) | |
340 | { | |
341 | struct rts51x_usb *rts51x = chip->usb; | |
342 | int result; | |
343 | ||
344 | RTS51X_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", | |
345 | __func__, request, requesttype, value, index, size); | |
346 | ||
347 | /* fill in the devrequest structure */ | |
348 | rts51x->cr->bRequestType = requesttype; | |
349 | rts51x->cr->bRequest = request; | |
350 | rts51x->cr->wValue = cpu_to_le16(value); | |
351 | rts51x->cr->wIndex = cpu_to_le16(index); | |
352 | rts51x->cr->wLength = cpu_to_le16(size); | |
353 | ||
354 | /* fill and submit the URB */ | |
355 | usb_fill_control_urb(rts51x->current_urb, rts51x->pusb_dev, pipe, | |
356 | (unsigned char *)rts51x->cr, data, size, | |
357 | urb_done_completion, NULL); | |
358 | result = rts51x_msg_common(chip, rts51x->current_urb, timeout); | |
359 | ||
360 | return interpret_urb_result(chip, pipe, size, result, | |
361 | rts51x->current_urb->actual_length); | |
362 | } | |
363 | ||
5085d127 | 364 | static int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe) |
1dac4186 | 365 | { |
366 | int result; | |
367 | int endp = usb_pipeendpoint(pipe); | |
368 | ||
369 | if (usb_pipein(pipe)) | |
370 | endp |= USB_DIR_IN; | |
371 | ||
372 | result = rts51x_ctrl_transfer(chip, SND_CTRL_PIPE(chip), | |
373 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, | |
374 | USB_ENDPOINT_HALT, endp, NULL, 0, 3000); | |
375 | if (result != STATUS_SUCCESS) | |
376 | TRACE_RET(chip, STATUS_FAIL); | |
377 | ||
378 | usb_reset_endpoint(chip->usb->pusb_dev, endp); | |
379 | ||
380 | return STATUS_SUCCESS; | |
381 | } | |
382 | ||
1dac4186 | 383 | static void rts51x_sg_clean(struct usb_sg_request *io) |
384 | { | |
385 | if (io->urbs) { | |
386 | while (io->entries--) | |
387 | usb_free_urb(io->urbs[io->entries]); | |
388 | kfree(io->urbs); | |
389 | io->urbs = NULL; | |
390 | } | |
1dac4186 | 391 | io->dev = NULL; |
392 | } | |
1dac4186 | 393 | |
5085d127 | 394 | static int rts51x_sg_init(struct usb_sg_request *io, struct usb_device *dev, |
1dac4186 | 395 | unsigned pipe, unsigned period, struct scatterlist *sg, |
396 | int nents, size_t length, gfp_t mem_flags) | |
397 | { | |
398 | return usb_sg_init(io, dev, pipe, period, sg, nents, length, mem_flags); | |
399 | } | |
400 | ||
5085d127 | 401 | static int rts51x_sg_wait(struct usb_sg_request *io, int timeout) |
1dac4186 | 402 | { |
403 | long timeleft; | |
404 | int i; | |
405 | int entries = io->entries; | |
406 | ||
407 | /* queue the urbs. */ | |
408 | spin_lock_irq(&io->lock); | |
409 | i = 0; | |
410 | while (i < entries && !io->status) { | |
411 | int retval; | |
412 | ||
413 | io->urbs[i]->dev = io->dev; | |
414 | retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); | |
415 | ||
416 | /* after we submit, let completions or cancelations fire; | |
417 | * we handshake using io->status. | |
418 | */ | |
419 | spin_unlock_irq(&io->lock); | |
420 | switch (retval) { | |
7086e6e5 | 421 | /* maybe the retry will recover */ |
1dac4186 | 422 | case -ENXIO: /* hc didn't queue this one */ |
423 | case -EAGAIN: | |
424 | case -ENOMEM: | |
425 | io->urbs[i]->dev = NULL; | |
426 | retval = 0; | |
427 | yield(); | |
428 | break; | |
429 | ||
430 | /* no error? continue immediately. | |
431 | * | |
432 | * NOTE: to work better with UHCI (4K I/O buffer may | |
433 | * need 3K of TDs) it may be good to limit how many | |
434 | * URBs are queued at once; N milliseconds? | |
435 | */ | |
436 | case 0: | |
437 | ++i; | |
438 | cpu_relax(); | |
439 | break; | |
440 | ||
441 | /* fail any uncompleted urbs */ | |
442 | default: | |
443 | io->urbs[i]->dev = NULL; | |
444 | io->urbs[i]->status = retval; | |
445 | dev_dbg(&io->dev->dev, "%s, submit --> %d\n", | |
446 | __func__, retval); | |
447 | usb_sg_cancel(io); | |
448 | } | |
449 | spin_lock_irq(&io->lock); | |
450 | if (retval && (io->status == 0 || io->status == -ECONNRESET)) | |
451 | io->status = retval; | |
452 | } | |
453 | io->count -= entries - i; | |
454 | if (io->count == 0) | |
455 | complete(&io->complete); | |
456 | spin_unlock_irq(&io->lock); | |
457 | ||
458 | timeleft = | |
459 | wait_for_completion_interruptible_timeout(&io->complete, | |
460 | (timeout * HZ / | |
461 | 1000) ? : | |
462 | MAX_SCHEDULE_TIMEOUT); | |
463 | if (timeleft <= 0) { | |
464 | RTS51X_DEBUGP("%s -- cancelling SG request\n", | |
465 | timeleft == 0 ? "Timeout" : "Signal"); | |
466 | usb_sg_cancel(io); | |
467 | if (timeleft == 0) | |
468 | io->status = -ETIMEDOUT; | |
469 | else | |
470 | io->status = -EINTR; | |
471 | } | |
472 | ||
473 | rts51x_sg_clean(io); | |
474 | return io->status; | |
475 | } | |
476 | ||
477 | /* | |
478 | * Transfer a scatter-gather list via bulk transfer | |
479 | * | |
480 | * This function does basically the same thing as usb_stor_bulk_transfer_buf() | |
481 | * above, but it uses the usbcore scatter-gather library. | |
482 | */ | |
483 | static int rts51x_bulk_transfer_sglist(struct rts51x_chip *chip, | |
484 | unsigned int pipe, | |
485 | struct scatterlist *sg, int num_sg, | |
486 | unsigned int length, | |
487 | unsigned int *act_len, int timeout) | |
488 | { | |
489 | int result; | |
490 | ||
491 | /* don't submit s-g requests during abort processing */ | |
492 | if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) | |
493 | TRACE_RET(chip, STATUS_ERROR); | |
494 | ||
495 | /* initialize the scatter-gather request block */ | |
496 | RTS51X_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__, | |
497 | length, num_sg); | |
498 | result = | |
499 | rts51x_sg_init(&chip->usb->current_sg, chip->usb->pusb_dev, pipe, 0, | |
500 | sg, num_sg, length, GFP_NOIO); | |
501 | if (result) { | |
502 | RTS51X_DEBUGP("rts51x_sg_init returned %d\n", result); | |
503 | TRACE_RET(chip, STATUS_ERROR); | |
504 | } | |
505 | ||
506 | /* since the block has been initialized successfully, it's now | |
507 | * okay to cancel it */ | |
508 | set_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); | |
509 | ||
510 | /* did an abort occur during the submission? */ | |
511 | if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) { | |
512 | ||
513 | /* cancel the request, if it hasn't been cancelled already */ | |
514 | if (test_and_clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags)) { | |
515 | RTS51X_DEBUGP("-- cancelling sg request\n"); | |
516 | usb_sg_cancel(&chip->usb->current_sg); | |
517 | } | |
518 | } | |
519 | ||
520 | /* wait for the completion of the transfer */ | |
521 | result = rts51x_sg_wait(&chip->usb->current_sg, timeout); | |
522 | ||
523 | clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); | |
524 | ||
525 | /* result = us->current_sg.status; */ | |
526 | if (act_len) | |
527 | *act_len = chip->usb->current_sg.bytes; | |
528 | return interpret_urb_result(chip, pipe, length, result, | |
529 | chip->usb->current_sg.bytes); | |
530 | } | |
1dac4186 | 531 | |
5085d127 OR |
532 | static int rts51x_bulk_transfer_buf(struct rts51x_chip *chip, |
533 | unsigned int pipe, | |
1dac4186 | 534 | void *buf, unsigned int length, |
535 | unsigned int *act_len, int timeout) | |
536 | { | |
537 | int result; | |
538 | ||
539 | /* fill and submit the URB */ | |
540 | usb_fill_bulk_urb(chip->usb->current_urb, chip->usb->pusb_dev, pipe, | |
541 | buf, length, urb_done_completion, NULL); | |
542 | result = rts51x_msg_common(chip, chip->usb->current_urb, timeout); | |
543 | ||
544 | /* store the actual length of the data transferred */ | |
545 | if (act_len) | |
546 | *act_len = chip->usb->current_urb->actual_length; | |
547 | return interpret_urb_result(chip, pipe, length, result, | |
548 | chip->usb->current_urb->actual_length); | |
549 | } | |
550 | ||
551 | int rts51x_transfer_data(struct rts51x_chip *chip, unsigned int pipe, | |
552 | void *buf, unsigned int len, int use_sg, | |
553 | unsigned int *act_len, int timeout) | |
554 | { | |
555 | int result; | |
556 | ||
557 | if (timeout < 600) | |
558 | timeout = 600; | |
559 | ||
560 | if (use_sg) { | |
561 | result = | |
562 | rts51x_bulk_transfer_sglist(chip, pipe, | |
563 | (struct scatterlist *)buf, | |
564 | use_sg, len, act_len, timeout); | |
565 | } else { | |
566 | result = | |
567 | rts51x_bulk_transfer_buf(chip, pipe, buf, len, act_len, | |
568 | timeout); | |
569 | } | |
570 | ||
571 | return result; | |
572 | } | |
573 | ||
574 | int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe, | |
575 | void *buf, void **ptr, unsigned int *offset, | |
576 | unsigned int len, int use_sg, | |
577 | unsigned int *act_len, int timeout) | |
578 | { | |
579 | int result; | |
580 | ||
581 | if (timeout < 600) | |
582 | timeout = 600; | |
583 | ||
584 | if (use_sg) { | |
585 | void *tmp_buf = kmalloc(len, GFP_KERNEL); | |
586 | if (!tmp_buf) | |
587 | TRACE_RET(chip, STATUS_NOMEM); | |
588 | ||
589 | if (usb_pipeout(pipe)) { | |
590 | rts51x_access_sglist(tmp_buf, len, buf, ptr, offset, | |
591 | FROM_XFER_BUF); | |
592 | } | |
593 | result = | |
594 | rts51x_bulk_transfer_buf(chip, pipe, tmp_buf, len, act_len, | |
595 | timeout); | |
596 | if (result == STATUS_SUCCESS) { | |
597 | if (usb_pipein(pipe)) { | |
598 | rts51x_access_sglist(tmp_buf, len, buf, ptr, | |
599 | offset, TO_XFER_BUF); | |
600 | } | |
601 | } | |
602 | ||
603 | kfree(tmp_buf); | |
1dac4186 | 604 | } else { |
605 | unsigned int step = 0; | |
606 | if (offset) | |
607 | step = *offset; | |
608 | result = | |
609 | rts51x_bulk_transfer_buf(chip, pipe, buf + step, len, | |
610 | act_len, timeout); | |
611 | if (act_len) | |
612 | step += *act_len; | |
613 | else | |
614 | step += len; | |
615 | if (offset) | |
616 | *offset = step; | |
617 | } | |
618 | ||
619 | return result; | |
620 | } | |
621 | ||
aa2f92ae | 622 | int rts51x_get_epc_status(struct rts51x_chip *chip, u16 *status) |
1dac4186 | 623 | { |
624 | unsigned int pipe = RCV_INTR_PIPE(chip); | |
625 | struct usb_host_endpoint *ep; | |
626 | struct completion urb_done; | |
627 | int result; | |
628 | ||
629 | if (!status) | |
630 | TRACE_RET(chip, STATUS_ERROR); | |
631 | ||
632 | /* set up data structures for the wakeup system */ | |
633 | init_completion(&urb_done); | |
634 | ||
635 | ep = chip->usb->pusb_dev->ep_in[usb_pipeendpoint(pipe)]; | |
636 | ||
637 | /* fill and submit the URB */ | |
638 | /* We set interval to 1 here, so the polling interval is controlled | |
639 | * by our polling thread */ | |
640 | usb_fill_int_urb(chip->usb->intr_urb, chip->usb->pusb_dev, pipe, | |
641 | status, 2, urb_done_completion, &urb_done, 1); | |
642 | ||
643 | result = rts51x_msg_common(chip, chip->usb->intr_urb, 50); | |
644 | ||
645 | return interpret_urb_result(chip, pipe, 2, result, | |
646 | chip->usb->intr_urb->actual_length); | |
647 | } | |
648 | ||
649 | u8 media_not_present[] = { | |
650 | 0x70, 0, 0x02, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0 }; | |
651 | u8 invalid_cmd_field[] = { | |
652 | 0x70, 0, 0x05, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0 }; | |
653 | ||
654 | void rts51x_invoke_transport(struct scsi_cmnd *srb, struct rts51x_chip *chip) | |
655 | { | |
656 | int result; | |
657 | ||
658 | #ifdef CONFIG_PM | |
659 | if (chip->option.ss_en) { | |
660 | if (srb->cmnd[0] == TEST_UNIT_READY) { | |
661 | if (RTS51X_CHK_STAT(chip, STAT_SS)) { | |
662 | if (check_fake_card_ready(chip, | |
663 | SCSI_LUN(srb))) { | |
664 | srb->result = SAM_STAT_GOOD; | |
665 | } else { | |
666 | srb->result = SAM_STAT_CHECK_CONDITION; | |
667 | memcpy(srb->sense_buffer, | |
668 | media_not_present, SENSE_SIZE); | |
669 | } | |
670 | return; | |
671 | } | |
672 | } else if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { | |
673 | if (RTS51X_CHK_STAT(chip, STAT_SS)) { | |
674 | int prevent = srb->cmnd[4] & 0x1; | |
675 | ||
676 | if (prevent) { | |
677 | srb->result = SAM_STAT_CHECK_CONDITION; | |
678 | memcpy(srb->sense_buffer, | |
679 | invalid_cmd_field, SENSE_SIZE); | |
680 | } else { | |
681 | srb->result = SAM_STAT_GOOD; | |
682 | } | |
683 | return; | |
684 | } | |
685 | } else { | |
686 | if (RTS51X_CHK_STAT(chip, STAT_SS) | |
687 | || RTS51X_CHK_STAT(chip, STAT_SS_PRE)) { | |
688 | /* Wake up device */ | |
689 | RTS51X_DEBUGP("Try to wake up device\n"); | |
690 | chip->resume_from_scsi = 1; | |
691 | ||
692 | rts51x_try_to_exit_ss(chip); | |
693 | ||
694 | if (RTS51X_CHK_STAT(chip, STAT_SS)) { | |
695 | wait_timeout(3000); | |
696 | ||
697 | rts51x_init_chip(chip); | |
698 | rts51x_init_cards(chip); | |
699 | } | |
700 | } | |
701 | } | |
702 | } | |
703 | #endif | |
704 | ||
705 | result = rts51x_scsi_handler(srb, chip); | |
706 | ||
707 | /* if there is a transport error, reset and don't auto-sense */ | |
708 | if (result == TRANSPORT_ERROR) { | |
709 | RTS51X_DEBUGP("-- transport indicates error, resetting\n"); | |
710 | srb->result = DID_ERROR << 16; | |
711 | goto Handle_Errors; | |
712 | } | |
713 | ||
714 | srb->result = SAM_STAT_GOOD; | |
715 | ||
716 | /* | |
717 | * If we have a failure, we're going to do a REQUEST_SENSE | |
718 | * automatically. Note that we differentiate between a command | |
719 | * "failure" and an "error" in the transport mechanism. | |
720 | */ | |
721 | if (result == TRANSPORT_FAILED) { | |
722 | /* set the result so the higher layers expect this data */ | |
723 | srb->result = SAM_STAT_CHECK_CONDITION; | |
724 | memcpy(srb->sense_buffer, | |
725 | (unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]), | |
726 | sizeof(struct sense_data_t)); | |
727 | } | |
728 | ||
729 | return; | |
730 | ||
731 | /* Error and abort processing: try to resynchronize with the device | |
732 | * by issuing a port reset. If that fails, try a class-specific | |
733 | * device reset. */ | |
734 | Handle_Errors: | |
735 | return; | |
736 | } |