Skip to content

Commit 6e0ae74

Browse files
Narsimhulu Musinimartinkpetersen
authored andcommitted
snic: Handling control path queue issues
Fix handles control path queue issues such as queue full and sudden removal of hardware. Signed-off-by: Narsimhulu Musini <[email protected]> Signed-off-by: Sesidhar Baddela <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent f352a0d commit 6e0ae74

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

drivers/scsi/snic/vnic_dev.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
263263
int wait)
264264
{
265265
struct devcmd2_controller *dc2c = vdev->devcmd2;
266-
struct devcmd2_result *result = dc2c->result + dc2c->next_result;
266+
struct devcmd2_result *result = NULL;
267267
unsigned int i;
268268
int delay;
269269
int err;
270270
u32 posted;
271+
u32 fetch_idx;
271272
u32 new_posted;
273+
u8 color;
274+
275+
fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
276+
if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone */
277+
/* Hardware surprise removal: return error */
278+
return -ENODEV;
279+
}
272280

273281
posted = ioread32(&dc2c->wq_ctrl->posted_index);
274282

@@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
278286
}
279287

280288
new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
289+
if (new_posted == fetch_idx) {
290+
pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
291+
pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
292+
293+
return -EBUSY;
294+
}
295+
281296
dc2c->cmd_ring[posted].cmd = cmd;
282297
dc2c->cmd_ring[posted].flags = 0;
283298

@@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
299314
if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
300315
return 0;
301316

317+
result = dc2c->result + dc2c->next_result;
318+
color = dc2c->color;
319+
320+
/*
321+
* Increment next_result, after posting the devcmd, irrespective of
322+
* devcmd result, and it should be done only once.
323+
*/
324+
dc2c->next_result++;
325+
if (dc2c->next_result == dc2c->result_size) {
326+
dc2c->next_result = 0;
327+
dc2c->color = dc2c->color ? 0 : 1;
328+
}
329+
302330
for (delay = 0; delay < wait; delay++) {
303331
udelay(100);
304-
if (result->color == dc2c->color) {
305-
dc2c->next_result++;
306-
if (dc2c->next_result == dc2c->result_size) {
307-
dc2c->next_result = 0;
308-
dc2c->color = dc2c->color ? 0 : 1;
309-
}
332+
if (result->color == color) {
310333
if (result->error) {
311334
err = (int) result->error;
312335
if (err != ERR_ECMDUNKNOWN ||
@@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
317340
return err;
318341
}
319342
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
320-
/*
321-
* Adding the rmb() prevents the compiler
322-
* and/or CPU from reordering the reads which
323-
* would potentially result in reading stale
324-
* values.
325-
*/
326-
rmb();
327343
for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
328344
vdev->args[i] = result->results[i];
329345
}

0 commit comments

Comments
 (0)