psdev.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  2.  * vim:expandtab:shiftwidth=8:tabstop=8:
  3.  *
  4.  *              An implementation of a loadable kernel mode driver providing
  5.  *              multiple kernel/user space bidirectional communications links.
  6.  *
  7.  *              Author:         Alan Cox <alan@cymru.net>
  8.  *
  9.  *              This program is free software; you can redistribute it and/or
  10.  *              modify it under the terms of the GNU General Public License
  11.  *              version 2 as published by the Free Software Foundation.
  12.  *
  13.  *              Adapted to become the Linux 2.0 Coda pseudo device
  14.  *              Peter  Braam  <braam@maths.ox.ac.uk>
  15.  *              Michael Callahan <mjc@emmy.smith.edu>
  16.  *
  17.  *              Changes for Linux 2.1
  18.  *              Copyright (c) 1997 Carnegie-Mellon University
  19.  *
  20.  *              Redone again for InterMezzo
  21.  *              Copyright (c) 1998 Peter J. Braam
  22.  *              Copyright (c) 2000 Mountain View Data, Inc.
  23.  *              Copyright (c) 2000 Tacitus Systems, Inc.
  24.  *              Copyright (c) 2001 Cluster File Systems, Inc.
  25.  *
  26.  */
  27. #include <linux/module.h>
  28. #include <linux/errno.h>
  29. #include <linux/kernel.h>
  30. #include <linux/major.h>
  31. #include <linux/sched.h>
  32. #include <linux/lp.h>
  33. #include <linux/slab.h>
  34. #include <linux/ioport.h>
  35. #include <linux/fcntl.h>
  36. #include <linux/delay.h>
  37. #include <linux/skbuff.h>
  38. #include <linux/proc_fs.h>
  39. #include <linux/vmalloc.h>
  40. #include <linux/fs.h>
  41. #include <linux/file.h>
  42. #include <linux/poll.h>
  43. #include <linux/init.h>
  44. #include <linux/list.h>
  45. #include <linux/devfs_fs_kernel.h>
  46. #include <asm/io.h>
  47. #include <asm/segment.h>
  48. #include <asm/system.h>
  49. #include <asm/poll.h>
  50. #include <asm/uaccess.h>
  51. #include <linux/miscdevice.h>
  52. #include <linux/intermezzo_fs.h>
  53. #include <linux/intermezzo_psdev.h>
  54. #ifdef PRESTO_DEVEL
  55. int  presto_print_entry = 1;
  56. int  presto_debug = 4095;
  57. #else
  58. int  presto_print_entry = 0;
  59. int  presto_debug = 0;
  60. #endif
  61. /* Like inode.c (presto_sym_iops), the initializer is just to prevent
  62.    izo_channels from appearing as a COMMON symbol (and therefore
  63.    interfering with other modules that use the same variable name). */
  64. struct upc_channel izo_channels[MAX_CHANNEL] = {{0}};
  65. int izo_psdev_get_free_channel(void)
  66. {
  67.         int i, result = -1;
  68.         
  69.         for (i = 0 ; i < MAX_CHANNEL ; i++ ) {
  70.                 if (list_empty(&(izo_channels[i].uc_cache_list))) { 
  71.                     result = i;
  72.                     break;
  73.                 }
  74.         }
  75.         return result;
  76. }
  77. int izo_psdev_setpid(int minor)
  78. {
  79.         struct upc_channel *channel; 
  80.         if (minor < 0 || minor >= MAX_CHANNEL) { 
  81.                 return -EINVAL;
  82.         }
  83.         channel = &(izo_channels[minor]); 
  84.         /*
  85.          * This ioctl is performed by each Lento that starts up
  86.          * and wants to do further communication with presto.
  87.          */
  88.         CDEBUG(D_PSDEV, "Setting current pid to %d channel %dn", 
  89.                current->pid, minor);
  90.         channel->uc_pid = current->pid;
  91.         spin_lock(&channel->uc_lock); 
  92.         if ( !list_empty(&channel->uc_processing) ) {
  93.                 struct list_head *lh;
  94.                 struct upc_req *req;
  95.                 CERROR("WARNING: setpid & processing not empty!n");
  96.                 lh = &channel->uc_processing;
  97.                 while ( (lh = lh->next) != &channel->uc_processing) {
  98.                         req = list_entry(lh, struct upc_req, rq_chain);
  99.                         /* freeing of req and data is done by the sleeper */
  100.                         wake_up(&req->rq_sleep);
  101.                 }
  102.         }
  103.         if ( !list_empty(&channel->uc_processing) ) {
  104.                 CERROR("BAD: FAILDED TO CLEAN PROCESSING LIST!n");
  105.         }
  106.         spin_unlock(&channel->uc_lock); 
  107.         EXIT;
  108.         return 0;
  109. }
  110. int izo_psdev_setchannel(struct file *file, int fd)
  111. {
  112.         struct file *psdev_file = fget(fd); 
  113.         struct presto_cache *cache = presto_get_cache(file->f_dentry->d_inode);
  114.         if (!psdev_file) { 
  115.                 CERROR("%s: no psdev_file!n", __FUNCTION__);
  116.                 return -EINVAL;
  117.         }
  118.         if (!cache) { 
  119.                 CERROR("%s: no cache!n", __FUNCTION__);
  120.                 fput(psdev_file); 
  121.                 return -EINVAL;
  122.         } 
  123.         if (psdev_file->private_data) { 
  124.                 CERROR("%s: channel already set!n", __FUNCTION__);
  125.                 fput(psdev_file); 
  126.                 return -EINVAL;
  127.         }
  128.         psdev_file->private_data = cache->cache_psdev;
  129.         fput(psdev_file); 
  130.         EXIT; 
  131.         return 0; 
  132. }
  133. inline int presto_lento_up(int minor) 
  134. {
  135.         return izo_channels[minor].uc_pid;
  136. }
  137. static unsigned int presto_psdev_poll(struct file *file, poll_table * wait)
  138.  {
  139.         struct upc_channel *channel = (struct upc_channel *)file->private_data;
  140.         unsigned int mask = POLLOUT | POLLWRNORM;
  141.         /* ENTRY; this will flood you */
  142.         if ( ! channel ) { 
  143.                 CERROR("%s: bad psdev filen", __FUNCTION__);
  144.                 return -EBADF;
  145.         }
  146.         poll_wait(file, &(channel->uc_waitq), wait);
  147.         spin_lock(&channel->uc_lock);
  148.         if (!list_empty(&channel->uc_pending)) {
  149.                 CDEBUG(D_PSDEV, "Non-empty pending list.n");
  150.                 mask |= POLLIN | POLLRDNORM;
  151.         }
  152.         spin_unlock(&channel->uc_lock);
  153.         /* EXIT; will flood you */
  154.         return mask;
  155. }
  156. /*
  157.  *      Receive a message written by Lento to the psdev
  158.  */
  159. static ssize_t presto_psdev_write(struct file *file, const char *buf,
  160.                                   size_t count, loff_t *off)
  161. {
  162.         struct upc_channel *channel = (struct upc_channel *)file->private_data;
  163.         struct upc_req *req = NULL;
  164.         struct upc_req *tmp;
  165.         struct list_head *lh;
  166.         struct izo_upcall_resp hdr;
  167.         int error;
  168.         if ( ! channel ) { 
  169.                 CERROR("%s: bad psdev filen", __FUNCTION__);
  170.                 return -EBADF;
  171.         }
  172.         /* Peek at the opcode, uniquefier */
  173.         if ( count < sizeof(hdr) ) {
  174.               CERROR("presto_psdev_write: Lento didn't write full hdr.n");
  175.                 return -EINVAL;
  176.         }
  177.         error = copy_from_user(&hdr, buf, sizeof(hdr));
  178.         if ( error )
  179.                 return -EFAULT;
  180.         CDEBUG(D_PSDEV, "(process,opc,uniq)=(%d,%d,%d)n",
  181.                current->pid, hdr.opcode, hdr.unique);
  182.         spin_lock(&channel->uc_lock); 
  183.         /* Look for the message on the processing queue. */
  184.         lh  = &channel->uc_processing;
  185.         while ( (lh = lh->next) != &channel->uc_processing ) {
  186.                 tmp = list_entry(lh, struct upc_req , rq_chain);
  187.                 if (tmp->rq_unique == hdr.unique) {
  188.                         req = tmp;
  189.                         /* unlink here: keeps search length minimal */
  190.                         list_del_init(&req->rq_chain);
  191.                         CDEBUG(D_PSDEV,"Eureka opc %d uniq %d!n",
  192.                                hdr.opcode, hdr.unique);
  193.                         break;
  194.                 }
  195.         }
  196.         spin_unlock(&channel->uc_lock); 
  197.         if (!req) {
  198.                 CERROR("psdev_write: msg (%d, %d) not foundn",
  199.                        hdr.opcode, hdr.unique);
  200.                 return(-ESRCH);
  201.         }
  202.         /* move data into response buffer. */
  203.         if (req->rq_bufsize < count) {
  204.                 CERROR("psdev_write: too much cnt: %d, cnt: %d, "
  205.                        "opc: %d, uniq: %d.n",
  206.                        req->rq_bufsize, count, hdr.opcode, hdr.unique);
  207.                 count = req->rq_bufsize; /* don't have more space! */
  208.         }
  209.         error = copy_from_user(req->rq_data, buf, count);
  210.         if ( error )
  211.                 return -EFAULT;
  212.         /* adjust outsize: good upcalls can be aware of this */
  213.         req->rq_rep_size = count;
  214.         req->rq_flags |= REQ_WRITE;
  215.         wake_up(&req->rq_sleep);
  216.         return(count);
  217. }
  218. /*
  219.  *      Read a message from the kernel to Lento
  220.  */
  221. static ssize_t presto_psdev_read(struct file * file, char * buf,
  222.                                  size_t count, loff_t *off)
  223. {
  224.         struct upc_channel *channel = (struct upc_channel *)file->private_data;
  225.         struct upc_req *req;
  226.         int result = count;
  227.         if ( ! channel ) { 
  228.                 CERROR("%s: bad psdev filen", __FUNCTION__);
  229.                 return -EBADF;
  230.         }
  231.         spin_lock(&channel->uc_lock); 
  232.         if (list_empty(&(channel->uc_pending))) {
  233.                 CDEBUG(D_UPCALL, "Empty pending list in read, not goodn");
  234.                 spin_unlock(&channel->uc_lock); 
  235.                 return -EINVAL;
  236.         }
  237.         req = list_entry((channel->uc_pending.next), struct upc_req, rq_chain);
  238.         list_del(&(req->rq_chain));
  239.         if (! (req->rq_flags & REQ_ASYNC) ) {
  240.                 list_add(&(req->rq_chain), channel->uc_processing.prev);
  241.         }
  242.         spin_unlock(&channel->uc_lock); 
  243.         req->rq_flags |= REQ_READ;
  244.         /* Move the input args into userspace */
  245.         CDEBUG(D_PSDEV, "n");
  246.         if (req->rq_bufsize <= count) {
  247.                 result = req->rq_bufsize;
  248.         }
  249.         if (count < req->rq_bufsize) {
  250.                 CERROR ("psdev_read: buffer too small, read %d of %d bytesn",
  251.                         count, req->rq_bufsize);
  252.         }
  253.         if ( copy_to_user(buf, req->rq_data, result) ) {
  254.                 BUG();
  255.                 return -EFAULT;
  256.         }
  257.         /* If request was asynchronous don't enqueue, but free */
  258.         if (req->rq_flags & REQ_ASYNC) {
  259.                 CDEBUG(D_PSDEV, "psdev_read: async msg (%d, %d), result %dn",
  260.                        req->rq_opcode, req->rq_unique, result);
  261.                 PRESTO_FREE(req->rq_data, req->rq_bufsize);
  262.                 PRESTO_FREE(req, sizeof(*req));
  263.                 return result;
  264.         }
  265.         return result;
  266. }
  267. static int presto_psdev_open(struct inode * inode, struct file * file)
  268. {
  269.         ENTRY;
  270.         file->private_data = NULL;  
  271.         MOD_INC_USE_COUNT;
  272.         CDEBUG(D_PSDEV, "Psdev_open: caller: %d, flags: %dn", current->pid, file->f_flags);
  273.         EXIT;
  274.         return 0;
  275. }
  276. static int presto_psdev_release(struct inode * inode, struct file * file)
  277. {
  278.         struct upc_channel *channel = (struct upc_channel *)file->private_data;
  279.         struct upc_req *req;
  280.         struct list_head *lh;
  281.         ENTRY;
  282.         if ( ! channel ) { 
  283.                 CERROR("%s: bad psdev filen", __FUNCTION__);
  284.                 return -EBADF;
  285.         }
  286.         MOD_DEC_USE_COUNT;
  287.         CDEBUG(D_PSDEV, "Lento: pid %dn", current->pid);
  288.         channel->uc_pid = 0;
  289.         /* Wake up clients so they can return. */
  290.         CDEBUG(D_PSDEV, "Wake up clients sleeping for pending.n");
  291.         spin_lock(&channel->uc_lock); 
  292.         lh = &channel->uc_pending;
  293.         while ( (lh = lh->next) != &channel->uc_pending) {
  294.                 req = list_entry(lh, struct upc_req, rq_chain);
  295.                 /* Async requests stay around for a new lento */
  296.                 if (req->rq_flags & REQ_ASYNC) {
  297.                         continue;
  298.                 }
  299.                 /* the sleeper will free the req and data */
  300.                 req->rq_flags |= REQ_DEAD; 
  301.                 wake_up(&req->rq_sleep);
  302.         }
  303.         CDEBUG(D_PSDEV, "Wake up clients sleeping for processingn");
  304.         lh = &channel->uc_processing;
  305.         while ( (lh = lh->next) != &channel->uc_processing) {
  306.                 req = list_entry(lh, struct upc_req, rq_chain);
  307.                 /* freeing of req and data is done by the sleeper */
  308.                 req->rq_flags |= REQ_DEAD; 
  309.                 wake_up(&req->rq_sleep);
  310.         }
  311.         spin_unlock(&channel->uc_lock); 
  312.         CDEBUG(D_PSDEV, "Done.n");
  313.         EXIT;
  314.         return 0;
  315. }
  316. static struct file_operations presto_psdev_fops = {
  317.         .read    = presto_psdev_read,
  318.         .write   = presto_psdev_write,
  319.         .poll    = presto_psdev_poll,
  320.         .open    = presto_psdev_open,
  321.         .release = presto_psdev_release
  322. };
  323. /* modules setup */
  324. static struct miscdevice intermezzo_psdev = {
  325.         INTERMEZZO_MINOR,
  326.         "intermezzo",
  327.         &presto_psdev_fops
  328. };
  329. int  presto_psdev_init(void)
  330. {
  331.         int i;
  332.         int err; 
  333.         if ( (err = misc_register(&intermezzo_psdev)) ) { 
  334.                 CERROR("%s: cannot register %d err %dn", 
  335.                        __FUNCTION__, INTERMEZZO_MINOR, err);
  336.                 return -EIO;
  337.         }
  338.         memset(&izo_channels, 0, sizeof(izo_channels));
  339.         for ( i = 0 ; i < MAX_CHANNEL ; i++ ) {
  340.                 struct upc_channel *channel = &(izo_channels[i]);
  341.                 INIT_LIST_HEAD(&channel->uc_pending);
  342.                 INIT_LIST_HEAD(&channel->uc_processing);
  343.                 INIT_LIST_HEAD(&channel->uc_cache_list);
  344.                 init_waitqueue_head(&channel->uc_waitq);
  345.                 channel->uc_lock = SPIN_LOCK_UNLOCKED;
  346.                 channel->uc_hard = 0;
  347.                 channel->uc_no_filter = 0;
  348.                 channel->uc_no_journal = 0;
  349.                 channel->uc_no_upcall = 0;
  350.                 channel->uc_timeout = 30;
  351.                 channel->uc_errorval = 0;
  352.                 channel->uc_minor = i;
  353.         }
  354.         return 0;
  355. }
  356. void presto_psdev_cleanup(void)
  357. {
  358.         int i;
  359.         misc_deregister(&intermezzo_psdev);
  360.         for ( i = 0 ; i < MAX_CHANNEL ; i++ ) {
  361.                 struct upc_channel *channel = &(izo_channels[i]);
  362.                 struct list_head *lh;
  363.                 spin_lock(&channel->uc_lock); 
  364.                 if ( ! list_empty(&channel->uc_pending)) { 
  365.                         CERROR("Weird, tell Peter: module cleanup and pending list not empty dev %dn", i);
  366.                 }
  367.                 if ( ! list_empty(&channel->uc_processing)) { 
  368.                         CERROR("Weird, tell Peter: module cleanup and processing list not empty dev %dn", i);
  369.                 }
  370.                 if ( ! list_empty(&channel->uc_cache_list)) { 
  371.                         CERROR("Weird, tell Peter: module cleanup and cache listnot empty dev %dn", i);
  372.                 }
  373.                 lh = channel->uc_pending.next;
  374.                 while ( lh != &channel->uc_pending) {
  375.                         struct upc_req *req;
  376.                         req = list_entry(lh, struct upc_req, rq_chain);
  377.                         lh = lh->next;
  378.                         if ( req->rq_flags & REQ_ASYNC ) {
  379.                                 list_del(&(req->rq_chain));
  380.                                 CDEBUG(D_UPCALL, "free pending upcall type %dn",
  381.                                        req->rq_opcode);
  382.                                 PRESTO_FREE(req->rq_data, req->rq_bufsize);
  383.                                 PRESTO_FREE(req, sizeof(struct upc_req));
  384.                         } else {
  385.                                 req->rq_flags |= REQ_DEAD; 
  386.                                 wake_up(&req->rq_sleep);
  387.                         }
  388.                 }
  389.                 lh = &channel->uc_processing;
  390.                 while ( (lh = lh->next) != &channel->uc_processing ) {
  391.                         struct upc_req *req;
  392.                         req = list_entry(lh, struct upc_req, rq_chain);
  393.                         list_del(&(req->rq_chain));
  394.                         req->rq_flags |= REQ_DEAD; 
  395.                         wake_up(&req->rq_sleep);
  396.                 }
  397.                 spin_unlock(&channel->uc_lock); 
  398.         }
  399. }
  400. /*
  401.  * lento_upcall and lento_downcall routines
  402.  */
  403. static inline unsigned long lento_waitfor_upcall
  404.             (struct upc_channel *channel, struct upc_req *req, int minor)
  405. {
  406.         DECLARE_WAITQUEUE(wait, current);
  407.         unsigned long posttime;
  408.         req->rq_posttime = posttime = jiffies;
  409.         add_wait_queue(&req->rq_sleep, &wait);
  410.         for (;;) {
  411.                 if ( izo_channels[minor].uc_hard == 0 )
  412.                         set_current_state(TASK_INTERRUPTIBLE);
  413.                 else
  414.                         set_current_state(TASK_UNINTERRUPTIBLE);
  415.                 /* got a reply */
  416.                 if ( req->rq_flags & (REQ_WRITE | REQ_DEAD) )
  417.                         break;
  418.                 /* these cases only apply when TASK_INTERRUPTIBLE */ 
  419.                 if ( !izo_channels[minor].uc_hard && signal_pending(current) ) {
  420.                         /* if this process really wants to die, let it go */
  421.                         if (sigismember(&(current->pending.signal), SIGKILL)||
  422.                             sigismember(&(current->pending.signal), SIGINT) )
  423.                                 break;
  424.                         /* signal is present: after timeout always return
  425.                            really smart idea, probably useless ... */
  426.                         if ( time_after(jiffies, req->rq_posttime +
  427.                              izo_channels[minor].uc_timeout * HZ) )
  428.                                 break;
  429.                 }
  430.                 schedule();
  431.         }
  432.         spin_lock(&channel->uc_lock);
  433.         list_del_init(&req->rq_chain); 
  434.         spin_unlock(&channel->uc_lock);
  435.         remove_wait_queue(&req->rq_sleep, &wait);
  436.         set_current_state(TASK_RUNNING);
  437.         CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ldn",
  438.                posttime, jiffies-posttime);
  439.         return  (jiffies - posttime);
  440. }
  441. /*
  442.  * lento_upcall will return an error in the case of
  443.  * failed communication with Lento _or_ will peek at Lento
  444.  * reply and return Lento's error.
  445.  *
  446.  * As lento has 2 types of errors, normal errors (positive) and internal
  447.  * errors (negative), normal errors are negated, while internal errors
  448.  * are all mapped to -EINTR, while showing a nice warning message. (jh)
  449.  *
  450.  * lento_upcall will always free buffer, either directly, when an upcall
  451.  * is read (in presto_psdev_read), when the filesystem is unmounted, or
  452.  * when the module is unloaded.
  453.  */
  454. int izo_upc_upcall(int minor, int *size, struct izo_upcall_hdr *buffer, 
  455.                    int async)
  456. {
  457.         unsigned long runtime;
  458.         struct upc_channel *channel;
  459.         struct izo_upcall_resp *out;
  460.         struct upc_req *req;
  461.         int error = 0;
  462.         ENTRY;
  463.         channel = &(izo_channels[minor]);
  464.         if (channel->uc_no_upcall) {
  465.                 EXIT;
  466.                 goto exit_buf;
  467.         }
  468.         if (!channel->uc_pid && !async) {
  469.                 EXIT;
  470.                 error = -ENXIO;
  471.                 goto exit_buf;
  472.         }
  473.         /* Format the request message. */
  474.         PRESTO_ALLOC(req, sizeof(struct upc_req));
  475.         if ( !req ) {
  476.                 EXIT;
  477.                 error = -ENOMEM;
  478.                 goto exit_buf;
  479.         }
  480.         req->rq_data = (void *)buffer;
  481.         req->rq_flags = 0;
  482.         req->rq_bufsize = *size;
  483.         req->rq_rep_size = 0;
  484.         req->rq_opcode = buffer->u_opc;
  485.         req->rq_unique = ++channel->uc_seq;
  486.         init_waitqueue_head(&req->rq_sleep);
  487.         /* Fill in the common input args. */
  488.         buffer->u_uniq = req->rq_unique;
  489.         buffer->u_async = async;
  490.         spin_lock(&channel->uc_lock); 
  491.         /* Append msg to pending queue and poke Lento. */
  492.         list_add(&req->rq_chain, channel->uc_pending.prev);
  493.         spin_unlock(&channel->uc_lock); 
  494.         CDEBUG(D_UPCALL,
  495.                "Proc %d waking Lento %d for(opc,uniq) =(%d,%d) msg at %p.n",
  496.                current->pid, channel->uc_pid, req->rq_opcode,
  497.                req->rq_unique, req);
  498.         wake_up_interruptible(&channel->uc_waitq);
  499.         if ( async ) {
  500.                 /* req, rq_data are freed in presto_psdev_read for async */
  501.                 req->rq_flags = REQ_ASYNC;
  502.                 EXIT;
  503.                 return 0;
  504.         }
  505.         /* We can be interrupted while we wait for Lento to process
  506.          * our request.  If the interrupt occurs before Lento has read
  507.          * the request, we dequeue and return. If it occurs after the
  508.          * read but before the reply, we dequeue, send a signal
  509.          * message, and return. If it occurs after the reply we ignore
  510.          * it. In no case do we want to restart the syscall.  If it
  511.          * was interrupted by a lento shutdown (psdev_close), return
  512.          * ENODEV.  */
  513.         /* Go to sleep.  Wake up on signals only after the timeout. */
  514.         runtime = lento_waitfor_upcall(channel, req, minor);
  515.         CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %dn",
  516.                req->rq_opcode, jiffies - req->rq_posttime,
  517.                req->rq_unique, req->rq_rep_size);
  518.         CDEBUG(D_UPCALL,
  519.                "..process %d woken up by Lento for req at 0x%x, data at %xn",
  520.                current->pid, (int)req, (int)req->rq_data);
  521.         if (channel->uc_pid) {      /* i.e. Lento is still alive */
  522.           /* Op went through, interrupt or not we go on */
  523.             if (req->rq_flags & REQ_WRITE) {
  524.                     out = (struct izo_upcall_resp *)req->rq_data;
  525.                     /* here we map positive Lento errors to kernel errors */
  526.                     if ( out->result < 0 ) {
  527.                             CERROR("Tell Peter: Lento returns negative error %d, for oc %d!n",
  528.                                    out->result, out->opcode);
  529.                           out->result = EINVAL;
  530.                     }
  531.                     error = -out->result;
  532.                     CDEBUG(D_UPCALL, "upcall: (u,o,r) (%d, %d, %d) out at %pn",
  533.                            out->unique, out->opcode, out->result, out);
  534.                     *size = req->rq_rep_size;
  535.                     EXIT;
  536.                     goto exit_req;
  537.             }
  538.             /* Interrupted before lento read it. */
  539.             if ( !(req->rq_flags & REQ_READ) && signal_pending(current)) {
  540.                     CDEBUG(D_UPCALL,
  541.                            "Interrupt before read: (op,un)=(%d,%d), flags %xn",
  542.                            req->rq_opcode, req->rq_unique, req->rq_flags);
  543.                     /* perhaps the best way to convince the app to give up? */
  544.                     error = -EINTR;
  545.                     EXIT;
  546.                     goto exit_req;
  547.             }
  548.             /* interrupted after Lento did its read, send signal */
  549.             if ( (req->rq_flags & REQ_READ) && signal_pending(current) ) {
  550.                     CDEBUG(D_UPCALL,"Interrupt after read: op = %d.%d, flags = %xn",
  551.                            req->rq_opcode, req->rq_unique, req->rq_flags);
  552.                     error = -EINTR;
  553.             } else {
  554.                   CERROR("Lento: Strange interruption - tell Peter.n");
  555.                     error = -EINTR;
  556.             }
  557.         } else {        /* If lento died i.e. !UC_OPEN(channel) */
  558.                 CERROR("lento_upcall: Lento dead on (op,un) (%d.%d) flags %dn",
  559.                        req->rq_opcode, req->rq_unique, req->rq_flags);
  560.                 error = -ENODEV;
  561.         }
  562. exit_req:
  563.         PRESTO_FREE(req, sizeof(struct upc_req));
  564. exit_buf:
  565.         return error;
  566. }