0

在 linux-5.4/drivers/nvme/host/pci.c 中,我创建了一个并希望使用以下行nvme_command将此命令写入:nvmeq->sq_cmds[nvmeq->sq_tail]

memcpy(&nvmeq->sq_cmds[nvmeq->sq_tail], &cmd, sizeof(cmd));

但是当printknvmeq->sq_cmds[nvmeq->sq_tail]. (3次有正确数据,但大部分时间没有数据)

首先,因为我绕过了块层,所以我创建了PER_CPU变量并得到了nvme_queue执行的时间nvme_alloc_queue()。我曾经怀疑原因是 nvme_queue没有成功获取到,但是我可以printk每个队列的nvmeq->qidnvmeq->q_depth。所以我排除了这个原因。

以下是我的代码:

DEFINE_PER_CPU(struct nvme_queue *, nvme_irq_queues);
......


static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth) {
  ......
  if (qid > 0) {
        struct nvme_queue **per_cpu_queue = &per_cpu(nvme_irq_queues, qid - 1);
        *per_cpu_queue = nvmeq;
        printk(KERN_ERR "[EBIO %s] NVMe interrupt queue: %p cpu: %d qid: %d depth: %d\n", __func__, nvmeq, qid - 1, qid, depth);
  }
  ......
}


int nvme_fine_granu_read(struct ebio *ebio) {
  struct nvme_queue *nvmeq = get_cpu_var(nvme_irq_queues);
  struct nvme_command cmd;
  union CSD_cmd_u csd_cmd;
  struct nvme_ns *ns = list_entry(nvmeq->dev->ctrl.namespaces.next, struct nvme_ns, list);
  
  memset(&cmd, 0, sizeof(cmd));

  csd_cmd.recordRead.header.opCode = E_CSD_CMD_OPCODE_RECORD_READ;
  csd_cmd.recordRead.strLbn = nvme_block_nr(ns, ebio->block);
  csd_cmd.recordRead.recordInfoAdrOfs = 0;

  cmd.common.opcode = 0xd0;
  cmd.common.command_id = ebio_tag(ebio) | NVME_FINE_GRANU;
  cmd.common.nsid = cpu_to_le32(ns->head->ns_id);
  cmd.common.cdw12 = cpu_to_le32(csd_cmd.data[0]);
  cmd.common.cdw13 = cpu_to_le32(csd_cmd.data[1]);
  cmd.common.cdw14 = cpu_to_le32(csd_cmd.data[2]);
  cmd.common.cdw15 = cpu_to_le32(csd_cmd.data[3]);
    
  spin_lock_irq(&nvmeq->sq_lock);
  memcpy(&nvmeq->sq_cmds[nvmeq->sq_tail], &cmd, sizeof(cmd));
  if (++nvmeq->sq_tail == nvmeq->q_depth)
        nvmeq->sq_tail = 0;
  if (nvme_dbbuf_update_and_check_event(nvmeq->sq_tail, nvmeq->dbbuf_sq_db, nvmeq->dbbuf_sq_ei))
        writel(nvmeq->sq_tail, nvmeq->q_db);
  nvmeq->last_sq_tail = nvmeq->sq_tail;
  spin_unlock_irq(&nvmeq->sq_lock);

  put_cpu_var(nvme_irq_queues);

  return 0;
}

printk的每个成员我都可以cmd,所以写的nvme_command是正确的,但是memcpy操作memcpy(&nvmeq->sq_cmds[nvmeq->sq_tail], &cmd, sizeof(cmd));失败了。

4

0 回答 0