enic: Bug Fix: Handle surprise hardware removals
authorVasanthy Kolluri <vkolluri@cisco.com>
Thu, 24 Jun 2010 10:52:08 +0000 (10:52 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 26 Jun 2010 03:50:25 +0000 (20:50 -0700)
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>
drivers/net/enic/vnic_dev.c
drivers/net/enic/vnic_rq.c
drivers/net/enic/vnic_wq.c

index 180912f480077831585caaa187907c2ce8c1d2c3..662123c9581e0eb59e6f9258c7d4afff989dac3e 100644 (file)
@@ -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)) {
 
index 45cfc79f9f98f943448fcc151e17a6889449d4bc..061a26fbbbfb566b4284dc6874df5d5602d1ad7a 100644 (file)
@@ -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)];
index 6c4d4f7f100ff8213cbe9c801a5f25d8a57f6d5c..3ab7fa5501cd60f9952becb671442533c1bd4f31 100644 (file)
@@ -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) {