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 <nmusini@cisco.com> Signed-off-by: Sesidhar Baddela <sebaddel@cisco.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
f352a0d5ba
commit
6e0ae74b5c
|
@ -263,12 +263,20 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||
int wait)
|
||||
{
|
||||
struct devcmd2_controller *dc2c = vdev->devcmd2;
|
||||
struct devcmd2_result *result = dc2c->result + dc2c->next_result;
|
||||
struct devcmd2_result *result = NULL;
|
||||
unsigned int i;
|
||||
int delay;
|
||||
int err;
|
||||
u32 posted;
|
||||
u32 fetch_idx;
|
||||
u32 new_posted;
|
||||
u8 color;
|
||||
|
||||
fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
|
||||
if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone */
|
||||
/* Hardware surprise removal: return error */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
posted = ioread32(&dc2c->wq_ctrl->posted_index);
|
||||
|
||||
|
@ -278,6 +286,13 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||
}
|
||||
|
||||
new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
|
||||
if (new_posted == fetch_idx) {
|
||||
pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
|
||||
pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dc2c->cmd_ring[posted].cmd = cmd;
|
||||
dc2c->cmd_ring[posted].flags = 0;
|
||||
|
||||
|
@ -299,14 +314,22 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||
if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
|
||||
return 0;
|
||||
|
||||
result = dc2c->result + dc2c->next_result;
|
||||
color = dc2c->color;
|
||||
|
||||
/*
|
||||
* Increment next_result, after posting the devcmd, irrespective of
|
||||
* devcmd result, and it should be done only once.
|
||||
*/
|
||||
dc2c->next_result++;
|
||||
if (dc2c->next_result == dc2c->result_size) {
|
||||
dc2c->next_result = 0;
|
||||
dc2c->color = dc2c->color ? 0 : 1;
|
||||
}
|
||||
|
||||
for (delay = 0; delay < wait; delay++) {
|
||||
udelay(100);
|
||||
if (result->color == dc2c->color) {
|
||||
dc2c->next_result++;
|
||||
if (dc2c->next_result == dc2c->result_size) {
|
||||
dc2c->next_result = 0;
|
||||
dc2c->color = dc2c->color ? 0 : 1;
|
||||
}
|
||||
if (result->color == color) {
|
||||
if (result->error) {
|
||||
err = (int) result->error;
|
||||
if (err != ERR_ECMDUNKNOWN ||
|
||||
|
@ -317,13 +340,6 @@ static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||
return err;
|
||||
}
|
||||
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
|
||||
/*
|
||||
* Adding the rmb() prevents the compiler
|
||||
* and/or CPU from reordering the reads which
|
||||
* would potentially result in reading stale
|
||||
* values.
|
||||
*/
|
||||
rmb();
|
||||
for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
|
||||
vdev->args[i] = result->results[i];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue