Esempio n. 1
0
/**
 * queue_cmd - Setup a chain of descriptors
 *
 * @priv:	 private data passed
 * @cmd_buf:     pointer to command buffer (to be removed)
 * @cmd_handle:  dma_addr_t pointer that holds the command
 * @cmd_len:     the size of the command buffer (to be removed)
 * @data_handle: dma_addr_t pointer to a data buffer
 * @data_len:    the size of the data buffer
 * @cmd_flags:   commands flags
 */
int queue_cmd(void *priv,
	      uint8_t *cmd_buf, dma_addr_t cmd_handle, int cmd_len,
	      dma_addr_t data, int data_len,
	      struct lba_cmd *cmd_flags)
{

	struct gpmi_perchip_data *g = priv;
	unsigned long flags;
	int idx;
	int ret = 0;
	struct stmp3xxx_dma_descriptor *chain ;
	int i;

	if (!g || !(cmd_buf || cmd_handle))
		BUG();

	spin_lock_irqsave(&g->lock, flags);

	/* Keep it for debug purpose */
	chain = g->d;
	for (i = g->d_tail; i < GPMI_DMA_MAX_CHAIN; i++) {
		chain[i].command->cmd = 0;
		chain[i].command->buf_ptr = 0;
	}
	/* End */

	if (!cmd_handle) {
		if (!cmd_buf)
			BUG();
		memcpy(g->cmd_buffer, cmd_buf, cmd_len);
		cmd_handle = g->cmd_buffer_handle;
	}

	idx = g->d_tail;
	chain = &g->d[idx];

	do {
		if (!cmd_flags)
			BUG();

		if (cmd_flags->flag & FE_W4R) {
			/* there seems to be HW BUG with W4R flag.
			 * IRQ controller hangs forever when it's combined
			 * with real operation.
			 */
			chain_w4r(chain, g->cs);
			chain++; idx++;
		}


		switch (cmd_flags->flag & F_MASK) {

		case F_CMD:
			chain_cmd(chain, cmd_handle, cmd_flags, g->cs);
			break;
		case F_DATA_READ:
			chain_read_data(chain, data, data_len,
					cmd_flags, g->cs);
			break;
		case F_DATA_WRITE:
			chain_write_data(chain, data, data_len,
					 cmd_flags, g->cs);
			break;
		default:{
			if (cmd_flags->flag & FE_END)
				goto out;
			else{
				printk(KERN_ERR "uknown cmd\n");
				BUG();
			}
		}
		}


		chain++; idx++;
		cmd_handle += cmd_flags->len;

		if (idx >= GPMI_DMA_MAX_CHAIN) {
			printk(KERN_ERR "to many chains; idx is 0x%x\n", idx);
			BUG();
		}

	} while (!((cmd_flags++)->flag & FE_END));

out:
	if (idx < GPMI_DMA_MAX_CHAIN) {
		ret = idx;
		g->d_tail = idx;
	}
	spin_unlock_irqrestore(g->lock, flags);

	return ret;

}
Esempio n. 2
0
static int create_table_and_chains(struct nftables_info *nft_info)
{
	struct mnl_socket *nl;
	struct nftnl_table *table;
	struct nftnl_chain *chain;
	int err;


	DBG("");

        err = socket_open_and_bind(&nl);
        if (err < 0)
		return err;

	/*
	 * Add table
	 * http://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
	 */

	/*
	 * # nft add table connman
	 */
	table = build_table(CONNMAN_TABLE, NFPROTO_IPV4);
	if (!table) {
		err = -ENOMEM;
		goto out;
	}

        err = table_cmd(nl, table, NFT_MSG_NEWTABLE, NFPROTO_IPV4,
			NLM_F_CREATE|NLM_F_ACK);
        if (err < 0)
                goto out;

	/*
	 * Add basic chains
	 * http://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains
	 */

	/*
	 * # nft add chain connman nat-prerouting		\
	 *	{ type nat hook prerouting priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_NAT_PRE, CONNMAN_TABLE,
				"nat", NF_INET_PRE_ROUTING, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

	/*
	 * # nft add chain connman nat-postrouting		\
	 *	{ type nat hook postrouting priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_NAT_POST, CONNMAN_TABLE,
				"nat", NF_INET_POST_ROUTING, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

	/*
	 * # nft add chain connman route-output		\
	 *	{ type route hook output priority 0 ; }
	 */
	chain = build_chain(CONNMAN_CHAIN_ROUTE_OUTPUT, CONNMAN_TABLE,
				"route", NF_INET_LOCAL_OUT, 0);
	if (!chain) {
		err = -ENOMEM;
		goto out;
	}

	err = chain_cmd(nl, chain, NFT_MSG_NEWCHAIN,
			NFPROTO_IPV4, NLM_F_CREATE | NLM_F_ACK,
			CALLBACK_RETURN_NONE, NULL);
	if (err < 0)
		goto out;

out:
	if (err)
		connman_warn("Failed to create basic chains: %s",
				strerror(-err));
	mnl_socket_close(nl);
	return err;
}