* idpf_ctlq_send - send command to Control Queue (CTQ) * @hw: pointer to hw struct * @cq: handle to control queue struct to send on * @num_q_msg: number of messages to send on control queue * @q_msg: pointer to array of queue messages to be sent * * The caller is expected to allocate DMAable buffers and pass them to the * send routine via the q_msg struct / control queue specific data struc
| 287 | * must be converted to LE before being written to the hw descriptor. |
| 288 | */ |
| 289 | int idpf_ctlq_send(struct idpf_hw *hw, struct idpf_ctlq_info *cq, |
| 290 | u16 num_q_msg, struct idpf_ctlq_msg q_msg[]) |
| 291 | { |
| 292 | struct idpf_ctlq_desc *desc; |
| 293 | int num_desc_avail = 0; |
| 294 | int status = 0; |
| 295 | int i = 0; |
| 296 | |
| 297 | if (!cq || !cq->ring_size) |
| 298 | return -ENOBUFS; |
| 299 | |
| 300 | idpf_acquire_lock(&cq->cq_lock); |
| 301 | |
| 302 | /* Ensure there are enough descriptors to send all messages */ |
| 303 | num_desc_avail = IDPF_CTLQ_DESC_UNUSED(cq); |
| 304 | if (num_desc_avail == 0 || num_desc_avail < num_q_msg) { |
| 305 | status = -ENOSPC; |
| 306 | goto sq_send_command_out; |
| 307 | } |
| 308 | |
| 309 | for (i = 0; i < num_q_msg; i++) { |
| 310 | struct idpf_ctlq_msg *msg = &q_msg[i]; |
| 311 | |
| 312 | desc = IDPF_CTLQ_DESC(cq, cq->next_to_use); |
| 313 | |
| 314 | desc->opcode = CPU_TO_LE16(msg->opcode); |
| 315 | desc->pfid_vfid = CPU_TO_LE16(msg->func_id); |
| 316 | |
| 317 | desc->cookie_high = CPU_TO_LE32(msg->cookie.mbx.chnl_opcode); |
| 318 | desc->cookie_low = CPU_TO_LE32(msg->cookie.mbx.chnl_retval); |
| 319 | |
| 320 | desc->flags = CPU_TO_LE16((msg->host_id & IDPF_HOST_ID_MASK) << |
| 321 | IDPF_CTLQ_FLAG_HOST_ID_S); |
| 322 | if (msg->data_len) { |
| 323 | struct idpf_dma_mem *buff = msg->ctx.indirect.payload; |
| 324 | |
| 325 | desc->datalen |= CPU_TO_LE16(msg->data_len); |
| 326 | desc->flags |= CPU_TO_LE16(IDPF_CTLQ_FLAG_BUF); |
| 327 | desc->flags |= CPU_TO_LE16(IDPF_CTLQ_FLAG_RD); |
| 328 | |
| 329 | /* Update the address values in the desc with the pa |
| 330 | * value for respective buffer |
| 331 | */ |
| 332 | desc->params.indirect.addr_high = |
| 333 | CPU_TO_LE32(IDPF_HI_DWORD(buff->pa)); |
| 334 | desc->params.indirect.addr_low = |
| 335 | CPU_TO_LE32(IDPF_LO_DWORD(buff->pa)); |
| 336 | |
| 337 | idpf_memcpy(&desc->params, msg->ctx.indirect.context, |
| 338 | IDPF_INDIRECT_CTX_SIZE, IDPF_NONDMA_TO_DMA); |
| 339 | #ifdef SIMICS_BUILD |
| 340 | /* MBX message with opcode idpf_mbq_opc_send_msg_to_pf |
| 341 | * need to set peer PF function id in param0 for Simics |
| 342 | */ |
| 343 | if (msg->opcode == idpf_mbq_opc_send_msg_to_pf) { |
| 344 | desc->params.indirect.param0 = |
| 345 | CPU_TO_LE32(msg->func_id); |
| 346 | } |
no test coverage detected