mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
[SCSI] ibmvfc: Fix command completion handling
Commands which are completed by the VIOS are placed on a CRQ in kernel memory for the ibmvfc driver to process. Each CRQ entry is 16 bytes. The ibmvfc driver reads the first 8 bytes to check if the entry is valid, then reads the next 8 bytes to get the handle, which is a pointer the completed command. This fixes an issue seen on Power 7 where the processor reordered the loads from memory, resulting in processing command completion with a stale handle. This could result in command timeouts, and also early completion of commands. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
859e816704
commit
f5832fa2f8
1 changed files with 6 additions and 0 deletions
|
@ -3013,6 +3013,7 @@ static struct ibmvfc_async_crq *ibmvfc_next_async_crq(struct ibmvfc_host *vhost)
|
|||
if (crq->valid & 0x80) {
|
||||
if (++async_crq->cur == async_crq->size)
|
||||
async_crq->cur = 0;
|
||||
rmb();
|
||||
} else
|
||||
crq = NULL;
|
||||
|
||||
|
@ -3035,6 +3036,7 @@ static struct ibmvfc_crq *ibmvfc_next_crq(struct ibmvfc_host *vhost)
|
|||
if (crq->valid & 0x80) {
|
||||
if (++queue->cur == queue->size)
|
||||
queue->cur = 0;
|
||||
rmb();
|
||||
} else
|
||||
crq = NULL;
|
||||
|
||||
|
@ -3083,12 +3085,14 @@ static void ibmvfc_tasklet(void *data)
|
|||
while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
|
||||
ibmvfc_handle_async(async, vhost);
|
||||
async->valid = 0;
|
||||
wmb();
|
||||
}
|
||||
|
||||
/* Pull all the valid messages off the CRQ */
|
||||
while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
|
||||
ibmvfc_handle_crq(crq, vhost);
|
||||
crq->valid = 0;
|
||||
wmb();
|
||||
}
|
||||
|
||||
vio_enable_interrupts(vdev);
|
||||
|
@ -3096,10 +3100,12 @@ static void ibmvfc_tasklet(void *data)
|
|||
vio_disable_interrupts(vdev);
|
||||
ibmvfc_handle_async(async, vhost);
|
||||
async->valid = 0;
|
||||
wmb();
|
||||
} else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
|
||||
vio_disable_interrupts(vdev);
|
||||
ibmvfc_handle_crq(crq, vhost);
|
||||
crq->valid = 0;
|
||||
wmb();
|
||||
} else
|
||||
done = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue