/****************************************************************************** * * usb_cpia_cleanup * *****************************************************************************/ void cpia2_usb_cleanup(void) { schedule_timeout(2 * HZ); usb_deregister(&cpia2_driver); }
/* * receive a message from an RxRPC socket * - we need to be careful about two or more threads calling recvmsg * simultaneously */ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) { struct rxrpc_skb_priv *sp; struct rxrpc_call *call = NULL, *continue_call = NULL; struct rxrpc_sock *rx = rxrpc_sk(sock->sk); struct sk_buff *skb; long timeo; int copy, ret, ullen, offset, copied = 0; u32 abort_code; DEFINE_WAIT(wait); _enter(",,,%zu,%d", len, flags); if (flags & (MSG_OOB | MSG_TRUNC)) return -EOPNOTSUPP; ullen = msg->msg_flags & MSG_CMSG_COMPAT ? 4 : sizeof(unsigned long); timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT); msg->msg_flags |= MSG_MORE; lock_sock(&rx->sk); for (;;) { /* return immediately if a client socket has no outstanding * calls */ if (RB_EMPTY_ROOT(&rx->calls)) { if (copied) goto out; if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) { release_sock(&rx->sk); if (continue_call) rxrpc_put_call(continue_call); return -ENODATA; } } /* get the next message on the Rx queue */ skb = skb_peek(&rx->sk.sk_receive_queue); if (!skb) { /* nothing remains on the queue */ if (copied && (msg->msg_flags & MSG_PEEK || timeo == 0)) goto out; /* wait for a message to turn up */ release_sock(&rx->sk); prepare_to_wait_exclusive(rx->sk), &wait, TASK_INTERRUPTIBLE); ret = sock_error(&rx->sk); if (ret) goto wait_error; if (skb_queue_empty(&rx->sk.sk_receive_queue)) { if (signal_pending(current)) goto wait_interrupted; timeo = schedule_timeout(timeo); } finish_wait(sk_sleep(rx->sk), &wait); lock_sock(&rx->sk); continue; } peek_next_packet: sp = rxrpc_skb(skb); call = sp->call; ASSERT(call != NULL); _debug("next pkt %s", rxrpc_pkts[sp->hdr.type]); /* make sure we wait for the state to be updated in this call */ spin_lock_bh(&call->lock); spin_unlock_bh(&call->lock); if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { _debug("packet from released call"); if (skb_dequeue(&rx->sk.sk_receive_queue) != skb) BUG(); rxrpc_free_skb(skb); continue; } /* determine whether to continue last data receive */ if (continue_call) { _debug("maybe cont"); if (call != continue_call || skb->mark != RXRPC_SKB_MARK_DATA) { release_sock(&rx->sk); rxrpc_put_call(continue_call); _leave(" = %d [noncont]", copied); return copied; } } rxrpc_get_call(call); /* copy the peer address and timestamp */ if (!continue_call) { if (msg->msg_name && msg->msg_namelen > 0) memcpy(&msg->msg_name, &call->conn->trans->peer->srx, sizeof(call->conn->trans->peer->srx)); sock_recv_timestamp(msg, &rx->sk, skb); } /* receive the message */ if (skb->mark != RXRPC_SKB_MARK_DATA) goto receive_non_data_message; _debug("recvmsg DATA #%u { %d, %d }", ntohl(sp->hdr.seq), skb->len, sp->offset); if (!continue_call) { /* only set the control data once per recvmsg() */ ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID, ullen, &call->user_call_ID); if (ret < 0) goto copy_error; ASSERT(test_bit(RXRPC_CALL_HAS_USERID, &call->flags)); } ASSERTCMP(ntohl(sp->hdr.seq), >=, call->rx_data_recv); ASSERTCMP(ntohl(sp->hdr.seq), <=, call->rx_data_recv + 1); call->rx_data_recv = ntohl(sp->hdr.seq); ASSERTCMP(ntohl(sp->hdr.seq), >, call->rx_data_eaten); offset = sp->offset; copy = skb->len - offset; if (copy > len - copied) copy = len - copied; if (skb->ip_summed == CHECKSUM_UNNECESSARY) { ret = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copy); } else { ret = skb_copy_and_csum_datagram_iovec(skb, offset, msg->msg_iov); if (ret == -EINVAL) goto csum_copy_error; } if (ret < 0) goto copy_error; /* handle piecemeal consumption of data packets */ _debug("copied %d+%d", copy, copied); offset += copy; copied += copy; if (!(flags & MSG_PEEK)) sp->offset = offset; if (sp->offset < skb->len) { _debug("buffer full"); ASSERTCMP(copied, ==, len); break; } /* we transferred the whole data packet */ if (sp->hdr.flags & RXRPC_LAST_PACKET) { _debug("last"); if (call->conn->out_clientflag) { /* last byte of reply received */ ret = copied; goto terminal_message; } /* last bit of request received */ if (!(flags & MSG_PEEK)) { _debug("eat packet"); if (skb_dequeue(&rx->sk.sk_receive_queue) != skb) BUG(); rxrpc_free_skb(skb); } msg->msg_flags &= ~MSG_MORE; break; } /* move on to the next data message */ _debug("next"); if (!continue_call) continue_call = sp->call; else rxrpc_put_call(call); call = NULL; if (flags & MSG_PEEK) { _debug("peek next"); skb = skb->next; if (skb == (struct sk_buff *) &rx->sk.sk_receive_queue) break; goto peek_next_packet; } _debug("eat packet"); if (skb_dequeue(&rx->sk.sk_receive_queue) != skb) BUG(); rxrpc_free_skb(skb); }
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr) { unsigned char __user *b = buf; DECLARE_WAITQUEUE(wait, current); int c; int minimum, time; ssize_t retval = 0; ssize_t size; long timeout; unsigned long flags; int packet; struct tty_buffer *head; int count; do_it_again: if (WARN_ON(!tty->read_buf)) return -EAGAIN; c = job_control(tty, file); if (c < 0) return c; minimum = time = 0; timeout = MAX_SCHEDULE_TIMEOUT; if (!tty->icanon) { time = (HZ / 10) * TIME_CHAR(tty); minimum = MIN_CHAR(tty); if (minimum) { if (time) tty->minimum_to_wake = 1; else if (!waitqueue_active(&tty->read_wait) || (tty->minimum_to_wake > minimum)) tty->minimum_to_wake = minimum; } else { timeout = 0; if (time) { timeout = time; time = 0; } tty->minimum_to_wake = minimum = 1; } } if (file->f_flags & O_NONBLOCK) { if (!mutex_trylock(&tty->atomic_read_lock)) return -EAGAIN; } else { if (mutex_lock_interruptible(&tty->atomic_read_lock)) return -ERESTARTSYS; } packet = tty->packet; add_wait_queue(&tty->read_wait, &wait); while (nr) { if (packet && tty->link->ctrl_status) { unsigned char cs; if (b != buf) break; spin_lock_irqsave(&tty->link->ctrl_lock, flags); cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); if (tty_put_user(tty, cs, b++)) { retval = -EFAULT; b--; break; } nr--; break; } set_current_state(TASK_INTERRUPTIBLE); if (((minimum - (b - buf)) < tty->minimum_to_wake) && ((minimum - (b - buf)) >= 1)) tty->minimum_to_wake = (minimum - (b - buf)); if (!input_available_p(tty, 0)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { retval = -EIO; break; } if (tty_hung_up_p(file)) break; if (!timeout) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } if (signal_pending(current)) { retval = -ERESTARTSYS; break; } n_tty_set_room(tty); timeout = schedule_timeout(timeout); BUG_ON(!tty->read_buf); continue; } __set_current_state(TASK_RUNNING); if (packet && b == buf) { if (tty_put_user(tty, TIOCPKT_DATA, b++)) { retval = -EFAULT; b--; break; } nr--; } if (tty->icanon && !L_EXTPROC(tty)) { while (nr && tty->read_cnt) { int eol; eol = test_and_clear_bit(tty->read_tail, tty->read_flags); c = tty->read_buf[tty->read_tail]; spin_lock_irqsave(&tty->read_lock, flags); tty->read_tail = ((tty->read_tail+1) & (N_TTY_BUF_SIZE-1)); tty->read_cnt--; if (eol) { if (--tty->canon_data < 0) tty->canon_data = 0; } spin_unlock_irqrestore(&tty->read_lock, flags); if (!eol || (c != __DISABLED_CHAR)) { if (tty_put_user(tty, c, b++)) { retval = -EFAULT; b--; break; } nr--; } if (eol) { tty_audit_push(tty); break; } } if (retval) break; } else { int uncopied; uncopied = copy_from_read_buf(tty, &b, &nr); uncopied += copy_from_read_buf(tty, &b, &nr); if (uncopied) { retval = -EFAULT; break; } } if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { n_tty_set_room(tty); check_unthrottle(tty); } if (b - buf >= minimum) break; if (time) timeout = time; } mutex_unlock(&tty->atomic_read_lock); remove_wait_queue(&tty->read_wait, &wait); if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = minimum; __set_current_state(TASK_RUNNING); size = b - buf; if (size) { retval = size; if (nr) clear_bit(TTY_PUSH, &tty->flags); } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) goto do_it_again; n_tty_set_room(tty); if(tty->update_room_in_ldisc){ spin_lock_irqsave(&tty->buf.lock, flags); head = tty->buf.head; if (head) { count = head->commit - head->read; if ((count || tty->buf.head != tty->buf.tail) && tty->receive_room && !work_busy(&tty->buf.work)){ schedule_work(&tty->buf.work); } } spin_unlock_irqrestore(&tty->buf.lock, flags); } return retval; }
static void do_catch_up(struct spk_synth *synth) { int synth_full_val = 0; static u_char ch; static u_char last = '\0'; unsigned long flags; unsigned long jiff_max; unsigned long timeout = msecs_to_jiffies(4000); DEFINE_WAIT(wait); struct var_t *jiffy_delta; struct var_t *delay_time; int jiffy_delta_val; int delay_time_val; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { /* if no ctl-a in 4, send data anyway */ spin_lock_irqsave(&flush_lock, flags); while (is_flushing && timeout) { prepare_to_wait(&flush, &wait, TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&flush_lock, flags); timeout = schedule_timeout(timeout); spin_lock_irqsave(&flush_lock, flags); } finish_wait(&flush, &wait); is_flushing = 0; spin_unlock_irqrestore(&flush_lock, flags); spin_lock_irqsave(&speakup_info.spinlock, flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spin_unlock_irqrestore(&speakup_info.spinlock, flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); delay_time_val = delay_time->u.n.value; synth_full_val = synth_full(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = 0x0D; if (synth_full_val || !spk_serial_out(ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } set_current_state(TASK_RUNNING); spin_lock_irqsave(&speakup_info.spinlock, flags); synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '[') in_escape = 1; else if (ch == ']') in_escape = 0; else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) spk_serial_out(PROCSPEECH); if (time_after_eq(jiffies, jiff_max)) { if (!in_escape) spk_serial_out(PROCSPEECH); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); schedule_timeout(msecs_to_jiffies (delay_time_val)); jiff_max = jiffies + jiffy_delta_val; } } last = ch; } if (!in_escape) spk_serial_out(PROCSPEECH); }
static int lnet_acceptor(void *arg) { struct socket *newsock; int rc; __u32 magic; __u32 peer_ip; int peer_port; int secure = (int)((long_ptr_t)arg); LASSERT(lnet_acceptor_state.pta_sock == NULL); cfs_block_allsigs(); rc = lnet_sock_listen(&lnet_acceptor_state.pta_sock, 0, accept_port, accept_backlog); if (rc != 0) { if (rc == -EADDRINUSE) LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port %d: port already in use\n", accept_port); else LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port %d: unexpected error %d\n", accept_port, rc); lnet_acceptor_state.pta_sock = NULL; } else { LCONSOLE(0, "Accept %s, port %d\n", accept_type, accept_port); } /* set init status and unblock parent */ lnet_acceptor_state.pta_shutdown = rc; complete(&lnet_acceptor_state.pta_signal); if (rc != 0) return rc; while (!lnet_acceptor_state.pta_shutdown) { rc = lnet_sock_accept(&newsock, lnet_acceptor_state.pta_sock); if (rc != 0) { if (rc != -EAGAIN) { CWARN("Accept error %d: pausing...\n", rc); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(cfs_time_seconds(1)); } continue; } /* maybe the LNet acceptor thread has been waken */ if (lnet_acceptor_state.pta_shutdown) { sock_release(newsock); break; } rc = lnet_sock_getaddr(newsock, 1, &peer_ip, &peer_port); if (rc != 0) { CERROR("Can't determine new connection's address\n"); goto failed; } if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) { CERROR("Refusing connection from %pI4h: insecure port %d\n", &peer_ip, peer_port); goto failed; } rc = lnet_sock_read(newsock, &magic, sizeof(magic), accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from %pI4h\n", rc, &peer_ip); goto failed; } rc = lnet_accept(newsock, magic); if (rc != 0) goto failed; continue; failed: sock_release(newsock); } sock_release(lnet_acceptor_state.pta_sock); lnet_acceptor_state.pta_sock = NULL; CDEBUG(D_NET, "Acceptor stopping\n"); /* unblock lnet_acceptor_stop() */ complete(&lnet_acceptor_state.pta_signal); return 0; }
static int init_port(void) { int i, nlow, nhigh; /* Reserve io region. */ #if defined(LIRC_ALLOW_MMAPPED_IO) /* Future MMAP-Developers: Attention! For memory mapped I/O you *might* need to use ioremap() first, for the NSLU2 it's done in boot code. */ if(((iommap != 0) && (request_mem_region(iommap, 8<<ioshift, LIRC_DRIVER_NAME) == NULL)) || ((iommap == 0) && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) #else if(request_region(io, 8, LIRC_DRIVER_NAME)==NULL) #endif { printk(KERN_ERR LIRC_DRIVER_NAME ": port %04x already in use\n", io); printk(KERN_WARNING LIRC_DRIVER_NAME ": use 'setserial /dev/ttySX uart none'\n"); printk(KERN_WARNING LIRC_DRIVER_NAME ": or compile the serial port driver as module and\n"); printk(KERN_WARNING LIRC_DRIVER_NAME ": make sure this module is loaded first\n"); return(-EBUSY); } hardware_init_port(); /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); /* If pin is high, then this must be an active low receiver. */ if(sense==-1) { /* wait 1/2 sec for the power supply */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/2); /* probe 9 times every 0.04s, collect "votes" for active high/low */ nlow = 0; nhigh = 0; for(i = 0; i < 9; i ++) { if (sinp(UART_MSR) & hardware[type].signal_pin) { nlow++; } else { nhigh++; } schedule_timeout(HZ/25); } sense = (nlow >= nhigh ? 1 : 0); printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " "%s receiver\n",sense ? "low":"high"); } else { printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " "%s receiver\n",sense ? "low":"high"); }; return 0; }
static int cifs_oplock_thread(void * dummyarg) { struct oplock_q_entry * oplock_item; struct cifsTconInfo *pTcon; struct inode * inode; __u16 netfid; int rc; daemonize("cifsoplockd"); allow_signal(SIGTERM); oplockThread = current; do { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1*HZ); spin_lock(&GlobalMid_Lock); if(list_empty(&GlobalOplock_Q)) { spin_unlock(&GlobalMid_Lock); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(39*HZ); } else { oplock_item = list_entry(GlobalOplock_Q.next, struct oplock_q_entry, qhead); if(oplock_item) { cFYI(1,("found oplock item to write out")); pTcon = oplock_item->tcon; inode = oplock_item->pinode; netfid = oplock_item->netfid; spin_unlock(&GlobalMid_Lock); DeleteOplockQEntry(oplock_item); /* can not grab inode sem here since it would deadlock when oplock received on delete since vfs_unlink holds the i_sem across the call */ /* down(&inode->i_sem);*/ if (S_ISREG(inode->i_mode)) { rc = filemap_fdatawrite(inode->i_mapping); if(CIFS_I(inode)->clientCanCacheRead == 0) { filemap_fdatawait(inode->i_mapping); invalidate_remote_inode(inode); } } else rc = 0; /* up(&inode->i_sem);*/ if (rc) CIFS_I(inode)->write_behind_rc = rc; cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); /* releasing a stale oplock after recent reconnection of smb session using a now incorrect file handle is not a data integrity issue but do not bother sending an oplock release if session to server still is disconnected since oplock already released by the server in that case */ if(pTcon->tidStatus != CifsNeedReconnect) { rc = CIFSSMBLock(0, pTcon, netfid, 0 /* len */ , 0 /* offset */, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, 0 /* wait flag */); cFYI(1,("Oplock release rc = %d ",rc)); } } else spin_unlock(&GlobalMid_Lock); } } while(!signal_pending(current)); complete_and_exit (&cifs_oplock_exited, 0); oplockThread = NULL; }
void one_core_wq_wait( OneCore *core, OneWaitQueue *queue, int *timeout_ms ) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) DEFINE_WAIT(wait); int timeout = 0; if (timeout_ms) timeout = *timeout_ms * HZ / 1000; D_MAGIC_ASSERT( core, OneCore ); D_MAGIC_ASSERT( queue, OneWaitQueue ); prepare_to_wait( &queue->queue, &wait, TASK_INTERRUPTIBLE ); one_core_unlock( core ); if (timeout_ms) { timeout = schedule_timeout(timeout); if (timeout) { timeout = timeout * 1000 / HZ; *timeout_ms = timeout ? timeout : 1; } else *timeout_ms = 0; } else schedule(); one_core_lock( core ); finish_wait( &queue->queue, &wait ); #else wait_queue_t wait; int timeout = 0; if (timeout_ms) timeout = *timeout_ms * HZ / 1000; D_MAGIC_ASSERT( core, OneCore ); D_MAGIC_ASSERT( queue, OneWaitQueue ); init_waitqueue_entry(&wait, current); current->state = TASK_INTERRUPTIBLE; write_lock( &queue->queue.lock); __add_wait_queue( &queue->queue, &wait); write_unlock( &queue->queue.lock ); one_core_unlock( core ); if (timeout_ms) { timeout = schedule_timeout(timeout); if (timeout) { timeout = timeout * 1000 / HZ; *timeout_ms = timeout ? timeout : 1; } else *timeout_ms = 0; } else schedule(); one_core_lock( core ); write_lock( &queue->queue.lock ); __remove_wait_queue( &queue->queue, &wait ); write_unlock( &queue->queue.lock ); #endif }
static void do_catch_up(struct spk_synth *synth) { u_char ch; static u_char last; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; int jiffy_delta_val; int delay_time_val; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); delay_time_val = delay_time->u.n.value; spk_unlock(flags); if (ch == '\n') ch = 0x0D; if (dt_sendchar(ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } set_current_state(TASK_RUNNING); spk_lock(flags); synth_buffer_getc(); spk_unlock(flags); if (ch == '[') in_escape = 1; else if (ch == ']') in_escape = 0; else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) dt_sendchar(PROCSPEECH); if (jiffies >= jiff_max) { if (!in_escape) dt_sendchar(PROCSPEECH); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spk_unlock(flags); schedule_timeout(msecs_to_jiffies (delay_time_val)); jiff_max = jiffies + jiffy_delta_val; } } last = ch; ch = 0; } if (!in_escape) dt_sendchar(PROCSPEECH); }
static ssize_t scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) { int status; int len; unsigned long flags; struct subch_data_s *sd = (struct subch_data_s *) file->private_data; /* try to get control of the read buffer */ if (down_trylock(&sd->sd_rbs)) { /* somebody else has it now; * if we're non-blocking, then exit... */ if (file->f_flags & O_NONBLOCK) { return -EAGAIN; } /* ...or if we want to block, then do so here */ if (down_interruptible(&sd->sd_rbs)) { /* something went wrong with wait */ return -ERESTARTSYS; } } /* anything to read? */ len = CHUNKSIZE; spin_lock_irqsave(&sd->sd_rlock, flags); status = read_status_check(sd, &len); /* if not, and we're blocking I/O, loop */ while (status < 0) { DECLARE_WAITQUEUE(wait, current); if (file->f_flags & O_NONBLOCK) { spin_unlock_irqrestore(&sd->sd_rlock, flags); up(&sd->sd_rbs); return -EAGAIN; } len = CHUNKSIZE; set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&sd->sd_rq, &wait); spin_unlock_irqrestore(&sd->sd_rlock, flags); schedule_timeout(SCDRV_TIMEOUT); remove_wait_queue(&sd->sd_rq, &wait); if (signal_pending(current)) { /* wait was interrupted */ up(&sd->sd_rbs); return -ERESTARTSYS; } spin_lock_irqsave(&sd->sd_rlock, flags); status = read_status_check(sd, &len); } spin_unlock_irqrestore(&sd->sd_rlock, flags); if (len > 0) { /* we read something in the last read_status_check(); copy * it out to user space */ if (count < len) { pr_debug("%s: only accepting %d of %d bytes\n", __func__, (int) count, len); } len = min((int) count, len); if (copy_to_user(buf, sd->sd_rb, len)) len = -EFAULT; } /* release the read buffer and wake anyone who might be * waiting for it */ up(&sd->sd_rbs); /* return the number of characters read in */ return len; }
static ssize_t scdrv_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos) { unsigned long flags; int status; struct subch_data_s *sd = (struct subch_data_s *) file->private_data; /* try to get control of the write buffer */ if (down_trylock(&sd->sd_wbs)) { /* somebody else has it now; * if we're non-blocking, then exit... */ if (file->f_flags & O_NONBLOCK) { return -EAGAIN; } /* ...or if we want to block, then do so here */ if (down_interruptible(&sd->sd_wbs)) { /* something went wrong with wait */ return -ERESTARTSYS; } } count = min((int) count, CHUNKSIZE); if (copy_from_user(sd->sd_wb, buf, count)) { up(&sd->sd_wbs); return -EFAULT; } /* try to send the buffer */ spin_lock_irqsave(&sd->sd_wlock, flags); status = write_status_check(sd, count); /* if we failed, and we want to block, then loop */ while (status <= 0) { DECLARE_WAITQUEUE(wait, current); if (file->f_flags & O_NONBLOCK) { spin_unlock(&sd->sd_wlock); up(&sd->sd_wbs); return -EAGAIN; } set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&sd->sd_wq, &wait); spin_unlock_irqrestore(&sd->sd_wlock, flags); schedule_timeout(SCDRV_TIMEOUT); remove_wait_queue(&sd->sd_wq, &wait); if (signal_pending(current)) { /* wait was interrupted */ up(&sd->sd_wbs); return -ERESTARTSYS; } spin_lock_irqsave(&sd->sd_wlock, flags); status = write_status_check(sd, count); } spin_unlock_irqrestore(&sd->sd_wlock, flags); /* release the write buffer and wake anyone who's waiting for it */ up(&sd->sd_wbs); /* return the number of characters accepted (should be the complete * "chunk" as requested) */ if ((status >= 0) && (status < count)) { pr_debug("Didn't accept the full chunk; %d of %d\n", status, (int) count); } return status; }
static void do_catch_up(struct spk_synth *synth) { u_char ch; int timeout; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; struct var_t *full_time; int delay_time_val; int full_time_val; int jiffy_delta_val; jiffy_delta = get_var(JIFFY); delay_time = get_var(DELAY); full_time = get_var(FULL); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spk_unlock(flags); if (synth_full()) { schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } set_current_state(TASK_RUNNING); timeout = 1000; while (synth_writable()) if (--timeout <= 0) break; if (timeout <= 0) { oops(); break; } spk_lock(flags); ch = synth_buffer_getc(); spk_unlock(flags); if (ch == '\n') ch = PROCSPEECH; outb_p(ch, synth_port); SWAIT; if ((jiffies >= jiff_max) && (ch == SPACE)) { timeout = 1000; while (synth_writable()) if (--timeout <= 0) break; if (timeout <= 0) { oops(); break; } outb_p(PROCSPEECH, synth_port); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spk_unlock(flags); schedule_timeout(msecs_to_jiffies(delay_time_val)); jiff_max = jiffies+jiffy_delta_val; } } timeout = 1000; while (synth_writable()) if (--timeout <= 0) break; if (timeout <= 0) oops(); else outb_p(PROCSPEECH, synth_port); }
static void do_catch_up(struct spk_synth *synth) { u_char ch; unsigned long flags; unsigned long jiff_max; int timeout; int delay_time_val; int jiffy_delta_val; int full_time_val; struct var_t *delay_time; struct var_t *full_time; struct var_t *jiffy_delta; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); full_time = spk_get_var(FULL); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spin_lock_irqsave(&speakup_info.spinlock, flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spin_unlock_irqrestore(&speakup_info.spinlock, flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; } set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (synth_full()) { schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } set_current_state(TASK_RUNNING); timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } spin_lock_irqsave(&speakup_info.spinlock, flags); ch = synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = PROCSPEECH; outb_p(ch, speakup_info.port_tts); if (time_after_eq(jiffies, jiff_max) && ch == SPACE) { timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } outb_p(PROCSPEECH, speakup_info.port_tts); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); schedule_timeout(msecs_to_jiffies(delay_time_val)); jiff_max = jiffies+jiffy_delta_val; } } timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } outb_p(PROCSPEECH, speakup_info.port_tts); }
static void ad1889_update_ptr(ad1889_dev_t *dev, int wake) { ad1889_state_t *state; struct dmabuf *dmabuf; unsigned long hwptr; int diff; /* check ADC first */ state = &dev->adc_state; dmabuf = &state->dmabuf; if (dmabuf->enable & ADC_RUNNING) { hwptr = ad1889_get_dma_addr(state); diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; dmabuf->hwptr = hwptr; dmabuf->total_bytes += diff; dmabuf->count += diff; if (dmabuf->count > dmabuf->dmasize) dmabuf->count = dmabuf->dmasize; if (dmabuf->mapped) { if (wake & dmabuf->count >= dmabuf->fragsize) wake_up(&dmabuf->wait); } else { if (wake & dmabuf->count > 0) wake_up(&dmabuf->wait); } } /* check DAC */ state = &dev->wav_state; dmabuf = &state->dmabuf; if (dmabuf->enable & DAC_RUNNING) { XXX } #endif /************************* /dev/dsp interfaces ************************* */ static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { return 0; } static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data; ad1889_state_t *state = &dev->state[AD_WAV_STATE]; volatile struct dmabuf *dmabuf = &state->dmabuf; ssize_t ret = 0; DECLARE_WAITQUEUE(wait, current); down(&state->sem); #if 0 if (dmabuf->mapped) { ret = -ENXIO; goto err1; } #endif if (!access_ok(VERIFY_READ, buffer, count)) { ret = -EFAULT; goto err1; } add_wait_queue(&state->dmabuf.wait, &wait); /* start filling dma buffer.... */ while (count > 0) { long rem; long cnt = count; unsigned long flags; for (;;) { long used_bytes; long timeout; /* max time for DMA in jiffies */ /* buffer is full if wr catches up to rd */ spin_lock_irqsave(&state->card->lock, flags); used_bytes = dmabuf->wr_ptr - dmabuf->rd_ptr; timeout = (dmabuf->dma_len * HZ) / dmabuf->rate; spin_unlock_irqrestore(&state->card->lock, flags); /* adjust for buffer wrap around */ used_bytes = (used_bytes + DMA_SIZE) & (DMA_SIZE - 1); /* If at least one page unused */ if (used_bytes < (DMA_SIZE - 0x1000)) break; /* dma buffer full */ if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; goto err2; } set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(timeout + 1); if (signal_pending(current)) { ret = -ERESTARTSYS; goto err2; } } /* watch out for wrapping around static buffer */ spin_lock_irqsave(&state->card->lock, flags); rem = DMA_SIZE - dmabuf->wr_ptr; if (cnt > rem) cnt = rem; rem = dmabuf->wr_ptr; /* update dma pointers */ dmabuf->wr_ptr += cnt; dmabuf->wr_ptr &= DMA_SIZE - 1; /* wrap ptr if necessary */ spin_unlock_irqrestore(&state->card->lock, flags); /* transfer unwrapped chunk */ if (copy_from_user(dmabuf->rawbuf + rem, buffer, cnt)) { ret = -EFAULT; goto err2; } DBG("Writing 0x%lx bytes to +0x%lx\n", cnt, rem); /* update counters */ count -= cnt; buffer += cnt; ret += cnt; /* we have something to play - go play it! */ ad1889_trigger_playback(dev); } err2: remove_wait_queue(&state->dmabuf.wait, &wait); err1: up(&state->sem); return ret; }
static int zpios_thread_main(void *data) { thread_data_t *thr = (thread_data_t *)data; run_args_t *run_args = thr->run_args; zpios_time_t t; dmu_obj_t obj; __u64 offset; __u32 chunk_size; zpios_region_t *region; char *buf; unsigned int random_int; int chunk_noise = run_args->chunk_noise; int chunk_noise_tmp = 0; int thread_delay = run_args->thread_delay; int thread_delay_tmp = 0; int i, rc = 0; if (chunk_noise) { get_random_bytes(&random_int, sizeof (unsigned int)); chunk_noise_tmp = (random_int % (chunk_noise * 2))-chunk_noise; } /* * It's OK to vmem_alloc() this memory because it will be copied * in to the slab and pointers to the slab copy will be setup in * the bio when the IO is submitted. This of course is not ideal * since we want a zero-copy IO path if possible. It would be nice * to have direct access to those slab entries. */ chunk_size = run_args->chunk_size + chunk_noise_tmp; buf = (char *)vmem_alloc(chunk_size, KM_SLEEP); ASSERT(buf); /* Trivial data verification pattern for now. */ if (run_args->flags & DMU_VERIFY) memset(buf, 'z', chunk_size); /* Write phase */ mutex_enter(&thr->lock); thr->stats.wr_time.start = zpios_timespec_now(); mutex_exit(&thr->lock); while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_WRITE)) { if (thread_delay) { get_random_bytes(&random_int, sizeof (unsigned int)); thread_delay_tmp = random_int % thread_delay; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(thread_delay_tmp); /* In jiffies */ } t.start = zpios_timespec_now(); rc = zpios_dmu_write(run_args, obj.os, obj.obj, offset, chunk_size, buf); t.stop = zpios_timespec_now(); t.delta = zpios_timespec_sub(t.stop, t.start); if (rc) { zpios_print(run_args->file, "IO error while doing " "dmu_write(): %d\n", rc); break; } mutex_enter(&thr->lock); thr->stats.wr_data += chunk_size; thr->stats.wr_chunks++; thr->stats.wr_time.delta = zpios_timespec_add( thr->stats.wr_time.delta, t.delta); mutex_exit(&thr->lock); mutex_enter(®ion->lock); region->stats.wr_data += chunk_size; region->stats.wr_chunks++; region->stats.wr_time.delta = zpios_timespec_add( region->stats.wr_time.delta, t.delta); /* First time region was accessed */ if (region->init_offset == offset) region->stats.wr_time.start = t.start; mutex_exit(®ion->lock); } mutex_enter(&run_args->lock_ctl); run_args->threads_done++; mutex_exit(&run_args->lock_ctl); mutex_enter(&thr->lock); thr->rc = rc; thr->stats.wr_time.stop = zpios_timespec_now(); mutex_exit(&thr->lock); wake_up(&run_args->waitq); set_current_state(TASK_UNINTERRUPTIBLE); schedule(); /* Check if we should exit */ mutex_enter(&thr->lock); rc = thr->rc; mutex_exit(&thr->lock); if (rc) goto out; /* Read phase */ mutex_enter(&thr->lock); thr->stats.rd_time.start = zpios_timespec_now(); mutex_exit(&thr->lock); while (zpios_get_work_item(run_args, &obj, &offset, &chunk_size, ®ion, DMU_READ)) { if (thread_delay) { get_random_bytes(&random_int, sizeof (unsigned int)); thread_delay_tmp = random_int % thread_delay; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(thread_delay_tmp); /* In jiffies */ } if (run_args->flags & DMU_VERIFY) memset(buf, 0, chunk_size); t.start = zpios_timespec_now(); rc = zpios_dmu_read(run_args, obj.os, obj.obj, offset, chunk_size, buf); t.stop = zpios_timespec_now(); t.delta = zpios_timespec_sub(t.stop, t.start); if (rc) { zpios_print(run_args->file, "IO error while doing " "dmu_read(): %d\n", rc); break; } /* Trivial data verification, expensive! */ if (run_args->flags & DMU_VERIFY) { for (i = 0; i < chunk_size; i++) { if (buf[i] != 'z') { zpios_print(run_args->file, "IO verify error: %d/%d/%d\n", (int)obj.obj, (int)offset, (int)chunk_size); break; } } } mutex_enter(&thr->lock); thr->stats.rd_data += chunk_size; thr->stats.rd_chunks++; thr->stats.rd_time.delta = zpios_timespec_add( thr->stats.rd_time.delta, t.delta); mutex_exit(&thr->lock); mutex_enter(®ion->lock); region->stats.rd_data += chunk_size; region->stats.rd_chunks++; region->stats.rd_time.delta = zpios_timespec_add( region->stats.rd_time.delta, t.delta); /* First time region was accessed */ if (region->init_offset == offset) region->stats.rd_time.start = t.start; mutex_exit(®ion->lock); } mutex_enter(&run_args->lock_ctl); run_args->threads_done++; mutex_exit(&run_args->lock_ctl); mutex_enter(&thr->lock); thr->rc = rc; thr->stats.rd_time.stop = zpios_timespec_now(); mutex_exit(&thr->lock); wake_up(&run_args->waitq); out: vmem_free(buf, chunk_size); do_exit(0); return (rc); /* Unreachable, due to do_exit() */ }
int vmw_fallback_wait(struct vmw_private *dev_priv, bool lazy, bool fifo_idle, uint32_t sequence, bool interruptible, unsigned long timeout) { struct vmw_fifo_state *fifo_state = &dev_priv->fifo; uint32_t count = 0; uint32_t signal_seq; int ret; unsigned long end_jiffies = jiffies + timeout; bool (*wait_condition)(struct vmw_private *, uint32_t); DEFINE_WAIT(__wait); wait_condition = (fifo_idle) ? &vmw_fifo_idle : &vmw_fence_signaled; /** * Block command submission while waiting for idle. */ if (fifo_idle) down_read(&fifo_state->rwsem); signal_seq = atomic_read_unchecked(&dev_priv->fence_seq); ret = 0; for (;;) { prepare_to_wait(&dev_priv->fence_queue, &__wait, (interruptible) ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); if (wait_condition(dev_priv, sequence)) break; if (time_after_eq(jiffies, end_jiffies)) { DRM_ERROR("SVGA device lockup.\n"); break; } if (lazy) schedule_timeout(1); else if ((++count & 0x0F) == 0) { /** * FIXME: Use schedule_hr_timeout here for * newer kernels and lower CPU utilization. */ __set_current_state(TASK_RUNNING); schedule(); __set_current_state((interruptible) ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); } if (interruptible && signal_pending(current)) { ret = -ERESTARTSYS; break; } } finish_wait(&dev_priv->fence_queue, &__wait); if (ret == 0 && fifo_idle) { __le32 __iomem *fifo_mem = dev_priv->mmio_virt; iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE); } wake_up_all(&dev_priv->fence_queue); if (fifo_idle) up_read(&fifo_state->rwsem); return ret; }
static void bluecard_write_wakeup(bluecard_info_t *info) { if (!info) { BT_ERR("Unknown device"); return; } if (!test_bit(XMIT_SENDING_READY, &(info->tx_state))) return; if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { set_bit(XMIT_WAKEUP, &(info->tx_state)); return; } do { register unsigned int iobase = info->p_dev->resource[0]->start; register unsigned int offset; register unsigned char command; register unsigned long ready_bit; register struct sk_buff *skb; register int len; clear_bit(XMIT_WAKEUP, &(info->tx_state)); if (!pcmcia_dev_present(info->p_dev)) return; if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state))) break; offset = 0x10; command = REG_COMMAND_TX_BUF_TWO; ready_bit = XMIT_BUF_TWO_READY; } else { if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state))) break; offset = 0x00; command = REG_COMMAND_TX_BUF_ONE; ready_bit = XMIT_BUF_ONE_READY; } if (!(skb = skb_dequeue(&(info->txq)))) break; if (bt_cb(skb)->pkt_type & 0x80) { /* Disable RTS */ info->ctrl_reg |= REG_CONTROL_RTS; outb(info->ctrl_reg, iobase + REG_CONTROL); } /* Activate LED */ bluecard_enable_activity_led(info); /* Send frame */ len = bluecard_write(iobase, offset, skb->data, skb->len); /* Tell the FPGA to send the data */ outb_p(command, iobase + REG_COMMAND); /* Mark the buffer as dirty */ clear_bit(ready_bit, &(info->tx_state)); if (bt_cb(skb)->pkt_type & 0x80) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); DEFINE_WAIT(wait); unsigned char baud_reg; switch (bt_cb(skb)->pkt_type) { case PKT_BAUD_RATE_460800: baud_reg = REG_CONTROL_BAUD_RATE_460800; break; case PKT_BAUD_RATE_230400: baud_reg = REG_CONTROL_BAUD_RATE_230400; break; case PKT_BAUD_RATE_115200: baud_reg = REG_CONTROL_BAUD_RATE_115200; break; case PKT_BAUD_RATE_57600: /* Fall through... */ default: baud_reg = REG_CONTROL_BAUD_RATE_57600; break; } /* Wait until the command reaches the baseband */ prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); finish_wait(&wq, &wait); /* Set baud on baseband */ info->ctrl_reg &= ~0x03; info->ctrl_reg |= baud_reg; outb(info->ctrl_reg, iobase + REG_CONTROL); /* Enable RTS */ info->ctrl_reg &= ~REG_CONTROL_RTS; outb(info->ctrl_reg, iobase + REG_CONTROL); /* Wait before the next HCI packet can be send */ prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); schedule_timeout(HZ); finish_wait(&wq, &wait); } if (len == skb->len) { kfree_skb(skb); } else { skb_pull(skb, len); skb_queue_head(&(info->txq), skb); } info->hdev->stat.byte_tx += len; /* Change buffer */ change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state)); } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); clear_bit(XMIT_SENDING, &(info->tx_state)); }
static int sdio_irq_thread(void *_host) { struct mmc_host *host = _host; struct sched_param param = { .sched_priority = 1 }; unsigned long period, idle_period; int ret; sched_setscheduler(current, SCHED_FIFO, ¶m); idle_period = msecs_to_jiffies(10); period = (host->caps & MMC_CAP_SDIO_IRQ) ? MAX_SCHEDULE_TIMEOUT : idle_period; pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n", mmc_hostname(host), period); do { ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort); if (ret) break; ret = process_sdio_pending_irqs(host); host->sdio_irq_pending = false; mmc_release_host(host); if (ret < 0) { set_current_state(TASK_INTERRUPTIBLE); if (!kthread_should_stop()) schedule_timeout(HZ); set_current_state(TASK_RUNNING); } if (!(host->caps & MMC_CAP_SDIO_IRQ)) { if (ret > 0) period /= 2; else { period++; if (period > idle_period) period = idle_period; } } set_current_state(TASK_INTERRUPTIBLE); if (host->caps & MMC_CAP_SDIO_IRQ) { mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 1); mmc_host_clk_release(host); } if (!kthread_should_stop()) schedule_timeout(period); set_current_state(TASK_RUNNING); } while (!kthread_should_stop()); if (host->caps & MMC_CAP_SDIO_IRQ) { mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 0); mmc_host_clk_release(host); } pr_debug("%s: IRQ thread exiting with code %d\n", mmc_hostname(host), ret); return ret; } static int sdio_card_irq_get(struct mmc_card *card) { struct mmc_host *host = card->host; WARN_ON(!host->claimed); if (!host->sdio_irqs++) { atomic_set(&host->sdio_irq_thread_abort, 0); host->sdio_irq_thread = kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", mmc_hostname(host)); if (IS_ERR(host->sdio_irq_thread)) { int err = PTR_ERR(host->sdio_irq_thread); host->sdio_irqs--; return err; } if (host->caps & MMC_CAP_SDIO_IRQ) { mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 1); mmc_host_clk_release(host); } } return 0; } static int sdio_card_irq_put(struct mmc_card *card) { struct mmc_host *host = card->host; WARN_ON(!host->claimed); BUG_ON(host->sdio_irqs < 1); if (host->sdio_irqs == 1) { if (host->caps & MMC_CAP_SDIO_IRQ) { mmc_host_clk_hold(host); host->ops->enable_sdio_irq(host, 0); mmc_host_clk_release(host); } } if (!--host->sdio_irqs) { atomic_set(&host->sdio_irq_thread_abort, 1); kthread_stop(host->sdio_irq_thread); } return 0; } static void sdio_single_irq_set(struct mmc_card *card) { struct sdio_func *func; int i; card->sdio_single_irq = NULL; if ((card->host->caps & MMC_CAP_SDIO_IRQ) && card->host->sdio_irqs == 1) for (i = 0; i < card->sdio_funcs; i++) { func = card->sdio_func[i]; if (func && func->irq_handler) { card->sdio_single_irq = func; break; } } } int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) { int ret; unsigned char reg; BUG_ON(!func); BUG_ON(!func->card); pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func)); if (func->irq_handler) { pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func)); return -EBUSY; } ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®); if (ret) return ret; reg |= 1 << func->num; reg |= 1; ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL); if (ret) return ret; func->irq_handler = handler; ret = sdio_card_irq_get(func->card); if (ret) func->irq_handler = NULL; sdio_single_irq_set(func->card); return ret; }
static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter) { u32 val = 0; int retval; DBG(1,""); isac_init(&adapter->isac); // FIXME is this okay now retval = -EBUSY; if (!request_region(adapter->io, 32, "fcpcipnp")) goto err; switch (adapter->type) { case AVM_FRITZ_PCIV2: retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ, "fcpcipnp", adapter); break; case AVM_FRITZ_PCI: retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ, "fcpcipnp", adapter); break; case AVM_FRITZ_PNP: retval = request_irq(adapter->irq, fcpci_irq, 0, "fcpcipnp", adapter); break; } if (retval) goto err_region; switch (adapter->type) { case AVM_FRITZ_PCIV2: case AVM_FRITZ_PCI: val = inl(adapter->io); break; case AVM_FRITZ_PNP: val = inb(adapter->io); val |= inb(adapter->io + 1) << 8; break; } DBG(1, "stat %#x Class %X Rev %d", val, val & 0xff, (val>>8) & 0xff); spin_lock_init(&adapter->hw_lock); adapter->isac.priv = adapter; switch (adapter->type) { case AVM_FRITZ_PCIV2: adapter->isac.read_isac = &fcpci2_read_isac;; adapter->isac.write_isac = &fcpci2_write_isac; adapter->isac.read_isac_fifo = &fcpci2_read_isac_fifo; adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo; adapter->read_hdlc_status = &fcpci2_read_hdlc_status; adapter->write_ctrl = &fcpci2_write_ctrl; break; case AVM_FRITZ_PCI: adapter->isac.read_isac = &fcpci_read_isac;; adapter->isac.write_isac = &fcpci_write_isac; adapter->isac.read_isac_fifo = &fcpci_read_isac_fifo; adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo; adapter->read_hdlc_status = &fcpci_read_hdlc_status; adapter->write_ctrl = &fcpci_write_ctrl; break; case AVM_FRITZ_PNP: adapter->isac.read_isac = &fcpci_read_isac;; adapter->isac.write_isac = &fcpci_write_isac; adapter->isac.read_isac_fifo = &fcpci_read_isac_fifo; adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo; adapter->read_hdlc_status = &fcpnp_read_hdlc_status; adapter->write_ctrl = &fcpnp_write_ctrl; break; } // Reset outb(0, adapter->io + AVM_STATUS0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(50 * HZ / 1000); // 50 msec outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(50 * HZ / 1000); // 50 msec outb(0, adapter->io + AVM_STATUS0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(10 * HZ / 1000); // 10 msec switch (adapter->type) { case AVM_FRITZ_PCIV2: fcpci2_init(adapter); isacsx_setup(&adapter->isac); break; case AVM_FRITZ_PCI: case AVM_FRITZ_PNP: fcpci_init(adapter); isac_setup(&adapter->isac); break; } val = adapter->read_hdlc_status(adapter, 0); DBG(0x20, "HDLC A STA %x", val); val = adapter->read_hdlc_status(adapter, 1); DBG(0x20, "HDLC B STA %x", val); adapter->bcs[0].mode = -1; adapter->bcs[1].mode = -1; modehdlc(&adapter->bcs[0], L1_MODE_NULL); modehdlc(&adapter->bcs[1], L1_MODE_NULL); return 0; err_region: release_region(adapter->io, 32); err: return retval; }
/* Delay */ static void delay_cycx(int sec) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sec*HZ); }
inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(pinfo->wait_closing); }
int do_select(int n, fd_set_bits *fds, long *timeout) { struct poll_wqueues table; poll_table *wait; int retval, i; long __timeout = *timeout; spin_lock(¤t->files->file_lock); retval = max_select_fd(n, fds); spin_unlock(¤t->files->file_lock); if (retval < 0) return retval; n = retval; poll_initwait(&table); wait = &table.pt; if (!__timeout) wait = NULL; retval = 0; for (;;) { unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; set_current_state(TASK_INTERRUPTIBLE); inp = fds->in; outp = fds->out; exp = fds->ex; rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; for (i = 0; i < n; ++rinp, ++routp, ++rexp) { unsigned long in, out, ex, all_bits, bit = 1, mask, j; unsigned long res_in = 0, res_out = 0, res_ex = 0; struct file_operations *f_op = NULL; struct file *file = NULL; in = *inp++; out = *outp++; ex = *exp++; all_bits = in | out | ex; if (all_bits == 0) { i += __NFDBITS; continue; } for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { if (i >= n) break; if (!(bit & all_bits)) continue; file = fget(i); if (file) { f_op = file->f_op; mask = DEFAULT_POLLMASK; if (f_op && f_op->poll) mask = (*f_op->poll)(file, retval ? NULL : wait); fput(file); if ((mask & POLLIN_SET) && (in & bit)) { res_in |= bit; retval++; } if ((mask & POLLOUT_SET) && (out & bit)) { res_out |= bit; retval++; } if ((mask & POLLEX_SET) && (ex & bit)) { res_ex |= bit; retval++; } } } if (res_in) *rinp = res_in; if (res_out) *routp = res_out; if (res_ex) *rexp = res_ex; } wait = NULL; if (retval || !__timeout || signal_pending(current)) break; if(table.error) { retval = table.error; break; } __timeout = schedule_timeout(__timeout); } __set_current_state(TASK_RUNNING); poll_freewait(&table); /* * Up-to-date the caller timeout. */ *timeout = __timeout; return retval; }
static void do_catch_up(struct spk_synth *synth) { u_char ch; static u_char last = '\0'; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; int jiffy_delta_val = 0; int delay_time_val = 0; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spin_lock_irqsave(&speakup_info.spinlock, flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spin_unlock_irqrestore(&speakup_info.spinlock, flags); synth->flush(synth); continue; } synth_buffer_skip_nonlatin1(); if (synth_buffer_empty()) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '\n') ch = 0x0D; if (synth_full() || !synth->io_ops->synth_out(synth, ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } set_current_state(TASK_RUNNING); spin_lock_irqsave(&speakup_info.spinlock, flags); synth_buffer_getc(); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (ch == '[') { in_escape = 1; } else if (ch == ']') { in_escape = 0; } else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) synth->io_ops->synth_out(synth, PROCSPEECH); if (time_after_eq(jiffies, jiff_max)) { if (!in_escape) synth->io_ops->synth_out(synth, PROCSPEECH); spin_lock_irqsave(&speakup_info.spinlock, flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spin_unlock_irqrestore(&speakup_info.spinlock, flags); schedule_timeout(msecs_to_jiffies (delay_time_val)); jiff_max = jiffies + jiffy_delta_val; } } last = ch; } if (!in_escape) synth->io_ops->synth_out(synth, PROCSPEECH); }
static ssize_t write_rio(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) { DEFINE_WAIT(wait); struct rio_usb_data *rio = &rio_instance; unsigned long copy_size; unsigned long bytes_written = 0; unsigned int partial; int result = 0; int maxretry; int errn = 0; int intr; intr = mutex_lock_interruptible(&(rio->lock)); if (intr) return -EINTR; /* Sanity check to make sure rio is connected, powered, etc */ if (rio->present == 0 || rio->rio_dev == NULL) { mutex_unlock(&(rio->lock)); return -ENODEV; } do { unsigned long thistime; char *obuf = rio->obuf; thistime = copy_size = (count >= OBUF_SIZE) ? OBUF_SIZE : count; if (copy_from_user(rio->obuf, buffer, copy_size)) { errn = -EFAULT; goto error; } maxretry = 5; while (thistime) { if (!rio->rio_dev) { errn = -ENODEV; goto error; } if (signal_pending(current)) { mutex_unlock(&(rio->lock)); return bytes_written ? bytes_written : -EINTR; } result = usb_bulk_msg(rio->rio_dev, usb_sndbulkpipe(rio->rio_dev, 2), obuf, thistime, &partial, 5000); dbg("write stats: result:%d thistime:%lu partial:%u", result, thistime, partial); if (result == -ETIMEDOUT) { /* NAK - so hold for a while */ if (!maxretry--) { errn = -ETIME; goto error; } prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); schedule_timeout(NAK_TIMEOUT); finish_wait(&rio->wait_q, &wait); continue; } else if (!result && partial) { obuf += partial; thistime -= partial; } else break; }; if (result) { err("Write Whoops - %x", result); errn = -EIO; goto error; } bytes_written += copy_size; count -= copy_size; buffer += copy_size; } while (count > 0); mutex_unlock(&(rio->lock)); return bytes_written ? bytes_written : -EIO; error: mutex_unlock(&(rio->lock)); return errn; }
/* * iterate through the VL servers in a cell until one of them admits knowing * about the volume in question */ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl, struct key *key, afs_volid_t volid, afs_voltype_t voltype, struct afs_cache_vlocation *vldb) { struct afs_cell *cell = vl->cell; struct in_addr addr; int count, ret; _enter("%s,%x,%d,", cell->name, volid, voltype); down_write(&vl->cell->vl_sem); ret = -ENOMEDIUM; for (count = cell->vl_naddrs; count > 0; count--) { addr = cell->vl_addrs[cell->vl_curr_svix]; _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr); /* attempt to access the VL server */ ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb, &afs_sync_call); switch (ret) { case 0: goto out; case -ENOMEM: case -ENONET: case -ENETUNREACH: case -EHOSTUNREACH: case -ECONNREFUSED: if (ret == -ENOMEM || ret == -ENONET) goto out; goto rotate; case -EBUSY: vl->upd_busy_cnt++; if (vl->upd_busy_cnt <= 3) { if (vl->upd_busy_cnt > 1) { /* second+ BUSY - sleep a little bit */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); __set_current_state(TASK_RUNNING); } continue; } break; case -ENOMEDIUM: vl->upd_rej_cnt++; goto rotate; default: ret = -EIO; goto rotate; } /* rotate the server records upon lookup failure */ rotate: cell->vl_curr_svix++; cell->vl_curr_svix %= cell->vl_naddrs; vl->upd_busy_cnt = 0; } out: if (ret < 0 && vl->upd_rej_cnt > 0) { printk(KERN_NOTICE "kAFS:" " Active volume no longer valid '%s'\n", vl->vldb.name); vl->valid = 0; ret = -ENOMEDIUM; } up_write(&vl->cell->vl_sem); _leave(" = %d", ret); return ret; }
static ssize_t read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) { DEFINE_WAIT(wait); struct rio_usb_data *rio = &rio_instance; ssize_t read_count; unsigned int partial; int this_read; int result; int maxretry = 10; char *ibuf; int intr; intr = mutex_lock_interruptible(&(rio->lock)); if (intr) return -EINTR; /* Sanity check to make sure rio is connected, powered, etc */ if (rio->present == 0 || rio->rio_dev == NULL) { mutex_unlock(&(rio->lock)); return -ENODEV; } ibuf = rio->ibuf; read_count = 0; while (count > 0) { if (signal_pending(current)) { mutex_unlock(&(rio->lock)); return read_count ? read_count : -EINTR; } if (!rio->rio_dev) { mutex_unlock(&(rio->lock)); return -ENODEV; } this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; result = usb_bulk_msg(rio->rio_dev, usb_rcvbulkpipe(rio->rio_dev, 1), ibuf, this_read, &partial, 8000); dbg("read stats: result:%d this_read:%u partial:%u", result, this_read, partial); if (partial) { count = this_read = partial; } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ if (!maxretry--) { mutex_unlock(&(rio->lock)); err("read_rio: maxretry timeout"); return -ETIME; } prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); schedule_timeout(NAK_TIMEOUT); finish_wait(&rio->wait_q, &wait); continue; } else if (result != -EREMOTEIO) { mutex_unlock(&(rio->lock)); err("Read Whoops - result:%u partial:%u this_read:%u", result, partial, this_read); return -EIO; } else { mutex_unlock(&(rio->lock)); return (0); } if (this_read) { if (copy_to_user(buffer, ibuf, this_read)) { mutex_unlock(&(rio->lock)); return -EFAULT; } count -= this_read; read_count += this_read; buffer += this_read; } } mutex_unlock(&(rio->lock)); return read_count; }
/* Main loop of the progression thread: keep eating from the buffer * and push to the serial port, waiting as needed * * For devices that have a "full" notification mecanism, the driver can * adapt the loop the way they prefer. */ void spk_do_catch_up(struct spk_synth *synth) { u_char ch; unsigned long flags; unsigned long jiff_max; struct var_t *delay_time; struct var_t *full_time; struct var_t *jiffy_delta; int jiffy_delta_val; int delay_time_val; int full_time_val; jiffy_delta = spk_get_var(JIFFY); full_time = spk_get_var(FULL); delay_time = spk_get_var(DELAY); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spk_unlock(flags); if (ch == '\n') ch = synth->procspeech; if (!spk_serial_out(ch)) { schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } if ((jiffies >= jiff_max) && (ch == SPACE)) { spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; full_time_val = full_time->u.n.value; spk_unlock(flags); if (spk_serial_out(synth->procspeech)) schedule_timeout( msecs_to_jiffies(delay_time_val)); else schedule_timeout( msecs_to_jiffies(full_time_val)); jiff_max = jiffies + jiffy_delta_val; } set_current_state(TASK_RUNNING); spk_lock(flags); synth_buffer_getc(); spk_unlock(flags); } spk_serial_out(synth->procspeech); }
static void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; struct { u_short buf[128]; cisparse_t parse; config_info_t conf; cistpl_cftable_entry_t dflt; } *stk = NULL; cistpl_cftable_entry_t *cfg; int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); stk = kmalloc(sizeof(*stk), GFP_KERNEL); if (!stk) goto err_mem; memset(stk, 0, sizeof(*stk)); cfg = &stk->parse.cftable_entry; tuple.TupleData = (cisdata_t *)&stk->buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); link->conf.ConfigBase = stk->parse.config.base; link->conf.Present = stk->parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); link->conf.Vcc = stk->conf.Vcc; pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) goto next_entry; } } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; if (!(io->flags & CISTPL_IO_16BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; if (io->nwin == 2) { link->io.NumPorts1 = 8; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = (is_kme) ? 2 : 1; if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort2; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { link->io.NumPorts1 = io->win[0].len; link->io.NumPorts2 = 0; if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort1 + 0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); /* disable drive interrupts during IDE probe */ outb(0x02, ctl_base); /* special setup for KXLC005 card */ if (is_kme) outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); hd = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ); if (hd >= 0) { io_base += 0x10; ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } if (hd < 0) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, link->irq.AssignedIRQ); goto failed; } info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); link->state &= ~DEV_CONFIG_PENDING; kfree(stk); return; err_mem: printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); goto failed; cs_failed: cs_error(link->handle, last_fn, last_ret); failed: kfree(stk); ide_release(link); link->state &= ~DEV_CONFIG_PENDING; } /* ide_config */
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock) { struct sock *sk; int len = skb->len; int protocol = ssk->protocol; long timeo; DECLARE_WAITQUEUE(wait, current); timeo = sock_sndtimeo(ssk, nonblock); retry: sk = netlink_lookup(protocol, pid); if (sk == NULL) goto no_dst; /* Don't bother queuing skb if kernel socket has no input function */ if (sk->protinfo.af_netlink->pid == 0 && !sk->protinfo.af_netlink->data_ready) goto no_dst; #ifdef NL_EMULATE_DEV if (sk->protinfo.af_netlink->handler) { skb_orphan(skb); len = sk->protinfo.af_netlink->handler(protocol, skb); sock_put(sk); return len; } #endif if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf || test_bit(0, &sk->protinfo.af_netlink->state)) { if (!timeo) { if (ssk->protinfo.af_netlink->pid == 0) netlink_overrun(sk); sock_put(sk); kfree_skb(skb); return -EAGAIN; } __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&sk->protinfo.af_netlink->wait, &wait); if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf || test_bit(0, &sk->protinfo.af_netlink->state)) && !sk->dead) timeo = schedule_timeout(timeo); __set_current_state(TASK_RUNNING); remove_wait_queue(&sk->protinfo.af_netlink->wait, &wait); sock_put(sk); if (signal_pending(current)) { kfree_skb(skb); return sock_intr_errno(timeo); } goto retry; } skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->receive_queue, skb); sk->data_ready(sk, len); sock_put(sk); return len; no_dst: kfree_skb(skb); return -ECONNREFUSED; }
/** * @param interface * @param id * * @returns 0 if all is OK * * @brief Load the driver * * This function detects the device and allocate the buffers for the device * and the video interface. */ static int usb_linect_probe(struct usb_interface *interface, const struct usb_device_id *id) { int err; int vendor_id; int product_id; int webcam_model; int tmpi, try, found; struct usb_linect *dev = NULL; struct usb_device *udev = interface_to_usbdev(interface); // Get USB VendorID and ProductID vendor_id = le16_to_cpu(udev->descriptor.idVendor); product_id = le16_to_cpu(udev->descriptor.idProduct); // Check if we can handle this device LNT_DEBUG("Probe function called with VendorID=%04X, ProductID=%04X and InterfaceNumber=%d\n", vendor_id, product_id, interface->cur_altsetting->desc.bInterfaceNumber); if (interface->cur_altsetting->desc.bInterfaceNumber > 0) return -ENODEV; // Detect device if (vendor_id == USB_MS_VENDOR_ID) { switch (product_id) { case USB_K1414_PRODUCT_ID: LNT_INFO("MS Kinect Model 1414 found.\n"); webcam_model = KNT_K1414; break; case USB_K1414_MOTOR_PRODUCT_ID: // Motor LNT_DEBUG("Kinect Motor found.\n"); tmpi = -1; found = 0; try = 10; while(1) { mutex_lock(&modlock_tmpmotor); if (tmp_motor_dev == NULL) { tmp_motor_dev = udev; tmp_motor_index = kindex++; LNT_DEBUG("Got number %d current %d.\n", tmp_motor_index, kindex); tmpi = tmp_motor_index; found = 1; mutex_unlock(&modlock_tmpmotor); break; } mutex_unlock(&modlock_tmpmotor); schedule_timeout(50); try--; if (try == 0) break; } if (!found) { LNT_INFO("Kinect unplugged. Please connect the Kinect power source.\n"); return -ENODEV;} dev = kzalloc(sizeof(struct usb_linect), GFP_KERNEL); if (dev == NULL) { LNT_ERROR("Out of memory !\n"); return -ENOMEM; } dev->type = KNT_TYPE_MOTOR; dev->index = tmpi; dev->motor_udev = udev; // Proc linect_proc_create(dev); mutex_lock(&modlock_tmpmotor); nmotors++; mutex_unlock(&modlock_tmpmotor); LNT_DEBUG("Kinect Motor ready.\n"); usb_set_intfdata(interface, dev); return 0; break; default: LNT_ERROR("usb_linect_probe failed ! Kinect product 0x%04X is not supported.\n", le16_to_cpu(udev->descriptor.idProduct)); return -ENODEV; } } else return -ENODEV; // Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device dev = kzalloc(sizeof(struct usb_linect), GFP_KERNEL); if (dev == NULL) { LNT_ERROR("Out of memory !\n"); return -ENOMEM; } dev->cam = kzalloc(sizeof(struct linect_cam), GFP_KERNEL); if (dev->cam == NULL) { LNT_ERROR("Out of memory !\n"); return -ENOMEM; } // Init mutexes, spinlock, etc. sema_init(&dev->cam->mutex_rgb, 1); sema_init(&dev->cam->mutex_depth, 1); mutex_init(&dev->mutex_motor); mutex_init(&dev->cam->mutex_cam); mutex_init(&dev->cam->modlock_rgb); mutex_init(&dev->cam->modlock_depth); spin_lock_init(&dev->cam->spinlock_rgb); spin_lock_init(&dev->cam->spinlock_depth); init_waitqueue_head(&dev->cam->wait_rgb_frame); init_waitqueue_head(&dev->cam->wait_depth_frame); // Save pointers dev->cam->webcam_model = webcam_model; dev->cam->udev = udev; dev->cam->interface = interface; // Read the product release dev->cam->release = le16_to_cpu(udev->descriptor.bcdDevice); LNT_INFO("Release: %04x\n", dev->cam->release); // Constructor dev->cam->nbuffers = 2; dev->cam->len_per_image = PAGE_ALIGN((640 * 480 * 4)); dev->cam->nbuffers_depth = 2; dev->cam->len_per_image_depth = PAGE_ALIGN((640 * 480 * 4)); // Get Motor while(1) { mutex_lock(&modlock_tmpmotor); if (tmp_motor_dev != NULL) { dev->motor_udev = tmp_motor_dev; LNT_DEBUG("Got Kinect motor ref to dev!\n"); tmp_motor_dev = NULL; dev->index = tmp_motor_index; tmp_motor_index = -1; mutex_unlock(&modlock_tmpmotor); break; } mutex_unlock(&modlock_tmpmotor); } // Params dev->freemotor = freemotor ? 1 : 0; dev->freeled = freeled ? 1 : 0; dev->cam->startupinit = startupinit ? 1 : 0; dev->type = KNT_TYPE_CAM; // Led if (!dev->freeled) linect_motor_set_led(dev, LED_GREEN); // Reset motor if (!dev->freemotor) linect_motor_set_tilt_degs(dev, 0); // TODO: Remove V4L2 deps and replace by some other video output mechanism... // V4L2 !! /* // Initialize the video device dev->cam->vdev = video_device_alloc(); dev->cam->depth_vdev = video_device_alloc(); if (!dev->cam->vdev) { kfree(dev); return -ENOMEM; } if (!dev->cam->depth_vdev) { kfree(dev); return -ENOMEM; }*/ // Initialize the camera linect_cam_init(dev); /* // Register the video device err = v4l_linect_register_rgb_video_device(dev); if (err) { kfree(dev); return err; } err = v4l_linect_register_depth_video_device(dev); if (err) { kfree(dev); return err; }*/ // Save our data pointer in this interface device usb_set_intfdata(interface, dev); // Default settings video device usb_linect_default_settings(dev); return 0; }