/* check for a space for a new command */ if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) {
dev_err(&pdev->dev, "API CMD chain %d is busy, cons_idx: %d, prod_idx: %d\n",
chain->chain_type, chain->cons_idx,
chain->prod_idx);
dump_api_chain_reg(chain); return -EBUSY;
} break;
default:
dev_err(&pdev->dev, "Unknown API CMD Chain type\n"); break;
}
return 0;
}
/** * get_cell_data_size - get the data size of a specific cell type * @type: chain type * * Return the data(Desc + Address) size in the cell
**/ static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type)
{
u8 cell_data_size = 0;
/** * prepare_cell_ctrl - prepare the ctrl of the cell for the command * @cell_ctrl: the control of the cell to set the control value into it * @data_size: the size of the data in the cell
**/ staticvoid prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size)
{
u8 chksum;
u64 ctrl;
val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);
val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART);
hinic_hwif_write_reg(hwif, reg_addr, val);
end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT); do {
val = hinic_hwif_read_reg(hwif, reg_addr);
if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {
err = 0; break;
}
msleep(20);
} while (time_before(jiffies, end));
return err;
}
/** * api_cmd_ctrl_init - set the control register of a chain * @chain: the API CMD specific chain to set control register for
**/ staticvoid api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain)
{ struct hinic_hwif *hwif = chain->hwif;
u32 addr, ctrl;
u16 cell_size;
/** * api_cmd_set_status_addr - set the status address of a chain in the HW * @chain: the API CMD specific chain to set in HW status address for
**/ staticvoid api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain)
{ struct hinic_hwif *hwif = chain->hwif;
u32 addr, val;
addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);
val = upper_32_bits(chain->wb_status_paddr);
hinic_hwif_write_reg(hwif, addr, val);
addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);
val = lower_32_bits(chain->wb_status_paddr);
hinic_hwif_write_reg(hwif, addr, val);
}
/** * api_cmd_set_num_cells - set the number cells of a chain in the HW * @chain: the API CMD specific chain to set in HW the number of cells for
**/ staticvoid api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain)
{ struct hinic_hwif *hwif = chain->hwif;
u32 addr, val;
addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);
val = chain->num_cells;
hinic_hwif_write_reg(hwif, addr, val);
}
/** * api_cmd_head_init - set the head of a chain in the HW * @chain: the API CMD specific chain to set in HW the head for
**/ staticvoid api_cmd_head_init(struct hinic_api_cmd_chain *chain)
{ struct hinic_hwif *hwif = chain->hwif;
u32 addr, val;
addr = HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);
val = upper_32_bits(chain->head_cell_paddr);
hinic_hwif_write_reg(hwif, addr, val);
addr = HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);
val = lower_32_bits(chain->head_cell_paddr);
hinic_hwif_write_reg(hwif, addr, val);
}
/** * api_cmd_chain_hw_clean - clean the HW * @chain: the API CMD specific chain
**/ staticvoid api_cmd_chain_hw_clean(struct hinic_api_cmd_chain *chain)
{ struct hinic_hwif *hwif = chain->hwif;
u32 addr, ctrl;
/** * free_cmd_buf - free the dma buffer of API CMD command * @chain: the API CMD specific chain of the cmd * @cell_idx: the cell index of the cmd
**/ staticvoid free_cmd_buf(struct hinic_api_cmd_chain *chain, int cell_idx)
{ struct hinic_api_cmd_cell_ctxt *cell_ctxt; struct hinic_hwif *hwif = chain->hwif; struct pci_dev *pdev = hwif->pdev;
/** * alloc_cmd_buf - allocate a dma buffer for API CMD command * @chain: the API CMD specific chain for the cmd * @cell: the cell in the HW for the cmd * @cell_idx: the index of the cell * * Return 0 - Success, negative - Failure
**/ staticint alloc_cmd_buf(struct hinic_api_cmd_chain *chain, struct hinic_api_cmd_cell *cell, int cell_idx)
{ struct hinic_api_cmd_cell_ctxt *cell_ctxt; struct hinic_hwif *hwif = chain->hwif; struct pci_dev *pdev = hwif->pdev;
dma_addr_t cmd_paddr;
u8 *cmd_vaddr; int err = 0;
cmd_vaddr = dma_alloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
&cmd_paddr, GFP_KERNEL); if (!cmd_vaddr) return -ENOMEM;
/* set the cmd DMA address in the cell */ switch (chain->chain_type) { case HINIC_API_CMD_WRITE_TO_MGMT_CPU: /* The data in the HW should be in Big Endian Format */
cell->write.hw_cmd_paddr = cpu_to_be64(cmd_paddr); break;
/** * api_cmd_create_cell - create API CMD cell for specific chain * @chain: the API CMD specific chain to create its cell * @cell_idx: the index of the cell to create * @pre_node: previous cell * @node_vaddr: the returned virt addr of the cell * * Return 0 - Success, negative - Failure
**/ staticint api_cmd_create_cell(struct hinic_api_cmd_chain *chain, int cell_idx, struct hinic_api_cmd_cell *pre_node, struct hinic_api_cmd_cell **node_vaddr)
{ struct hinic_api_cmd_cell_ctxt *cell_ctxt; struct hinic_hwif *hwif = chain->hwif; struct pci_dev *pdev = hwif->pdev; struct hinic_api_cmd_cell *node;
dma_addr_t node_paddr; int err;
node = dma_alloc_coherent(&pdev->dev, chain->cell_size, &node_paddr,
GFP_KERNEL); if (!node) return -ENOMEM;
if (!pre_node) {
chain->head_cell_paddr = node_paddr;
chain->head_node = node;
} else { /* The data in the HW should be in Big Endian Format */
pre_node->next_cell_paddr = cpu_to_be64(node_paddr);
}
switch (chain->chain_type) { case HINIC_API_CMD_WRITE_TO_MGMT_CPU:
err = alloc_cmd_buf(chain, node, cell_idx); if (err) {
dev_err(&pdev->dev, "Failed to allocate cmd buffer\n"); goto err_alloc_cmd_buf;
} break;
/** * api_cmd_destroy_cells - destroy API CMD cells of specific chain * @chain: the API CMD specific chain to destroy its cells * @num_cells: number of cells to destroy
**/ staticvoid api_cmd_destroy_cells(struct hinic_api_cmd_chain *chain, int num_cells)
{ int cell_idx;
/** * api_cmd_destroy_chain - destroy API CMD specific chain * @chain: the API CMD specific chain to destroy
**/ staticvoid api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain)
{
api_cmd_chain_hw_clean(chain);
api_cmd_destroy_cells(chain, chain->num_cells);
api_chain_free(chain);
}
/** * hinic_api_cmd_init - Initialize all the API CMD chains * @chain: the API CMD chains that are initialized * @hwif: the hardware interface of a pci function device * * Return 0 - Success, negative - Failure
**/ int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain, struct hinic_hwif *hwif)
{ enum hinic_api_cmd_chain_type type, chain_type; struct hinic_api_cmd_chain_attr attr; struct pci_dev *pdev = hwif->pdev;
size_t hw_cell_sz; int err;
if (chain_type != HINIC_API_CMD_WRITE_TO_MGMT_CPU) continue;
chain[chain_type] = api_cmd_create_chain(&attr); if (IS_ERR(chain[chain_type])) {
dev_err(&pdev->dev, "Failed to create chain %d\n",
chain_type);
err = PTR_ERR(chain[chain_type]); goto err_create_chain;
}
}
return 0;
err_create_chain:
type = HINIC_API_CMD_WRITE_TO_MGMT_CPU; for ( ; type < chain_type; type++) { if (type != HINIC_API_CMD_WRITE_TO_MGMT_CPU) continue;
api_cmd_destroy_chain(chain[type]);
}
return err;
}
/** * hinic_api_cmd_free - free the API CMD chains * @chain: the API CMD chains that are freed
**/ void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain)
{ enum hinic_api_cmd_chain_type chain_type;
chain_type = HINIC_API_CMD_WRITE_TO_MGMT_CPU; for ( ; chain_type < HINIC_API_CMD_MAX; chain_type++) { if (chain_type != HINIC_API_CMD_WRITE_TO_MGMT_CPU) continue;
api_cmd_destroy_chain(chain[chain_type]);
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.