Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Brian King and committed by
James Bottomley
f5832fa2 859e8167

+6
+6
drivers/scsi/ibmvscsi/ibmvfc.c
··· 3013 3013 if (crq->valid & 0x80) { 3014 3014 if (++async_crq->cur == async_crq->size) 3015 3015 async_crq->cur = 0; 3016 + rmb(); 3016 3017 } else 3017 3018 crq = NULL; 3018 3019 ··· 3036 3035 if (crq->valid & 0x80) { 3037 3036 if (++queue->cur == queue->size) 3038 3037 queue->cur = 0; 3038 + rmb(); 3039 3039 } else 3040 3040 crq = NULL; 3041 3041 ··· 3085 3083 while ((async = ibmvfc_next_async_crq(vhost)) != NULL) { 3086 3084 ibmvfc_handle_async(async, vhost); 3087 3085 async->valid = 0; 3086 + wmb(); 3088 3087 } 3089 3088 3090 3089 /* Pull all the valid messages off the CRQ */ 3091 3090 while ((crq = ibmvfc_next_crq(vhost)) != NULL) { 3092 3091 ibmvfc_handle_crq(crq, vhost); 3093 3092 crq->valid = 0; 3093 + wmb(); 3094 3094 } 3095 3095 3096 3096 vio_enable_interrupts(vdev); ··· 3100 3096 vio_disable_interrupts(vdev); 3101 3097 ibmvfc_handle_async(async, vhost); 3102 3098 async->valid = 0; 3099 + wmb(); 3103 3100 } else if ((crq = ibmvfc_next_crq(vhost)) != NULL) { 3104 3101 vio_disable_interrupts(vdev); 3105 3102 ibmvfc_handle_crq(crq, vhost); 3106 3103 crq->valid = 0; 3104 + wmb(); 3107 3105 } else 3108 3106 done = 1; 3109 3107 }