/* * Function: qp_wr_post * * Description: * This in-line function allocates a MQ msg, then moves the host-copy of * the completed WR into msg. Then it posts the message. * * IN: * q - ptr to user MQ. * wr - ptr to host-copy of the WR. * qp - ptr to user qp * size - Number of bytes to post. Assumed to be divisible by 4. * * OUT: none * * Return: * CCIL status codes. */ static int qp_wr_post(struct c2_mq *q, union c2wr * wr, struct c2_qp *qp, u32 size) { union c2wr *msg; msg = c2_mq_alloc(q); if (msg == NULL) { return -EINVAL; } #ifdef CCMSGMAGIC ((c2wr_hdr_t *) wr)->magic = cpu_to_be32(CCWR_MAGIC); #endif /* * Since all header fields in the WR are the same as the * CQE, set the following so the adapter need not. */ c2_wr_set_result(wr, CCERR_PENDING); /* * Copy the wr down to the adapter */ memcpy((void *) msg, (void *) wr, size); c2_mq_produce(q); return 0; }
int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr) { void *msg; wait_queue_t __wait; spin_lock(&c2dev->vqlock); msg = c2_mq_alloc(&c2dev->req_vq); while (msg == NULL) { pr_debug("%s:%d no available msg in VQ, waiting...\n", __func__, __LINE__); init_waitqueue_entry(&__wait, current); add_wait_queue(&c2dev->req_vq_wo, &__wait); spin_unlock(&c2dev->vqlock); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (!c2_mq_full(&c2dev->req_vq)) { break; } if (!signal_pending(current)) { schedule_timeout(1 * HZ); continue; } set_current_state(TASK_RUNNING); remove_wait_queue(&c2dev->req_vq_wo, &__wait); return -EINTR; } set_current_state(TASK_RUNNING); remove_wait_queue(&c2dev->req_vq_wo, &__wait); spin_lock(&c2dev->vqlock); msg = c2_mq_alloc(&c2dev->req_vq); } memcpy(msg, wr, c2dev->req_vq.msg_size); c2_mq_produce(&c2dev->req_vq); spin_unlock(&c2dev->vqlock); return 0; }
/* * vq_send_wr - post a verbs request message to the Verbs Request Queue. * If a message is not available in the MQ, then block until one is available. * NOTE: handle_mq() on the interrupt context will wake up threads blocked here. * When the adapter drains the Verbs Request Queue, * it inserts MQ index 0 in to the * adapter->host activity fifo and interrupts the host. */ int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr) { void *msg; wait_queue_t __wait; /* * grab adapter vq lock */ spin_lock(&c2dev->vqlock); /* * allocate msg */ msg = c2_mq_alloc(&c2dev->req_vq); /* * If we cannot get a msg, then we'll wait * When a messages are available, the int handler will wake_up() * any waiters. */ while (msg == NULL) { pr_debug("%s:%d no available msg in VQ, waiting...\n", __func__, __LINE__); init_waitqueue_entry(&__wait, current); add_wait_queue(&c2dev->req_vq_wo, &__wait); spin_unlock(&c2dev->vqlock); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (!c2_mq_full(&c2dev->req_vq)) { break; } if (!signal_pending(current)) { schedule_timeout(1 * HZ); /* 1 second... */ continue; } set_current_state(TASK_RUNNING); remove_wait_queue(&c2dev->req_vq_wo, &__wait); return -EINTR; } set_current_state(TASK_RUNNING); remove_wait_queue(&c2dev->req_vq_wo, &__wait); spin_lock(&c2dev->vqlock); msg = c2_mq_alloc(&c2dev->req_vq); } /* * copy wr into adapter msg */ memcpy(msg, wr, c2dev->req_vq.msg_size); /* * post msg */ c2_mq_produce(&c2dev->req_vq); /* * release adapter vq lock */ spin_unlock(&c2dev->vqlock); return 0; }