]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/cciss-ignore-stale-commands
Revert "Move xen patchset to new version's subdir."
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / cciss-ignore-stale-commands
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/cciss-ignore-stale-commands b/src/patches/suse-2.6.27.31/patches.drivers/cciss-ignore-stale-commands
deleted file mode 100644 (file)
index 837eb44..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-From: Hannes Reinecke <hare@suse.de>
-Subject: cciss: Ignore stale commands after reboot
-References: bnc#513437
-Patch-Mainline: yes
-
-When doing an unexpected shutdown like kexec the cciss
-firmware might still have some commands in flight, which
-it is trying to complete.
-The driver is doing it's best on resetting the HBA,
-but sadly there's a firmware issue causing the firmware
-_not_ to abort or drop old commands.
-So the firmware will send us commands which we haven't
-accounted for, causing the driver to panic.
-
-This patch also updates the queue handling to using
-kernel-provided hashed lists; without it we wouldn't
-be able to detect stale commands at all.
-Queue handling is backported from mainline.
-
-Signed-off-by: Hannes Reinecke <hare@suse.de>
-
-diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
-index d7ec8e4..28d3f3d 100644
---- a/drivers/block/cciss.c
-+++ b/drivers/block/cciss.c
-@@ -214,31 +214,27 @@ static struct block_device_operations cciss_fops = {
- /*
-  * Enqueuing and dequeuing functions for cmdlists.
-  */
--static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
-+static inline void addQ(struct hlist_head *list, CommandList_struct *c)
- {
--      if (*Qptr == NULL) {
--              *Qptr = c;
--              c->next = c->prev = c;
--      } else {
--              c->prev = (*Qptr)->prev;
--              c->next = (*Qptr);
--              (*Qptr)->prev->next = c;
--              (*Qptr)->prev = c;
--      }
-+      hlist_add_head(&c->list, list);
- }
--static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
--                                        CommandList_struct *c)
-+static inline void removeQ(CommandList_struct *c)
- {
--      if (c && c->next != c) {
--              if (*Qptr == c)
--                      *Qptr = c->next;
--              c->prev->next = c->next;
--              c->next->prev = c->prev;
--      } else {
--              *Qptr = NULL;
-+      /*
-+       * After kexec/dump some commands might still
-+       * be in flight, which the firmware will try
-+       * to complete. Resetting the firmware doesn't work
-+       * with old fw revisions, so we have to mark
-+       * them off as 'stale' to prevent the driver from
-+       * falling over.
-+       */
-+      if (unlikely(hlist_unhashed(&c->list))) {
-+              c->cmd_type = CMD_MSG_STALE;
-+              return;
-       }
--      return c;
-+
-+      hlist_del_init(&c->list);
- }
- #include "cciss_scsi.c"               /* For SCSI tape support */
-@@ -505,6 +501,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
-               c->cmdindex = i;
-       }
-+      INIT_HLIST_NODE(&c->list);
-       c->busaddr = (__u32) cmd_dma_handle;
-       temp64.val = (__u64) err_dma_handle;
-       c->ErrDesc.Addr.lower = temp64.val32.lower;
-@@ -2549,7 +2548,8 @@ static void start_io(ctlr_info_t *h)
- {
-       CommandList_struct *c;
--      while ((c = h->reqQ) != NULL) {
-+      while (!hlist_empty(&h->reqQ)) {
-+              c = hlist_entry(h->reqQ.first, CommandList_struct, list);
-               /* can't do anything if fifo is full */
-               if ((h->access.fifo_full(h))) {
-                       printk(KERN_WARNING "cciss: fifo full\n");
-@@ -2557,14 +2557,14 @@ static void start_io(ctlr_info_t *h)
-               }
-               /* Get the first entry from the Request Q */
--              removeQ(&(h->reqQ), c);
-+              removeQ(c);
-               h->Qdepth--;
-               /* Tell the controller execute command */
-               h->access.submit_command(h, c);
-               /* Put job onto the completed Q */
--              addQ(&(h->cmpQ), c);
-+              addQ(&h->cmpQ, c);
-       }
- }
-@@ -2577,7 +2577,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
-       memset(c->err_info, 0, sizeof(ErrorInfo_struct));
-       /* add it to software queue and then send it to the controller */
--      addQ(&(h->reqQ), c);
-+      addQ(&h->reqQ, c);
-       h->Qdepth++;
-       if (h->Qdepth > h->maxQsinceinit)
-               h->maxQsinceinit = h->Qdepth;
-@@ -2898,7 +2898,7 @@ static void do_cciss_request(struct request_queue *q)
-       spin_lock_irq(q->queue_lock);
--      addQ(&(h->reqQ), c);
-+      addQ(&h->reqQ, c);
-       h->Qdepth++;
-       if (h->Qdepth > h->maxQsinceinit)
-               h->maxQsinceinit = h->Qdepth;
-@@ -2986,16 +2986,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
-                               a = c->busaddr;
-                       } else {
-+                              struct hlist_node *tmp;
-+
-                               a &= ~3;
--                              if ((c = h->cmpQ) == NULL) {
--                                      printk(KERN_WARNING
--                                             "cciss: Completion of %08x ignored\n",
--                                             a1);
--                                      continue;
--                              }
--                              while (c->busaddr != a) {
--                                      c = c->next;
--                                      if (c == h->cmpQ)
-+                              c = NULL;
-+                              hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
-+                                      if (c->busaddr == a)
-                                               break;
-                               }
-                       }
-@@ -3003,8 +2999,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
-                        * If we've found the command, take it off the
-                        * completion Q and free it
-                        */
--                      if (c->busaddr == a) {
--                              removeQ(&h->cmpQ, c);
-+                      if (c && c->busaddr == a) {
-+                              removeQ(c);
-                               if (c->cmd_type == CMD_RWREQ) {
-                                       complete_command(h, c, 0);
-                               } else if (c->cmd_type == CMD_IOCTL_PEND) {
-@@ -3423,6 +3419,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
-               return -1;
-       hba[i]->busy_initializing = 1;
-+      INIT_HLIST_HEAD(&hba[i]->cmpQ);
-+      INIT_HLIST_HEAD(&hba[i]->reqQ);
-       if (cciss_pci_init(hba[i], pdev) != 0)
-               goto clean1;
-@@ -3730,16 +3728,19 @@ static void fail_all_cmds(unsigned long ctlr)
-       pci_disable_device(h->pdev);    /* Make sure it is really dead. */
-       /* move everything off the request queue onto the completed queue */
--      while ((c = h->reqQ) != NULL) {
--              removeQ(&(h->reqQ), c);
-+      while (!hlist_empty(&h->reqQ)) {
-+              c = hlist_entry(h->reqQ.first, CommandList_struct, list);
-+              removeQ(c);
-               h->Qdepth--;
--              addQ(&(h->cmpQ), c);
-+              addQ(&h->cmpQ, c);
-       }
-       /* Now, fail everything on the completed queue with a HW error */
--      while ((c = h->cmpQ) != NULL) {
--              removeQ(&h->cmpQ, c);
--              c->err_info->CommandStatus = CMD_HARDWARE_ERR;
-+      while (!hlist_empty(&h->cmpQ)) {
-+              c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
-+              removeQ(c);
-+              if (c->cmd_type != CMD_MSG_STALE)
-+                      c->err_info->CommandStatus = CMD_HARDWARE_ERR;
-               if (c->cmd_type == CMD_RWREQ) {
-                       complete_command(h, c, 0);
-               } else if (c->cmd_type == CMD_IOCTL_PEND)
-diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
-index 24a7efa..15e2b84 100644
---- a/drivers/block/cciss.h
-+++ b/drivers/block/cciss.h
-@@ -89,8 +89,8 @@ struct ctlr_info
-       struct access_method access;
-       /* queue and queue Info */ 
--      CommandList_struct *reqQ;
--      CommandList_struct  *cmpQ;
-+      struct hlist_head reqQ;
-+      struct hlist_head cmpQ;
-       unsigned int Qdepth;
-       unsigned int maxQsinceinit;
-       unsigned int maxSG;
-diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
-index 43bf559..e4ca588 100644
---- a/drivers/block/cciss_cmd.h
-+++ b/drivers/block/cciss_cmd.h
-@@ -249,6 +249,7 @@ typedef struct _ErrorInfo_struct {
- #define CMD_SCSI      0x03
- #define CMD_MSG_DONE  0x04
- #define CMD_MSG_TIMEOUT 0x05
-+#define CMD_MSG_STALE   0xff
- /* This structure needs to be divisible by 8 for new
-  * indexing method.
-@@ -265,8 +266,7 @@ typedef struct _CommandList_struct {
-   int                    ctlr;
-   int                    cmd_type; 
-   long                           cmdindex;
--  struct _CommandList_struct *prev;
--  struct _CommandList_struct *next;
-+  struct hlist_node list;
-   struct request *       rq;
-   struct completion *waiting;
-   int  retry_count;