int modem_acquire_mmio(struct modemctl *mc)
{
	if (modem_request_mmio(mc) == 0)
		if (wait_event_interruptible(mc->wq, mmio_owner_p(mc))) {
			modem_release_mmio(mc, 0);
			return -ERESTARTSYS;
		}
	if (!modem_running(mc)) {
		modem_release_mmio(mc, 0);
		return -ENODEV;
	}
	return 0;
}
Example #2
0
/* 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;
	}
}
Example #3
0
/* 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;
	}
}
Example #4
0
int modem_acquire_mmio(struct modemctl *mc)
{
    if (modem_request_mmio(mc) == 0) {
        int ret = wait_event_interruptible_timeout(
                      mc->wq, mmio_owner_p(mc), 5 * HZ);
        if (ret <= 0) {
            modem_release_mmio(mc, 0);
            if (ret == 0) {
                pr_err("modem_acquire_mmio() TIMEOUT\n");
                return -ENODEV;
            } else {
                return -ERESTARTSYS;
            }
        }
    }
    if (!modem_running(mc)) {
        modem_release_mmio(mc, 0);
        return -ENODEV;
    }
    return 0;
}
Example #5
0
/* 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;
}