| 101 | } |
| 102 | |
| 103 | static rt_err_t nvme_submit_cmd(struct rt_nvme_queue *queue, |
| 104 | struct rt_nvme_command *cmd) |
| 105 | { |
| 106 | rt_ubase_t level; |
| 107 | rt_err_t err = RT_EOK; |
| 108 | rt_uint16_t tail, head; |
| 109 | struct rt_nvme_controller *nvme = queue->nvme; |
| 110 | |
| 111 | _retry: |
| 112 | level = rt_spin_lock_irqsave(&queue->lock); |
| 113 | |
| 114 | tail = queue->sq_tail; |
| 115 | head = queue->cq_head; |
| 116 | |
| 117 | if (tail + 1 == head) |
| 118 | { |
| 119 | /* IO queue is full, waiting for the last IO command to complete. */ |
| 120 | rt_spin_unlock_irqrestore(&queue->lock, level); |
| 121 | |
| 122 | rt_thread_yield(); |
| 123 | |
| 124 | goto _retry; |
| 125 | } |
| 126 | |
| 127 | cmd->common.cmdid = nvme_next_cmdid(nvme); |
| 128 | rt_memcpy(&queue->sq_cmds[tail], cmd, sizeof(*cmd)); |
| 129 | |
| 130 | if (nvme->ops->submit_cmd) |
| 131 | { |
| 132 | if ((err = nvme->ops->submit_cmd(queue, cmd))) |
| 133 | { |
| 134 | return err; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | if (++tail == queue->depth) |
| 139 | { |
| 140 | tail = 0; |
| 141 | } |
| 142 | HWREG32(queue->doorbell) = tail; |
| 143 | queue->sq_tail = tail; |
| 144 | |
| 145 | queue->cmd = cmd; |
| 146 | queue->err = RT_EOK; |
| 147 | |
| 148 | rt_spin_unlock_irqrestore(&queue->lock, level); |
| 149 | |
| 150 | err = rt_completion_wait(&queue->done, |
| 151 | rt_tick_from_millisecond(queue->qid != 0 ? RT_WAITING_FOREVER : 60)); |
| 152 | |
| 153 | return err ? : queue->err; |
| 154 | } |
| 155 | |
| 156 | static rt_err_t nvme_set_features_simple(struct rt_nvme_controller *nvme, |
| 157 | rt_uint32_t fid, rt_uint32_t dword11) |
no test coverage detected