/* 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; } }
/* 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->rx_lock held */ static int modem_pipe_recv(struct m_pipe *pipe, struct modem_io *io) { int ret; ret = modem_acquire_mmio(pipe->mc); if (ret) return ret; ret = modem_pipe_read(pipe, io); modem_update_pipe(pipe); if ((ret != 0) && (ret != -EAGAIN)) { pr_err("[MODEM] purging %s fifo\n", pipe->dev.name); fifo_purge(pipe->rx); MODEM_COUNT(pipe->mc, pipe_rx_purged); } else if (ret == 0) { MODEM_COUNT(pipe->mc, pipe_rx); } modem_release_mmio(pipe->mc, 0); return ret; }