|
@@ -272,56 +272,51 @@ out:
|
|
|
|
|
|
static int coda_psdev_open(struct inode * inode, struct file * file)
|
|
|
{
|
|
|
- struct venus_comm *vcp;
|
|
|
- int idx;
|
|
|
+ struct venus_comm *vcp;
|
|
|
+ int idx, err;
|
|
|
|
|
|
- lock_kernel();
|
|
|
idx = iminor(inode);
|
|
|
- if(idx >= MAX_CODADEVS) {
|
|
|
- unlock_kernel();
|
|
|
+ if (idx < 0 || idx >= MAX_CODADEVS)
|
|
|
return -ENODEV;
|
|
|
- }
|
|
|
|
|
|
+ lock_kernel();
|
|
|
+
|
|
|
+ err = -EBUSY;
|
|
|
vcp = &coda_comms[idx];
|
|
|
- if(vcp->vc_inuse) {
|
|
|
- unlock_kernel();
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-
|
|
|
- if (!vcp->vc_inuse++) {
|
|
|
+ if (!vcp->vc_inuse) {
|
|
|
+ vcp->vc_inuse++;
|
|
|
+
|
|
|
INIT_LIST_HEAD(&vcp->vc_pending);
|
|
|
INIT_LIST_HEAD(&vcp->vc_processing);
|
|
|
init_waitqueue_head(&vcp->vc_waitq);
|
|
|
vcp->vc_sb = NULL;
|
|
|
vcp->vc_seq = 0;
|
|
|
+
|
|
|
+ file->private_data = vcp;
|
|
|
+ err = 0;
|
|
|
}
|
|
|
-
|
|
|
- file->private_data = vcp;
|
|
|
|
|
|
unlock_kernel();
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
|
|
|
static int coda_psdev_release(struct inode * inode, struct file * file)
|
|
|
{
|
|
|
- struct venus_comm *vcp = (struct venus_comm *) file->private_data;
|
|
|
- struct upc_req *req, *tmp;
|
|
|
+ struct venus_comm *vcp = (struct venus_comm *) file->private_data;
|
|
|
+ struct upc_req *req, *tmp;
|
|
|
|
|
|
- lock_kernel();
|
|
|
- if ( !vcp->vc_inuse ) {
|
|
|
- unlock_kernel();
|
|
|
+ if (!vcp || !vcp->vc_inuse ) {
|
|
|
printk("psdev_release: Not open.\n");
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (--vcp->vc_inuse) {
|
|
|
- unlock_kernel();
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* Wakeup clients so they can return. */
|
|
|
+ lock_kernel();
|
|
|
+
|
|
|
+ /* Wakeup clients so they can return. */
|
|
|
list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
|
|
|
+ list_del(&req->uc_chain);
|
|
|
+
|
|
|
/* Async requests need to be freed here */
|
|
|
if (req->uc_flags & REQ_ASYNC) {
|
|
|
CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
|
|
@@ -330,13 +325,17 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
|
|
|
}
|
|
|
req->uc_flags |= REQ_ABORT;
|
|
|
wake_up(&req->uc_sleep);
|
|
|
- }
|
|
|
-
|
|
|
- list_for_each_entry(req, &vcp->vc_processing, uc_chain) {
|
|
|
+ }
|
|
|
+
|
|
|
+ list_for_each_entry_safe(req, tmp, &vcp->vc_processing, uc_chain) {
|
|
|
+ list_del(&req->uc_chain);
|
|
|
+
|
|
|
req->uc_flags |= REQ_ABORT;
|
|
|
- wake_up(&req->uc_sleep);
|
|
|
- }
|
|
|
+ wake_up(&req->uc_sleep);
|
|
|
+ }
|
|
|
|
|
|
+ file->private_data = NULL;
|
|
|
+ vcp->vc_inuse--;
|
|
|
unlock_kernel();
|
|
|
return 0;
|
|
|
}
|