diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 2ebfb2bb0f42..7b23f21f22f1 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -185,6 +185,11 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue) | |||
185 | if (crq->valid & 0x80) { | 185 | if (crq->valid & 0x80) { |
186 | if (++queue->cur == queue->size) | 186 | if (++queue->cur == queue->size) |
187 | queue->cur = 0; | 187 | queue->cur = 0; |
188 | |||
189 | /* Ensure the read of the valid bit occurs before reading any | ||
190 | * other bits of the CRQ entry | ||
191 | */ | ||
192 | rmb(); | ||
188 | } else | 193 | } else |
189 | crq = NULL; | 194 | crq = NULL; |
190 | spin_unlock_irqrestore(&queue->lock, flags); | 195 | spin_unlock_irqrestore(&queue->lock, flags); |
@@ -203,6 +208,11 @@ static int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, | |||
203 | { | 208 | { |
204 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); | 209 | struct vio_dev *vdev = to_vio_dev(hostdata->dev); |
205 | 210 | ||
211 | /* | ||
212 | * Ensure the command buffer is flushed to memory before handing it | ||
213 | * over to the VIOS to prevent it from fetching any stale data. | ||
214 | */ | ||
215 | mb(); | ||
206 | return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2); | 216 | return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2); |
207 | } | 217 | } |
208 | 218 | ||
@@ -797,7 +807,8 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) | |||
797 | evt->hostdata->dev); | 807 | evt->hostdata->dev); |
798 | if (evt->cmnd_done) | 808 | if (evt->cmnd_done) |
799 | evt->cmnd_done(evt->cmnd); | 809 | evt->cmnd_done(evt->cmnd); |
800 | } else if (evt->done) | 810 | } else if (evt->done && evt->crq.format != VIOSRP_MAD_FORMAT && |
811 | evt->iu.srp.login_req.opcode != SRP_LOGIN_REQ) | ||
801 | evt->done(evt); | 812 | evt->done(evt); |
802 | free_event_struct(&evt->hostdata->pool, evt); | 813 | free_event_struct(&evt->hostdata->pool, evt); |
803 | spin_lock_irqsave(hostdata->host->host_lock, flags); | 814 | spin_lock_irqsave(hostdata->host->host_lock, flags); |