aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/uss720.c
diff options
context:
space:
mode:
authorThomas Sailer <sailer@ife.ee.ethz.ch>2005-09-09 04:43:50 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-12 15:23:53 -0400
commit0f36163d3abefbda1b21a330b3fdf3c2dc076d94 (patch)
tree54eddfc5acb73a32991ad59aaf99516d1bfbceef /drivers/usb/misc/uss720.c
parentce441594e965e32965432404cfaba73e8fbc6ff7 (diff)
[PATCH] usb: fix uss720 schedule with interrupts off
This patch fixes the long standing schedule with interrupts off problem of the uss720 driver. The problem is caused by the parport layer calling the save and restore methods within a write_lock_irqsave guarded region. The fix is to issue the control transaction requests required by save and restore asynchronously. Signed-off-by: Thomas Sailer, <sailer@ife.ee.ethz.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc/uss720.c')
-rw-r--r--drivers/usb/misc/uss720.c393
1 files changed, 270 insertions, 123 deletions
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index faa74436de52..03fb70ef2eb3 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -3,8 +3,8 @@
3/* 3/*
4 * uss720.c -- USS720 USB Parport Cable. 4 * uss720.c -- USS720 USB Parport Cable.
5 * 5 *
6 * Copyright (C) 1999 6 * Copyright (C) 1999, 2005
7 * Thomas Sailer (sailer@ife.ee.ethz.ch) 7 * Thomas Sailer (t.sailer@alumni.ethz.ch)
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -23,103 +23,240 @@
23 * Based on parport_pc.c 23 * Based on parport_pc.c
24 * 24 *
25 * History: 25 * History:
26 * 0.1 04.08.99 Created 26 * 0.1 04.08.1999 Created
27 * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh 27 * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh
28 * Interrupt handling currently disabled because 28 * Interrupt handling currently disabled because
29 * usb_request_irq crashes somewhere within ohci.c 29 * usb_request_irq crashes somewhere within ohci.c
30 * for no apparent reason (that is for me, anyway) 30 * for no apparent reason (that is for me, anyway)
31 * ECP currently untested 31 * ECP currently untested
32 * 0.3 10.08.99 fixing merge errors 32 * 0.3 10.08.1999 fixing merge errors
33 * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable 33 * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable
34 * 0.5 20.09.99 usb_control_msg wrapper used 34 * 0.5 20.09.1999 usb_control_msg wrapper used
35 * Nov01.00 usb_device_table support by Adam J. Richter 35 * Nov01.2000 usb_device_table support by Adam J. Richter
36 * 08.04.01 Identify version on module load. gb 36 * 08.04.2001 Identify version on module load. gb
37 * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore
38 * context asynchronous
37 * 39 *
38 */ 40 */
39 41
40/*****************************************************************************/ 42/*****************************************************************************/
41 43
44#define DEBUG
45
42#include <linux/module.h> 46#include <linux/module.h>
43#include <linux/socket.h> 47#include <linux/socket.h>
44#include <linux/parport.h> 48#include <linux/parport.h>
45#include <linux/init.h> 49#include <linux/init.h>
46#include <linux/usb.h> 50#include <linux/usb.h>
47#include <linux/delay.h> 51#include <linux/delay.h>
52#include <linux/completion.h>
53#include <linux/kref.h>
48 54
49/* 55/*
50 * Version Information 56 * Version Information
51 */ 57 */
52#define DRIVER_VERSION "v0.5" 58#define DRIVER_VERSION "v0.6"
53#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch" 59#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
54#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip" 60#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
55 61
56/* --------------------------------------------------------------------- */ 62/* --------------------------------------------------------------------- */
57 63
58struct parport_uss720_private { 64struct parport_uss720_private {
59 struct usb_device *usbdev; 65 struct usb_device *usbdev;
60 void *irqhandle; 66 struct parport *pp;
61 unsigned int irqpipe; 67 struct kref ref_count;
62 unsigned char reg[7]; /* USB registers */ 68 __u8 reg[7]; /* USB registers */
69 struct list_head asynclist;
70 spinlock_t asynclock;
71};
72
73struct uss720_async_request {
74 struct parport_uss720_private *priv;
75 struct kref ref_count;
76 struct list_head asynclist;
77 struct completion compl;
78 struct urb *urb;
79 struct usb_ctrlrequest dr;
80 __u8 reg[7];
63}; 81};
64 82
65/* --------------------------------------------------------------------- */ 83/* --------------------------------------------------------------------- */
66 84
67static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val) 85static void destroy_priv(struct kref *kref)
68{ 86{
69 struct parport_uss720_private *priv = pp->private_data; 87 struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
70 struct usb_device *usbdev = priv->usbdev;
71 static const unsigned char regindex[9] = {
72 4, 0, 1, 5, 5, 0, 2, 3, 6
73 };
74 int ret;
75 88
76 if (!usbdev) 89 usb_put_dev(priv->usbdev);
77 return -1; 90 kfree(priv);
78 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000); 91 dbg("destroying priv datastructure");
79 if (ret != 7) { 92}
80 printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n", 93
81 (unsigned int)reg, ret); 94static void destroy_async(struct kref *kref)
82 ret = -1; 95{
83 } else { 96 struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
97 struct parport_uss720_private *priv = rq->priv;
98 unsigned long flags;
99
100 if (likely(rq->urb))
101 usb_free_urb(rq->urb);
102 spin_lock_irqsave(&priv->asynclock, flags);
103 list_del_init(&rq->asynclist);
104 spin_unlock_irqrestore(&priv->asynclock, flags);
105 kfree(rq);
106 kref_put(&priv->ref_count, destroy_priv);
107}
108
109/* --------------------------------------------------------------------- */
110
111static void async_complete(struct urb *urb, struct pt_regs *ptregs)
112{
113 struct uss720_async_request *rq;
114 struct parport *pp;
115 struct parport_uss720_private *priv;
116
117 rq = urb->context;
118 priv = rq->priv;
119 pp = priv->pp;
120 if (urb->status) {
121 err("async_complete: urb error %d", urb->status);
122 } else if (rq->dr.bRequest == 3) {
123 memcpy(priv->reg, rq->reg, sizeof(priv->reg));
84#if 0 124#if 0
85 printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n", 125 dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
86 (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], 126 (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
87 (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], 127 (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
88 (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]); 128 (unsigned int)priv->reg[6]);
89#endif 129#endif
90 /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ 130 /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
91 if (priv->reg[2] & priv->reg[1] & 0x10) 131 if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
92 parport_generic_irq(0, pp, NULL); 132 parport_generic_irq(0, pp, NULL);
93 ret = 0;
94 } 133 }
95 if (val) 134 complete(&rq->compl);
96 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]]; 135 kref_put(&rq->ref_count, destroy_async);
97 return ret;
98} 136}
99 137
100static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val) 138static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
139 __u8 request, __u8 requesttype, __u16 value, __u16 index,
140 unsigned int mem_flags)
101{ 141{
102 struct parport_uss720_private *priv = pp->private_data; 142 struct usb_device *usbdev;
103 struct usb_device *usbdev = priv->usbdev; 143 struct uss720_async_request *rq;
144 unsigned long flags;
104 int ret; 145 int ret;
105 146
147 if (!priv)
148 return NULL;
149 usbdev = priv->usbdev;
106 if (!usbdev) 150 if (!usbdev)
107 return -1; 151 return NULL;
108 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000); 152 rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
109 if (ret) { 153 if (!rq) {
110 printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 154 err("submit_async_request out of memory");
111 (unsigned int)reg, (unsigned int)val, ret); 155 return NULL;
112 } else { 156 }
113#if 0 157 kref_init(&rq->ref_count);
114 printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 158 INIT_LIST_HEAD(&rq->asynclist);
115 (unsigned int)reg, (unsigned int)val); 159 init_completion(&rq->compl);
116#endif 160 kref_get(&priv->ref_count);
161 rq->priv = priv;
162 rq->urb = usb_alloc_urb(0, mem_flags);
163 if (!rq->urb) {
164 kref_put(&rq->ref_count, destroy_async);
165 err("submit_async_request out of memory");
166 return NULL;
167 }
168 rq->dr.bRequestType = requesttype;
169 rq->dr.bRequest = request;
170 rq->dr.wValue = cpu_to_le16(value);
171 rq->dr.wIndex = cpu_to_le16(index);
172 rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
173 usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
174 (unsigned char *)&rq->dr,
175 (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
176 /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
177 spin_lock_irqsave(&priv->asynclock, flags);
178 list_add_tail(&rq->asynclist, &priv->asynclist);
179 spin_unlock_irqrestore(&priv->asynclock, flags);
180 ret = usb_submit_urb(rq->urb, mem_flags);
181 if (!ret) {
182 kref_get(&rq->ref_count);
183 return rq;
117 } 184 }
185 kref_put(&rq->ref_count, destroy_async);
186 err("submit_async_request submit_urb failed with %d", ret);
187 return NULL;
188}
189
190static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
191{
192 struct uss720_async_request *rq;
193 unsigned long flags;
194 unsigned int ret = 0;
195
196 spin_lock_irqsave(&priv->asynclock, flags);
197 list_for_each_entry(rq, &priv->asynclist, asynclist) {
198 usb_unlink_urb(rq->urb);
199 ret++;
200 }
201 spin_unlock_irqrestore(&priv->asynclock, flags);
118 return ret; 202 return ret;
119} 203}
120 204
121/* --------------------------------------------------------------------- */ 205/* --------------------------------------------------------------------- */
122 206
207static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
208{
209 struct parport_uss720_private *priv;
210 struct uss720_async_request *rq;
211 static const unsigned char regindex[9] = {
212 4, 0, 1, 5, 5, 0, 2, 3, 6
213 };
214 int ret;
215
216 if (!pp)
217 return -EIO;
218 priv = pp->private_data;
219 rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
220 if (!rq) {
221 err("get_1284_register(%u) failed", (unsigned int)reg);
222 return -EIO;
223 }
224 if (!val) {
225 kref_put(&rq->ref_count, destroy_async);
226 return 0;
227 }
228 if (wait_for_completion_timeout(&rq->compl, HZ)) {
229 ret = rq->urb->status;
230 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
231 if (ret)
232 warn("get_1284_register: usb error %d", ret);
233 kref_put(&rq->ref_count, destroy_async);
234 return ret;
235 }
236 warn("get_1284_register timeout");
237 kill_all_async_requests_priv(priv);
238 return -EIO;
239}
240
241static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
242{
243 struct parport_uss720_private *priv;
244 struct uss720_async_request *rq;
245
246 if (!pp)
247 return -EIO;
248 priv = pp->private_data;
249 rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
250 if (!rq) {
251 err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
252 return -EIO;
253 }
254 kref_put(&rq->ref_count, destroy_async);
255 return 0;
256}
257
258/* --------------------------------------------------------------------- */
259
123/* ECR modes */ 260/* ECR modes */
124#define ECR_SPP 00 261#define ECR_SPP 00
125#define ECR_PS2 01 262#define ECR_PS2 01
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
132{ 269{
133 struct parport_uss720_private *priv = pp->private_data; 270 struct parport_uss720_private *priv = pp->private_data;
134 int mode; 271 int mode;
272 __u8 reg;
135 273
136 if (get_1284_register(pp, 6, NULL)) 274 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
137 return -EIO; 275 return -EIO;
138 /* Bits <7:5> contain the mode. */ 276 /* Bits <7:5> contain the mode. */
139 mode = (priv->reg[2] >> 5) & 0x7; 277 mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
153 case ECR_ECP: /* ECP Parallel Port mode */ 291 case ECR_ECP: /* ECP Parallel Port mode */
154 /* Poll slowly. */ 292 /* Poll slowly. */
155 for (;;) { 293 for (;;) {
156 if (get_1284_register(pp, 6, NULL)) 294 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
157 return -EIO; 295 return -EIO;
158 if (priv->reg[2] & 0x01) 296 if (priv->reg[2] & 0x01)
159 break; 297 break;
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
167 } 305 }
168 } 306 }
169 /* Set the mode. */ 307 /* Set the mode. */
170 if (set_1284_register(pp, 6, m << 5)) 308 if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
309 return -EIO;
310 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
171 return -EIO; 311 return -EIO;
172 return 0; 312 return 0;
173} 313}
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
179{ 319{
180 unsigned char stat; 320 unsigned char stat;
181 321
182 if (get_1284_register(pp, 1, &stat)) 322 if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
183 return 1; 323 return 1;
184 return stat & 1; 324 return stat & 1;
185} 325}
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
205 345
206static void parport_uss720_write_data(struct parport *pp, unsigned char d) 346static void parport_uss720_write_data(struct parport *pp, unsigned char d)
207{ 347{
208 set_1284_register(pp, 0, d); 348 set_1284_register(pp, 0, d, GFP_KERNEL);
209} 349}
210 350
211static unsigned char parport_uss720_read_data(struct parport *pp) 351static unsigned char parport_uss720_read_data(struct parport *pp)
212{ 352{
213 unsigned char ret; 353 unsigned char ret;
214 354
215 if (get_1284_register(pp, 0, &ret)) 355 if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
216 return 0; 356 return 0;
217 return ret; 357 return ret;
218} 358}
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
222 struct parport_uss720_private *priv = pp->private_data; 362 struct parport_uss720_private *priv = pp->private_data;
223 363
224 d = (d & 0xf) | (priv->reg[1] & 0xf0); 364 d = (d & 0xf) | (priv->reg[1] & 0xf0);
225 if (set_1284_register(pp, 2, d)) 365 if (set_1284_register(pp, 2, d, GFP_KERNEL))
226 return; 366 return;
227 priv->reg[1] = d; 367 priv->reg[1] = d;
228} 368}
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
241 mask &= 0x0f; 381 mask &= 0x0f;
242 val &= 0x0f; 382 val &= 0x0f;
243 d = (priv->reg[1] & (~mask)) ^ val; 383 d = (priv->reg[1] & (~mask)) ^ val;
244 if (set_1284_register(pp, 2, d)) 384 if (set_1284_register(pp, 2, d, GFP_KERNEL))
245 return 0; 385 return 0;
246 priv->reg[1] = d; 386 priv->reg[1] = d;
247 return d & 0xf; 387 return d & 0xf;
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
251{ 391{
252 unsigned char ret; 392 unsigned char ret;
253 393
254 if (get_1284_register(pp, 1, &ret)) 394 if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
255 return 0; 395 return 0;
256 return ret & 0xf8; 396 return ret & 0xf8;
257} 397}
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
262 unsigned char d; 402 unsigned char d;
263 403
264 d = priv->reg[1] & ~0x10; 404 d = priv->reg[1] & ~0x10;
265 if (set_1284_register(pp, 2, d)) 405 if (set_1284_register(pp, 2, d, GFP_KERNEL))
266 return; 406 return;
267 priv->reg[1] = d; 407 priv->reg[1] = d;
268} 408}
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
273 unsigned char d; 413 unsigned char d;
274 414
275 d = priv->reg[1] | 0x10; 415 d = priv->reg[1] | 0x10;
276 if (set_1284_register(pp, 2, d)) 416 if (set_1284_register(pp, 2, d, GFP_KERNEL))
277 return; 417 return;
278 priv->reg[1] = d; 418 priv->reg[1] = d;
279} 419}
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
284 unsigned char d; 424 unsigned char d;
285 425
286 d = priv->reg[1] & ~0x20; 426 d = priv->reg[1] & ~0x20;
287 if (set_1284_register(pp, 2, d)) 427 if (set_1284_register(pp, 2, d, GFP_KERNEL))
288 return; 428 return;
289 priv->reg[1] = d; 429 priv->reg[1] = d;
290} 430}
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
295 unsigned char d; 435 unsigned char d;
296 436
297 d = priv->reg[1] | 0x20; 437 d = priv->reg[1] | 0x20;
298 if (set_1284_register(pp, 2, d)) 438 if (set_1284_register(pp, 2, d, GFP_KERNEL))
299 return; 439 return;
300 priv->reg[1] = d; 440 priv->reg[1] = d;
301} 441}
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
310{ 450{
311 struct parport_uss720_private *priv = pp->private_data; 451 struct parport_uss720_private *priv = pp->private_data;
312 452
313 if (get_1284_register(pp, 2, NULL)) 453#if 0
454 if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
314 return; 455 return;
456#endif
315 s->u.pc.ctr = priv->reg[1]; 457 s->u.pc.ctr = priv->reg[1];
316 s->u.pc.ecr = priv->reg[2]; 458 s->u.pc.ecr = priv->reg[2];
317} 459}
318 460
319static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s) 461static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
320{ 462{
321 set_1284_register(pp, 2, s->u.pc.ctr); 463 struct parport_uss720_private *priv = pp->private_data;
322 set_1284_register(pp, 6, s->u.pc.ecr); 464
323 get_1284_register(pp, 2, NULL); 465 set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
466 set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
467 get_1284_register(pp, 2, NULL, GFP_ATOMIC);
468 priv->reg[1] = s->u.pc.ctr;
469 priv->reg[2] = s->u.pc.ecr;
324} 470}
325 471
326static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags) 472static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
331 if (change_mode(pp, ECR_EPP)) 477 if (change_mode(pp, ECR_EPP))
332 return 0; 478 return 0;
333 for (; got < length; got++) { 479 for (; got < length; got++) {
334 if (get_1284_register(pp, 4, (char *)buf)) 480 if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
335 break; 481 break;
336 buf++; 482 buf++;
337 if (priv->reg[0] & 0x01) { 483 if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
352 if (change_mode(pp, ECR_EPP)) 498 if (change_mode(pp, ECR_EPP))
353 return 0; 499 return 0;
354 for (; written < length; written++) { 500 for (; written < length; written++) {
355 if (set_1284_register(pp, 4, (char *)buf)) 501 if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
356 break; 502 break;
357 ((char*)buf)++; 503 ((char*)buf)++;
358 if (get_1284_register(pp, 1, NULL)) 504 if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
359 break; 505 break;
360 if (priv->reg[0] & 0x01) { 506 if (priv->reg[0] & 0x01) {
361 clear_epp_timeout(pp); 507 clear_epp_timeout(pp);
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
390 if (change_mode(pp, ECR_EPP)) 536 if (change_mode(pp, ECR_EPP))
391 return 0; 537 return 0;
392 for (; got < length; got++) { 538 for (; got < length; got++) {
393 if (get_1284_register(pp, 3, (char *)buf)) 539 if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
394 break; 540 break;
395 buf++; 541 buf++;
396 if (priv->reg[0] & 0x01) { 542 if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
410 if (change_mode(pp, ECR_EPP)) 556 if (change_mode(pp, ECR_EPP))
411 return 0; 557 return 0;
412 for (; written < length; written++) { 558 for (; written < length; written++) {
413 if (set_1284_register(pp, 3, *(char *)buf)) 559 if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
414 break; 560 break;
415 buf++; 561 buf++;
416 if (get_1284_register(pp, 1, NULL)) 562 if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
417 break; 563 break;
418 if (priv->reg[0] & 0x01) { 564 if (priv->reg[0] & 0x01) {
419 clear_epp_timeout(pp); 565 clear_epp_timeout(pp);
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
467 if (change_mode(pp, ECR_ECP)) 613 if (change_mode(pp, ECR_ECP))
468 return 0; 614 return 0;
469 for (; written < len; written++) { 615 for (; written < len; written++) {
470 if (set_1284_register(pp, 5, *(char *)buffer)) 616 if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
471 break; 617 break;
472 buffer++; 618 buffer++;
473 } 619 }
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
536static int uss720_probe(struct usb_interface *intf, 682static int uss720_probe(struct usb_interface *intf,
537 const struct usb_device_id *id) 683 const struct usb_device_id *id)
538{ 684{
539 struct usb_device *usbdev = interface_to_usbdev(intf); 685 struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
540 struct usb_host_interface *interface; 686 struct usb_host_interface *interface;
541 struct usb_host_endpoint *endpoint; 687 struct usb_host_endpoint *endpoint;
542 struct parport_uss720_private *priv; 688 struct parport_uss720_private *priv;
543 struct parport *pp; 689 struct parport *pp;
690 unsigned char reg;
544 int i; 691 int i;
545 692
546 printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", 693 dbg("probe: vendor id 0x%x, device id 0x%x\n",
547 le16_to_cpu(usbdev->descriptor.idVendor), 694 le16_to_cpu(usbdev->descriptor.idVendor),
548 le16_to_cpu(usbdev->descriptor.idProduct)); 695 le16_to_cpu(usbdev->descriptor.idProduct));
549 696
550 /* our known interfaces have 3 alternate settings */ 697 /* our known interfaces have 3 alternate settings */
551 if (intf->num_altsetting != 3) 698 if (intf->num_altsetting != 3) {
699 usb_put_dev(usbdev);
552 return -ENODEV; 700 return -ENODEV;
553 701 }
554 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); 702 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
555 printk(KERN_DEBUG "uss720: set inteface result %d\n", i); 703 dbg("set inteface result %d", i);
556 704
557 interface = intf->cur_altsetting; 705 interface = intf->cur_altsetting;
558 706
559 /* 707 /*
560 * Allocate parport interface 708 * Allocate parport interface
561 */ 709 */
562 printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n"); 710 if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
563 711 usb_put_dev(usbdev);
564 if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
565 return -ENOMEM; 712 return -ENOMEM;
713 }
714 priv->pp = NULL;
715 priv->usbdev = usbdev;
716 kref_init(&priv->ref_count);
717 spin_lock_init(&priv->asynclock);
718 INIT_LIST_HEAD(&priv->asynclist);
566 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) { 719 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
567 printk(KERN_WARNING "usb-uss720: could not register parport\n"); 720 warn("could not register parport");
568 goto probe_abort; 721 goto probe_abort;
569 } 722 }
570 723
724 priv->pp = pp;
571 pp->private_data = priv; 725 pp->private_data = priv;
572 priv->usbdev = usbdev;
573 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; 726 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
574 727
575 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */ 728 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */
576 set_1284_register(pp, 7, 0x00); 729 set_1284_register(pp, 7, 0x00, GFP_KERNEL);
577 set_1284_register(pp, 6, 0x30); /* PS/2 mode */ 730 set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */
578 set_1284_register(pp, 2, 0x0c); 731 set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
579 /* debugging */ 732 /* debugging */
580 get_1284_register(pp, 0, NULL); 733 get_1284_register(pp, 0, &reg, GFP_KERNEL);
581 printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n", 734 dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
582 priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); 735 priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
583 736
584 endpoint = &interface->endpoint[2]; 737 endpoint = &interface->endpoint[2];
585 printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); 738 dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
586#if 0
587 priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
588 i = usb_request_irq(usbdev, priv->irqpipe,
589 uss720_irq, endpoint->bInterval,
590 pp, &priv->irqhandle);
591 if (i) {
592 printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
593 goto probe_abort_port;
594 }
595#endif
596 parport_announce_port(pp); 739 parport_announce_port(pp);
597 740
598 usb_set_intfdata (intf, pp); 741 usb_set_intfdata(intf, pp);
599 return 0; 742 return 0;
600 743
601#if 0
602probe_abort_port:
603 parport_put_port(pp);
604#endif
605probe_abort: 744probe_abort:
606 kfree(priv); 745 kill_all_async_requests_priv(priv);
746 kref_put(&priv->ref_count, destroy_priv);
607 return -ENODEV; 747 return -ENODEV;
608} 748}
609 749
610static void uss720_disconnect(struct usb_interface *intf) 750static void uss720_disconnect(struct usb_interface *intf)
611{ 751{
612 struct parport *pp = usb_get_intfdata (intf); 752 struct parport *pp = usb_get_intfdata(intf);
613 struct parport_uss720_private *priv; 753 struct parport_uss720_private *priv;
754 struct usb_device *usbdev;
614 755
615 usb_set_intfdata (intf, NULL); 756 dbg("disconnect");
757 usb_set_intfdata(intf, NULL);
616 if (pp) { 758 if (pp) {
617 priv = pp->private_data; 759 priv = pp->private_data;
618 parport_remove_port(pp); 760 usbdev = priv->usbdev;
619#if 0
620 usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
621#endif
622 priv->usbdev = NULL; 761 priv->usbdev = NULL;
762 priv->pp = NULL;
763 dbg("parport_remove_port");
764 parport_remove_port(pp);
623 parport_put_port(pp); 765 parport_put_port(pp);
624 kfree(priv); 766 kill_all_async_requests_priv(priv);
767 kref_put(&priv->ref_count, destroy_priv);
625 } 768 }
769 dbg("disconnect done");
626} 770}
627 771
628/* table of cables that work through this driver */ 772/* table of cables that work through this driver */
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
647 791
648/* --------------------------------------------------------------------- */ 792/* --------------------------------------------------------------------- */
649 793
650MODULE_AUTHOR( DRIVER_AUTHOR ); 794MODULE_AUTHOR(DRIVER_AUTHOR);
651MODULE_DESCRIPTION( DRIVER_DESC ); 795MODULE_DESCRIPTION(DRIVER_DESC);
652MODULE_LICENSE("GPL"); 796MODULE_LICENSE("GPL");
653 797
654static int __init uss720_init(void) 798static int __init uss720_init(void)
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
659 goto out; 803 goto out;
660 804
661 info(DRIVER_VERSION ":" DRIVER_DESC); 805 info(DRIVER_VERSION ":" DRIVER_DESC);
806 info("NOTE: this is a special purpose driver to allow nonstandard");
807 info("protocols (eg. bitbang) over USS720 usb to parallel cables");
808 info("If you just want to connect to a printer, use usblp instead");
662out: 809out:
663 return retval; 810 return retval;
664} 811}