static int mmio_owner_p(struct modemctl *mc) { unsigned long flags; int ret; spin_lock_irqsave(&mc->lock, flags); ret = mc->mmio_owner || modem_offline(mc); spin_unlock_irqrestore(&mc->lock, flags); return ret; }
/* must be called with pipe->tx_lock held */ static int modem_pipe_send(struct m_pipe *pipe, struct modem_io *io) { char hdr[M_PIPE_MAX_HDR]; static char ftr = 0x7e; unsigned size; int ret; ret = pipe->push_header(io, hdr); if (ret) return ret; size = io->size + pipe->header_size + 1; if (io->size > 0x10000000) return -EINVAL; if (size >= (pipe->tx->size - 1)) return -EINVAL; for (;;) { ret = modem_acquire_mmio(pipe->mc); if (ret) return ret; modem_update_pipe(pipe); if (pipe->tx->avail >= size) { fifo_write(pipe->tx, hdr, pipe->header_size); fifo_write_user(pipe->tx, io->data, io->size); fifo_write(pipe->tx, &ftr, 1); modem_update_pipe(pipe); modem_release_mmio(pipe->mc, pipe->tx->bits); MODEM_COUNT(pipe->mc, pipe_tx); return 0; } pr_info("modem_pipe_send: wait for space\n"); MODEM_COUNT(pipe->mc, pipe_tx_delayed); modem_release_mmio(pipe->mc, 0); ret = wait_event_interruptible_timeout( pipe->mc->wq, (pipe->tx->avail >= size) || modem_offline(pipe->mc), 5 * HZ); if (ret == 0) return -ENODEV; if (ret < 0) return ret; } }
/* must be called with pipe->tx_lock held */ static int modem_pipe_send(struct m_pipe *pipe, struct modem_io *io) { char hdr[M_PIPE_MAX_HDR]; unsigned size; int ret; io->magic = 0xCAFECAFE; ret = pipe->push_header(io, hdr); if (ret) return ret; size = io->datasize + pipe->header_size; if (size > 0x1000 /*pipe->tx->size*/) { pr_err ("Trying to send bigger than 4kB frame - MULTIPACKET not implemented yet.\n"); return -EINVAL; } for (;;) { ret = modem_acquire_mmio(pipe->mc); if (ret) return ret; modem_update_pipe(pipe); if (pipe->tx->avail >= size) { fifo_write(pipe->tx, hdr, pipe->header_size); fifo_move_head(pipe->tx, pipe->header_size); fifo_write_user(pipe->tx, io->data, io->datasize); fifo_move_head(pipe->tx, SIZ_PACKET_BUFSIZE); modem_update_pipe(pipe); modem_release_mmio(pipe->mc, pipe->tx->bits); MODEM_COUNT(pipe->mc, pipe_tx); return 0; } pr_info("modem_pipe_send: wait for space\n"); MODEM_COUNT(pipe->mc, pipe_tx_delayed); modem_release_mmio(pipe->mc, 0); ret = wait_event_interruptible(pipe->mc->wq, (pipe->tx->avail >= size) || modem_offline(pipe->mc)); if (ret) return ret; } }
static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned long flags; struct m_pipe *pipe = filp->private_data; int ret; poll_wait(filp, &pipe->mc->wq, wait); spin_lock_irqsave(&pipe->mc->lock, flags); if (pipe->rx->avail || modem_offline(pipe->mc)) ret = POLLIN | POLLRDNORM; else ret = 0; spin_unlock_irqrestore(&pipe->mc->lock, flags); return ret; }