/** * 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; }
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; }