Commit 3d69b1eb authored by Nick Holloway's avatar Nick Holloway Committed by Dave Jones

[PATCH] cpia driver update

Here are some minor fixes and cleanups to the cpia (Creative WebCam II et
al) driver.  These have been extracted from the sourceforge CVS archive,
and I'd like to get these in before a larger change to the parallel port
code to support more transfer modes.

This patch contains:
  * cpia: use the <linux/list.h> list implementation, instead of cpia specific
    version.
  * cpia_pp: don't clear camera list after cameras have been registered (as
    this prevents them being deregistered, and oops after module
    unload).
  * hold cpia_pp list spinlock while walking list, not just during the
    element removal.
parent 98468cf8
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/list.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
struct cpia_camera_ops struct cpia_camera_ops
...@@ -239,8 +240,7 @@ enum v4l_camstates { ...@@ -239,8 +240,7 @@ enum v4l_camstates {
#define FRAME_NUM 2 /* double buffering for now */ #define FRAME_NUM 2 /* double buffering for now */
struct cam_data { struct cam_data {
struct cam_data **previous; struct list_head cam_data_list;
struct cam_data *next;
struct semaphore busy_lock; /* guard against SMP multithreading */ struct semaphore busy_lock; /* guard against SMP multithreading */
struct cpia_camera_ops *ops; /* lowlevel driver operations */ struct cpia_camera_ops *ops; /* lowlevel driver operations */
...@@ -421,28 +421,6 @@ void cpia_unregister_camera(struct cam_data *cam); ...@@ -421,28 +421,6 @@ void cpia_unregister_camera(struct cam_data *cam);
(p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
(p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
static inline void cpia_add_to_list(struct cam_data** l, struct cam_data** drv_p)
{
struct cam_data* drv;
drv = *drv_p;
drv->next = *l;
drv->previous = l;
*l = drv;
}
static inline void cpia_remove_from_list(struct cam_data** drv_p)
{
struct cam_data* drv;
drv = *drv_p;
if (drv->previous != NULL) {
if (drv->next != NULL)
drv->next->previous = drv->previous;
*(drv->previous) = drv->next;
drv->previous = NULL;
drv->next = NULL;
}
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* cpia_h */ #endif /* cpia_h */
...@@ -161,8 +161,8 @@ static struct cpia_camera_ops cpia_pp_ops = ...@@ -161,8 +161,8 @@ static struct cpia_camera_ops cpia_pp_ops =
THIS_MODULE THIS_MODULE
}; };
static struct cam_data *cam_list; static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_pp; static spinlock_t cam_list_lock_pp = SPIN_LOCK_UNLOCKED;
#ifdef _CPIA_DEBUG_ #ifdef _CPIA_DEBUG_
#define DEB_PORT(port) { \ #define DEB_PORT(port) { \
...@@ -566,7 +566,7 @@ static int cpia_pp_register(struct parport *port) ...@@ -566,7 +566,7 @@ static int cpia_pp_register(struct parport *port)
return -ENXIO; return -ENXIO;
} }
spin_lock( &cam_list_lock_pp ); spin_lock( &cam_list_lock_pp );
cpia_add_to_list(&cam_list, &cpia); list_add( &cpia->cam_data_list, &cam_list );
spin_unlock( &cam_list_lock_pp ); spin_unlock( &cam_list_lock_pp );
return 0; return 0;
...@@ -574,14 +574,16 @@ static int cpia_pp_register(struct parport *port) ...@@ -574,14 +574,16 @@ static int cpia_pp_register(struct parport *port)
static void cpia_pp_detach (struct parport *port) static void cpia_pp_detach (struct parport *port)
{ {
struct list_head *tmp;
struct cam_data *cpia; struct cam_data *cpia;
struct pp_cam_entry *cam;
for(cpia = cam_list; cpia != NULL; cpia = cpia->next) {
struct pp_cam_entry *cam = cpia->lowlevel_data;
if (cam && cam->port->number == port->number) {
spin_lock( &cam_list_lock_pp ); spin_lock( &cam_list_lock_pp );
cpia_remove_from_list(&cpia); list_for_each (tmp, &cam_list) {
spin_unlock( &cam_list_lock_pp ); cpia = list_entry(tmp, struct cam_data, cam_data_list);
cam = cpia->lowlevel_data;
if (cam && cam->port->number == port->number) {
list_del(&cpia->cam_data_list);
cpia_unregister_camera(cpia); cpia_unregister_camera(cpia);
if(cam->open_count > 0) { if(cam->open_count > 0) {
...@@ -595,6 +597,7 @@ static void cpia_pp_detach (struct parport *port) ...@@ -595,6 +597,7 @@ static void cpia_pp_detach (struct parport *port)
break; break;
} }
} }
spin_unlock( &cam_list_lock_pp );
} }
static void cpia_pp_attach (struct parport *port) static void cpia_pp_attach (struct parport *port)
...@@ -647,9 +650,6 @@ int cpia_pp_init(void) ...@@ -647,9 +650,6 @@ int cpia_pp_init(void)
return -EIO; return -EIO;
} }
cam_list = NULL;
spin_lock_init( &cam_list_lock_pp );
return 0; return 0;
} }
......
...@@ -104,8 +104,8 @@ static struct cpia_camera_ops cpia_usb_ops = { ...@@ -104,8 +104,8 @@ static struct cpia_camera_ops cpia_usb_ops = {
THIS_MODULE THIS_MODULE
}; };
static struct cam_data *cam_list; static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_usb; static spinlock_t cam_list_lock_usb = SPIN_LOCK_UNLOCKED;
static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
{ {
...@@ -549,7 +549,7 @@ static int cpia_probe(struct usb_interface *intf, ...@@ -549,7 +549,7 @@ static int cpia_probe(struct usb_interface *intf,
} }
spin_lock( &cam_list_lock_usb ); spin_lock( &cam_list_lock_usb );
cpia_add_to_list(&cam_list, &cam); list_add( &cam->cam_data_list, &cam_list );
spin_unlock( &cam_list_lock_usb ); spin_unlock( &cam_list_lock_usb );
usb_set_intfdata(intf, cam); usb_set_intfdata(intf, cam);
...@@ -603,7 +603,7 @@ static void cpia_disconnect(struct usb_interface *intf) ...@@ -603,7 +603,7 @@ static void cpia_disconnect(struct usb_interface *intf)
ucpia = (struct usb_cpia *) cam->lowlevel_data; ucpia = (struct usb_cpia *) cam->lowlevel_data;
spin_lock( &cam_list_lock_usb ); spin_lock( &cam_list_lock_usb );
cpia_remove_from_list(&cam); list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb ); spin_unlock( &cam_list_lock_usb );
/* Don't even try to reset the altsetting if we're disconnected */ /* Don't even try to reset the altsetting if we're disconnected */
...@@ -647,8 +647,6 @@ static void cpia_disconnect(struct usb_interface *intf) ...@@ -647,8 +647,6 @@ static void cpia_disconnect(struct usb_interface *intf)
static int __init usb_cpia_init(void) static int __init usb_cpia_init(void)
{ {
cam_list = NULL;
spin_lock_init(&cam_list_lock_usb);
return usb_register(&cpia_driver); return usb_register(&cpia_driver);
} }
...@@ -667,4 +665,3 @@ static void __exit usb_cpia_cleanup(void) ...@@ -667,4 +665,3 @@ static void __exit usb_cpia_cleanup(void)
module_init (usb_cpia_init); module_init (usb_cpia_init);
module_exit (usb_cpia_cleanup); module_exit (usb_cpia_cleanup);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment