Commit 3d7c8206 authored by Srikanth Jampala's avatar Srikanth Jampala Committed by Herbert Xu

crypto: cavium/nitrox - fix for command corruption in queue full case with backlog submissions.

Earlier used to post the current command without checking queue full
     after backlog submissions. So, post the current command only after
     confirming the space in queue after backlog submissions.

     Maintain host write index instead of reading device registers
     to get the next free slot to post the command.

     Return -ENOSPC in queue full case.
Signed-off-by: default avatarSrikanth Jampala <Jampala.Srikanth@cavium.com>
Reviewed-by: default avatarGadam Sreerama <sgadam@cavium.com>
Tested-by: default avatarJha, Chandan <Chandan.Jha@cavium.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0522236d
...@@ -35,6 +35,7 @@ struct nitrox_cmdq { ...@@ -35,6 +35,7 @@ struct nitrox_cmdq {
/* requests in backlog queues */ /* requests in backlog queues */
atomic_t backlog_count; atomic_t backlog_count;
int write_idx;
/* command size 32B/64B */ /* command size 32B/64B */
u8 instr_size; u8 instr_size;
u8 qno; u8 qno;
...@@ -87,7 +88,7 @@ struct nitrox_bh { ...@@ -87,7 +88,7 @@ struct nitrox_bh {
struct bh_data *slc; struct bh_data *slc;
}; };
/* NITROX-5 driver state */ /* NITROX-V driver state */
#define NITROX_UCODE_LOADED 0 #define NITROX_UCODE_LOADED 0
#define NITROX_READY 1 #define NITROX_READY 1
......
...@@ -36,6 +36,7 @@ static int cmdq_common_init(struct nitrox_cmdq *cmdq) ...@@ -36,6 +36,7 @@ static int cmdq_common_init(struct nitrox_cmdq *cmdq)
cmdq->head = PTR_ALIGN(cmdq->head_unaligned, PKT_IN_ALIGN); cmdq->head = PTR_ALIGN(cmdq->head_unaligned, PKT_IN_ALIGN);
cmdq->dma = PTR_ALIGN(cmdq->dma_unaligned, PKT_IN_ALIGN); cmdq->dma = PTR_ALIGN(cmdq->dma_unaligned, PKT_IN_ALIGN);
cmdq->qsize = (qsize + PKT_IN_ALIGN); cmdq->qsize = (qsize + PKT_IN_ALIGN);
cmdq->write_idx = 0;
spin_lock_init(&cmdq->response_lock); spin_lock_init(&cmdq->response_lock);
spin_lock_init(&cmdq->cmdq_lock); spin_lock_init(&cmdq->cmdq_lock);
......
...@@ -42,6 +42,16 @@ ...@@ -42,6 +42,16 @@
* Invalid flag options in AES-CCM IV. * Invalid flag options in AES-CCM IV.
*/ */
static inline int incr_index(int index, int count, int max)
{
if ((index + count) >= max)
index = index + count - max;
else
index += count;
return index;
}
/** /**
* dma_free_sglist - unmap and free the sg lists. * dma_free_sglist - unmap and free the sg lists.
* @ndev: N5 device * @ndev: N5 device
...@@ -426,30 +436,29 @@ static void post_se_instr(struct nitrox_softreq *sr, ...@@ -426,30 +436,29 @@ static void post_se_instr(struct nitrox_softreq *sr,
struct nitrox_cmdq *cmdq) struct nitrox_cmdq *cmdq)
{ {
struct nitrox_device *ndev = sr->ndev; struct nitrox_device *ndev = sr->ndev;
union nps_pkt_in_instr_baoff_dbell pkt_in_baoff_dbell; int idx;
u64 offset;
u8 *ent; u8 *ent;
spin_lock_bh(&cmdq->cmdq_lock); spin_lock_bh(&cmdq->cmdq_lock);
/* get the next write offset */ idx = cmdq->write_idx;
offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(cmdq->qno);
pkt_in_baoff_dbell.value = nitrox_read_csr(ndev, offset);
/* copy the instruction */ /* copy the instruction */
ent = cmdq->head + pkt_in_baoff_dbell.s.aoff; ent = cmdq->head + (idx * cmdq->instr_size);
memcpy(ent, &sr->instr, cmdq->instr_size); memcpy(ent, &sr->instr, cmdq->instr_size);
/* flush the command queue updates */
dma_wmb();
sr->tstamp = jiffies;
atomic_set(&sr->status, REQ_POSTED); atomic_set(&sr->status, REQ_POSTED);
response_list_add(sr, cmdq); response_list_add(sr, cmdq);
sr->tstamp = jiffies;
/* flush the command queue updates */
dma_wmb();
/* Ring doorbell with count 1 */ /* Ring doorbell with count 1 */
writeq(1, cmdq->dbell_csr_addr); writeq(1, cmdq->dbell_csr_addr);
/* orders the doorbell rings */ /* orders the doorbell rings */
mmiowb(); mmiowb();
cmdq->write_idx = incr_index(idx, 1, ndev->qlen);
spin_unlock_bh(&cmdq->cmdq_lock); spin_unlock_bh(&cmdq->cmdq_lock);
} }
...@@ -459,6 +468,9 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) ...@@ -459,6 +468,9 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq)
struct nitrox_softreq *sr, *tmp; struct nitrox_softreq *sr, *tmp;
int ret = 0; int ret = 0;
if (!atomic_read(&cmdq->backlog_count))
return 0;
spin_lock_bh(&cmdq->backlog_lock); spin_lock_bh(&cmdq->backlog_lock);
list_for_each_entry_safe(sr, tmp, &cmdq->backlog_head, backlog) { list_for_each_entry_safe(sr, tmp, &cmdq->backlog_head, backlog) {
...@@ -466,7 +478,7 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) ...@@ -466,7 +478,7 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq)
/* submit until space available */ /* submit until space available */
if (unlikely(cmdq_full(cmdq, ndev->qlen))) { if (unlikely(cmdq_full(cmdq, ndev->qlen))) {
ret = -EBUSY; ret = -ENOSPC;
break; break;
} }
/* delete from backlog list */ /* delete from backlog list */
...@@ -491,23 +503,20 @@ static int nitrox_enqueue_request(struct nitrox_softreq *sr) ...@@ -491,23 +503,20 @@ static int nitrox_enqueue_request(struct nitrox_softreq *sr)
{ {
struct nitrox_cmdq *cmdq = sr->cmdq; struct nitrox_cmdq *cmdq = sr->cmdq;
struct nitrox_device *ndev = sr->ndev; struct nitrox_device *ndev = sr->ndev;
int ret = -EBUSY;
/* try to post backlog requests */
post_backlog_cmds(cmdq);
if (unlikely(cmdq_full(cmdq, ndev->qlen))) { if (unlikely(cmdq_full(cmdq, ndev->qlen))) {
if (!(sr->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) if (!(sr->flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
return -EAGAIN; return -ENOSPC;
/* add to backlog list */
backlog_list_add(sr, cmdq); backlog_list_add(sr, cmdq);
} else { return -EBUSY;
ret = post_backlog_cmds(cmdq);
if (ret) {
backlog_list_add(sr, cmdq);
return ret;
} }
post_se_instr(sr, cmdq); post_se_instr(sr, cmdq);
ret = -EINPROGRESS;
} return -EINPROGRESS;
return ret;
} }
/** /**
...@@ -624,11 +633,9 @@ int nitrox_process_se_request(struct nitrox_device *ndev, ...@@ -624,11 +633,9 @@ int nitrox_process_se_request(struct nitrox_device *ndev,
*/ */
sr->instr.fdata[0] = *((u64 *)&req->gph); sr->instr.fdata[0] = *((u64 *)&req->gph);
sr->instr.fdata[1] = 0; sr->instr.fdata[1] = 0;
/* flush the soft_req changes before posting the cmd */
wmb();
ret = nitrox_enqueue_request(sr); ret = nitrox_enqueue_request(sr);
if (ret == -EAGAIN) if (ret == -ENOSPC)
goto send_fail; goto send_fail;
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment