summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasanthy Kolluri <vkolluri@cisco.com>2010-06-24 10:52:08 +0000
committerDavid S. Miller <davem@davemloft.net>2010-06-25 20:50:25 -0700
commit506e1198413d28446f9a98792b2b38b6bf5f8295 (patch)
treee86d4441f76ae2424128261a6df65a0256257dc6
parent1825aca667196f75b193e2d509ea96ffdc8db0ca (diff)
enic: Bug Fix: Handle surprise hardware removals
Handle surprise hardware removals gracefully during devcmd issue and init, cleanup of queues. Signed-off-by: Scott Feldman <scofeldm@cisco.com> Signed-off-by: Vasanthy Kolluri <vkolluri@cisco.com> Signed-off-by: Roopa Prabhu <roprabhu@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/enic/vnic_dev.c9
-rw-r--r--drivers/net/enic/vnic_rq.c13
-rw-r--r--drivers/net/enic/vnic_wq.c2
3 files changed, 20 insertions, 4 deletions
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 180912f48007..662123c9581e 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -275,6 +275,11 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
int err;
status = ioread32(&devcmd->status);
+ if (status == 0xFFFFFFFF) {
+ /* PCI-e target device is gone */
+ return -ENODEV;
+ }
+
if (status & STAT_BUSY) {
pr_err("Busy devcmd %d\n", _CMD_N(cmd));
return -EBUSY;
@@ -296,6 +301,10 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
udelay(100);
status = ioread32(&devcmd->status);
+ if (status == 0xFFFFFFFF) {
+ /* PCI-e target device is gone */
+ return -ENODEV;
+ }
if (!(status & STAT_BUSY)) {
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c
index 45cfc79f9f98..061a26fbbbfb 100644
--- a/drivers/net/enic/vnic_rq.c
+++ b/drivers/net/enic/vnic_rq.c
@@ -146,6 +146,11 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
/* Use current fetch_index as the ring starting point */
fetch_index = ioread32(&rq->ctrl->fetch_index);
+ if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */
+ /* Hardware surprise removal: reset fetch_index */
+ fetch_index = 0;
+ }
+
vnic_rq_init_start(rq, cq_index,
fetch_index, fetch_index,
error_interrupt_enable,
@@ -187,8 +192,6 @@ void vnic_rq_clean(struct vnic_rq *rq,
u32 fetch_index;
unsigned int count = rq->ring.desc_count;
- BUG_ON(ioread32(&rq->ctrl->enable));
-
buf = rq->to_clean;
while (vnic_rq_desc_used(rq) > 0) {
@@ -201,6 +204,12 @@ void vnic_rq_clean(struct vnic_rq *rq,
/* Use current fetch_index as the ring starting point */
fetch_index = ioread32(&rq->ctrl->fetch_index);
+
+ if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */
+ /* Hardware surprise removal: reset fetch_index */
+ fetch_index = 0;
+ }
+
rq->to_use = rq->to_clean =
&rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)]
[fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c
index 6c4d4f7f100f..3ab7fa5501cd 100644
--- a/drivers/net/enic/vnic_wq.c
+++ b/drivers/net/enic/vnic_wq.c
@@ -178,8 +178,6 @@ void vnic_wq_clean(struct vnic_wq *wq,
{
struct vnic_wq_buf *buf;
- BUG_ON(ioread32(&wq->ctrl->enable));
-
buf = wq->to_clean;
while (vnic_wq_desc_used(wq) > 0) {