static inline void mbox_send_request(struct mbox *m, struct octeontx_mbox_hdr *hdr, const void *txmsg, uint16_t txsize) { struct mbox_ram_hdr old_hdr; struct mbox_ram_hdr new_hdr = { {0} }; uint64_t *ram_mbox_hdr = (uint64_t *)m->ram_mbox_base; uint8_t *ram_mbox_msg = m->ram_mbox_base + sizeof(struct mbox_ram_hdr); /* * Initialize the channel with the tag left by last send. * On success full mbox send complete, PF increments the tag by one. * The sender can validate integrity of PF message with this scheme */ old_hdr.u64 = rte_read64(ram_mbox_hdr); m->tag_own = (old_hdr.tag + 2) & (~0x1ul); /* next even number */ /* Copy msg body */ if (txmsg) mbox_msgcpy(ram_mbox_msg, txmsg, txsize); /* Prepare new hdr */ new_hdr.chan_state = MBOX_CHAN_STATE_REQ; new_hdr.coproc = hdr->coproc; new_hdr.msg = hdr->msg; new_hdr.vfid = hdr->vfid; new_hdr.tag = m->tag_own; new_hdr.len = txsize; /* Write the msg header */ rte_write64(new_hdr.u64, ram_mbox_hdr); rte_smp_wmb(); /* Notify PF about the new msg - write to MBOX reg generates PF IRQ */ rte_write64(0, m->reg); }
/** * Process the received mbox message. */ int lio_mbox_process_message(struct lio_mbox *mbox) { struct lio_mbox_cmd mbox_cmd; if (mbox->state & LIO_MBOX_STATE_ERROR) { if (mbox->state & (LIO_MBOX_STATE_RES_PENDING | LIO_MBOX_STATE_RES_RECEIVING)) { rte_memcpy(&mbox_cmd, &mbox->mbox_resp, sizeof(struct lio_mbox_cmd)); mbox->state = LIO_MBOX_STATE_IDLE; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); mbox_cmd.recv_status = 1; if (mbox_cmd.fn) mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, mbox_cmd.fn_arg); return 0; } mbox->state = LIO_MBOX_STATE_IDLE; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); return 0; } if (mbox->state & LIO_MBOX_STATE_RES_RECEIVED) { rte_memcpy(&mbox_cmd, &mbox->mbox_resp, sizeof(struct lio_mbox_cmd)); mbox->state = LIO_MBOX_STATE_IDLE; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); mbox_cmd.recv_status = 0; if (mbox_cmd.fn) mbox_cmd.fn(mbox->lio_dev, &mbox_cmd, mbox_cmd.fn_arg); return 0; } if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVED) { rte_memcpy(&mbox_cmd, &mbox->mbox_req, sizeof(struct lio_mbox_cmd)); if (!mbox_cmd.msg.s.resp_needed) { mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVED; if (!(mbox->state & LIO_MBOX_STATE_RES_PENDING)) mbox->state = LIO_MBOX_STATE_IDLE; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); } lio_mbox_process_cmd(mbox, &mbox_cmd); return 0; } RTE_ASSERT(0); return 0; }
static void cn23xx_vf_setup_iq_regs(struct lio_device *lio_dev, uint32_t iq_no) { struct lio_instr_queue *iq = lio_dev->instr_queue[iq_no]; uint64_t pkt_in_done = 0; PMD_INIT_FUNC_TRACE(); /* Write the start of the input queue's ring and its size */ lio_write_csr64(lio_dev, CN23XX_SLI_IQ_BASE_ADDR64(iq_no), iq->base_addr_dma); lio_write_csr(lio_dev, CN23XX_SLI_IQ_SIZE(iq_no), iq->max_count); /* Remember the doorbell & instruction count register addr * for this queue */ iq->doorbell_reg = (uint8_t *)lio_dev->hw_addr + CN23XX_SLI_IQ_DOORBELL(iq_no); iq->inst_cnt_reg = (uint8_t *)lio_dev->hw_addr + CN23XX_SLI_IQ_INSTR_COUNT64(iq_no); lio_dev_dbg(lio_dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n", iq_no, iq->doorbell_reg, iq->inst_cnt_reg); /* Store the current instruction counter (used in flush_iq * calculation) */ pkt_in_done = rte_read64(iq->inst_cnt_reg); /* Clear the count by writing back what we read, but don't * enable data traffic here */ rte_write64(pkt_in_done, iq->inst_cnt_reg); }
void cn23xx_vf_handle_mbox(struct lio_device *lio_dev) { uint64_t mbox_int_val; /* read and clear by writing 1 */ mbox_int_val = rte_read64(lio_dev->mbox[0]->mbox_int_reg); rte_write64(mbox_int_val, lio_dev->mbox[0]->mbox_int_reg); if (lio_mbox_read(lio_dev->mbox[0])) lio_mbox_process_message(lio_dev->mbox[0]); }
static int cn23xx_vf_setup_mbox(struct lio_device *lio_dev) { struct lio_mbox *mbox; PMD_INIT_FUNC_TRACE(); if (lio_dev->mbox == NULL) { lio_dev->mbox = rte_zmalloc(NULL, sizeof(void *), 0); if (lio_dev->mbox == NULL) return -ENOMEM; } mbox = rte_zmalloc(NULL, sizeof(struct lio_mbox), 0); if (mbox == NULL) { rte_free(lio_dev->mbox); lio_dev->mbox = NULL; return -ENOMEM; } rte_spinlock_init(&mbox->lock); mbox->lio_dev = lio_dev; mbox->q_no = 0; mbox->state = LIO_MBOX_STATE_IDLE; /* VF mbox interrupt reg */ mbox->mbox_int_reg = (uint8_t *)lio_dev->hw_addr + CN23XX_VF_SLI_PKT_MBOX_INT(0); /* VF reads from SIG0 reg */ mbox->mbox_read_reg = (uint8_t *)lio_dev->hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 0); /* VF writes into SIG1 reg */ mbox->mbox_write_reg = (uint8_t *)lio_dev->hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 1); lio_dev->mbox[0] = mbox; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); return 0; }
/** * lio_mbox_read: * @mbox: Pointer mailbox * * Reads the 8-bytes of data from the mbox register * Writes back the acknowledgment indicating completion of read */ int lio_mbox_read(struct lio_mbox *mbox) { union lio_mbox_message msg; int ret = 0; msg.mbox_msg64 = rte_read64(mbox->mbox_read_reg); if ((msg.mbox_msg64 == LIO_PFVFACK) || (msg.mbox_msg64 == LIO_PFVFSIG)) return 0; if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) { mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.mbox_msg64; mbox->mbox_req.recv_len++; } else { if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) { mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] = msg.mbox_msg64; mbox->mbox_resp.recv_len++; } else { if ((mbox->state & LIO_MBOX_STATE_IDLE) && (msg.s.type == LIO_MBOX_REQUEST)) { mbox->state &= ~LIO_MBOX_STATE_IDLE; mbox->state |= LIO_MBOX_STATE_REQ_RECEIVING; mbox->mbox_req.msg.mbox_msg64 = msg.mbox_msg64; mbox->mbox_req.q_no = mbox->q_no; mbox->mbox_req.recv_len = 1; } else { if ((mbox->state & LIO_MBOX_STATE_RES_PENDING) && (msg.s.type == LIO_MBOX_RESPONSE)) { mbox->state &= ~LIO_MBOX_STATE_RES_PENDING; mbox->state |= LIO_MBOX_STATE_RES_RECEIVING; mbox->mbox_resp.msg.mbox_msg64 = msg.mbox_msg64; mbox->mbox_resp.q_no = mbox->q_no; mbox->mbox_resp.recv_len = 1; } else { rte_write64(LIO_PFVFERR, mbox->mbox_read_reg); mbox->state |= LIO_MBOX_STATE_ERROR; return -1; } } } } if (mbox->state & LIO_MBOX_STATE_REQ_RECEIVING) { if (mbox->mbox_req.recv_len < msg.s.len) { ret = 0; } else { mbox->state &= ~LIO_MBOX_STATE_REQ_RECEIVING; mbox->state |= LIO_MBOX_STATE_REQ_RECEIVED; ret = 1; } } else { if (mbox->state & LIO_MBOX_STATE_RES_RECEIVING) { if (mbox->mbox_resp.recv_len < msg.s.len) { ret = 0; } else { mbox->state &= ~LIO_MBOX_STATE_RES_RECEIVING; mbox->state |= LIO_MBOX_STATE_RES_RECEIVED; ret = 1; } } else { RTE_ASSERT(0); } } rte_write64(LIO_PFVFACK, mbox->mbox_read_reg); return ret; }
/** * lio_mbox_write: * @lio_dev: Pointer lio device * @mbox_cmd: Cmd to send to mailbox. * * Populates the queue specific mbox structure * with cmd information. * Write the cmd to mbox register */ int lio_mbox_write(struct lio_device *lio_dev, struct lio_mbox_cmd *mbox_cmd) { struct lio_mbox *mbox = lio_dev->mbox[mbox_cmd->q_no]; uint32_t count, i, ret = LIO_MBOX_STATUS_SUCCESS; if ((mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) && !(mbox->state & LIO_MBOX_STATE_REQ_RECEIVED)) return LIO_MBOX_STATUS_FAILED; if ((mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) && !(mbox->state & LIO_MBOX_STATE_IDLE)) return LIO_MBOX_STATUS_BUSY; if (mbox_cmd->msg.s.type == LIO_MBOX_REQUEST) { rte_memcpy(&mbox->mbox_resp, mbox_cmd, sizeof(struct lio_mbox_cmd)); mbox->state = LIO_MBOX_STATE_RES_PENDING; } count = 0; while (rte_read64(mbox->mbox_write_reg) != LIO_PFVFSIG) { rte_delay_ms(1); if (count++ == 1000) { ret = LIO_MBOX_STATUS_FAILED; break; } } if (ret == LIO_MBOX_STATUS_SUCCESS) { rte_write64(mbox_cmd->msg.mbox_msg64, mbox->mbox_write_reg); for (i = 0; i < (uint32_t)(mbox_cmd->msg.s.len - 1); i++) { count = 0; while (rte_read64(mbox->mbox_write_reg) != LIO_PFVFACK) { rte_delay_ms(1); if (count++ == 1000) { ret = LIO_MBOX_STATUS_FAILED; break; } } rte_write64(mbox_cmd->data[i], mbox->mbox_write_reg); } } if (mbox_cmd->msg.s.type == LIO_MBOX_RESPONSE) { mbox->state = LIO_MBOX_STATE_IDLE; rte_write64(LIO_PFVFSIG, mbox->mbox_read_reg); } else { if ((!mbox_cmd->msg.s.resp_needed) || (ret == LIO_MBOX_STATUS_FAILED)) { mbox->state &= ~LIO_MBOX_STATE_RES_PENDING; if (!(mbox->state & (LIO_MBOX_STATE_REQ_RECEIVING | LIO_MBOX_STATE_REQ_RECEIVED))) mbox->state = LIO_MBOX_STATE_IDLE; } } return ret; }