void c2_mq_produce(struct c2_mq *q) { BUG_ON(q->magic != C2_MQ_MAGIC); BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); if (!c2_mq_full(q)) { q->priv = (q->priv + 1) % q->q_size; q->hint_count++; /* Update peer's offset. */ __raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared); } }
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; }
void *c2_mq_alloc(struct c2_mq *q) { BUG_ON(q->magic != C2_MQ_MAGIC); BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); if (c2_mq_full(q)) { return NULL; } else { #ifdef DEBUG struct c2wr_hdr *m = (struct c2wr_hdr *) (q->msg_pool.host + q->priv * q->msg_size); #ifdef CCMSGMAGIC BUG_ON(m->magic != be32_to_cpu(~CCWR_MAGIC)); m->magic = cpu_to_be32(CCWR_MAGIC); #endif return m; #else return q->msg_pool.host + q->priv * q->msg_size; #endif } }
/* * 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; }