]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.drivers/cciss-ignore-stale-commands
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / cciss-ignore-stale-commands
CommitLineData
00e5a55c
BS
1From: Hannes Reinecke <hare@suse.de>
2Subject: cciss: Ignore stale commands after reboot
3References: bnc#513437
4Patch-Mainline: yes
5
6When doing an unexpected shutdown like kexec the cciss
7firmware might still have some commands in flight, which
8it is trying to complete.
9The driver is doing it's best on resetting the HBA,
10but sadly there's a firmware issue causing the firmware
11_not_ to abort or drop old commands.
12So the firmware will send us commands which we haven't
13accounted for, causing the driver to panic.
14
15This patch also updates the queue handling to using
16kernel-provided hashed lists; without it we wouldn't
17be able to detect stale commands at all.
18Queue handling is backported from mainline.
19
20Signed-off-by: Hannes Reinecke <hare@suse.de>
21
22diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
23index d7ec8e4..28d3f3d 100644
24--- a/drivers/block/cciss.c
25+++ b/drivers/block/cciss.c
26@@ -214,31 +214,27 @@ static struct block_device_operations cciss_fops = {
27 /*
28 * Enqueuing and dequeuing functions for cmdlists.
29 */
30-static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
31+static inline void addQ(struct hlist_head *list, CommandList_struct *c)
32 {
33- if (*Qptr == NULL) {
34- *Qptr = c;
35- c->next = c->prev = c;
36- } else {
37- c->prev = (*Qptr)->prev;
38- c->next = (*Qptr);
39- (*Qptr)->prev->next = c;
40- (*Qptr)->prev = c;
41- }
42+ hlist_add_head(&c->list, list);
43 }
44
45-static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
46- CommandList_struct *c)
47+static inline void removeQ(CommandList_struct *c)
48 {
49- if (c && c->next != c) {
50- if (*Qptr == c)
51- *Qptr = c->next;
52- c->prev->next = c->next;
53- c->next->prev = c->prev;
54- } else {
55- *Qptr = NULL;
56+ /*
57+ * After kexec/dump some commands might still
58+ * be in flight, which the firmware will try
59+ * to complete. Resetting the firmware doesn't work
60+ * with old fw revisions, so we have to mark
61+ * them off as 'stale' to prevent the driver from
62+ * falling over.
63+ */
64+ if (unlikely(hlist_unhashed(&c->list))) {
65+ c->cmd_type = CMD_MSG_STALE;
66+ return;
67 }
68- return c;
69+
70+ hlist_del_init(&c->list);
71 }
72
73 #include "cciss_scsi.c" /* For SCSI tape support */
74@@ -505,6 +501,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
75 c->cmdindex = i;
76 }
77
78+ INIT_HLIST_NODE(&c->list);
79 c->busaddr = (__u32) cmd_dma_handle;
80 temp64.val = (__u64) err_dma_handle;
81 c->ErrDesc.Addr.lower = temp64.val32.lower;
82@@ -2549,7 +2548,8 @@ static void start_io(ctlr_info_t *h)
83 {
84 CommandList_struct *c;
85
86- while ((c = h->reqQ) != NULL) {
87+ while (!hlist_empty(&h->reqQ)) {
88+ c = hlist_entry(h->reqQ.first, CommandList_struct, list);
89 /* can't do anything if fifo is full */
90 if ((h->access.fifo_full(h))) {
91 printk(KERN_WARNING "cciss: fifo full\n");
92@@ -2557,14 +2557,14 @@ static void start_io(ctlr_info_t *h)
93 }
94
95 /* Get the first entry from the Request Q */
96- removeQ(&(h->reqQ), c);
97+ removeQ(c);
98 h->Qdepth--;
99
100 /* Tell the controller execute command */
101 h->access.submit_command(h, c);
102
103 /* Put job onto the completed Q */
104- addQ(&(h->cmpQ), c);
105+ addQ(&h->cmpQ, c);
106 }
107 }
108
109@@ -2577,7 +2577,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
110 memset(c->err_info, 0, sizeof(ErrorInfo_struct));
111
112 /* add it to software queue and then send it to the controller */
113- addQ(&(h->reqQ), c);
114+ addQ(&h->reqQ, c);
115 h->Qdepth++;
116 if (h->Qdepth > h->maxQsinceinit)
117 h->maxQsinceinit = h->Qdepth;
118@@ -2898,7 +2898,7 @@ static void do_cciss_request(struct request_queue *q)
119
120 spin_lock_irq(q->queue_lock);
121
122- addQ(&(h->reqQ), c);
123+ addQ(&h->reqQ, c);
124 h->Qdepth++;
125 if (h->Qdepth > h->maxQsinceinit)
126 h->maxQsinceinit = h->Qdepth;
127@@ -2986,16 +2986,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
128 a = c->busaddr;
129
130 } else {
131+ struct hlist_node *tmp;
132+
133 a &= ~3;
134- if ((c = h->cmpQ) == NULL) {
135- printk(KERN_WARNING
136- "cciss: Completion of %08x ignored\n",
137- a1);
138- continue;
139- }
140- while (c->busaddr != a) {
141- c = c->next;
142- if (c == h->cmpQ)
143+ c = NULL;
144+ hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
145+ if (c->busaddr == a)
146 break;
147 }
148 }
149@@ -3003,8 +2999,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
150 * If we've found the command, take it off the
151 * completion Q and free it
152 */
153- if (c->busaddr == a) {
154- removeQ(&h->cmpQ, c);
155+ if (c && c->busaddr == a) {
156+ removeQ(c);
157 if (c->cmd_type == CMD_RWREQ) {
158 complete_command(h, c, 0);
159 } else if (c->cmd_type == CMD_IOCTL_PEND) {
160@@ -3423,6 +3419,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
161 return -1;
162
163 hba[i]->busy_initializing = 1;
164+ INIT_HLIST_HEAD(&hba[i]->cmpQ);
165+ INIT_HLIST_HEAD(&hba[i]->reqQ);
166
167 if (cciss_pci_init(hba[i], pdev) != 0)
168 goto clean1;
169@@ -3730,16 +3728,19 @@ static void fail_all_cmds(unsigned long ctlr)
170 pci_disable_device(h->pdev); /* Make sure it is really dead. */
171
172 /* move everything off the request queue onto the completed queue */
173- while ((c = h->reqQ) != NULL) {
174- removeQ(&(h->reqQ), c);
175+ while (!hlist_empty(&h->reqQ)) {
176+ c = hlist_entry(h->reqQ.first, CommandList_struct, list);
177+ removeQ(c);
178 h->Qdepth--;
179- addQ(&(h->cmpQ), c);
180+ addQ(&h->cmpQ, c);
181 }
182
183 /* Now, fail everything on the completed queue with a HW error */
184- while ((c = h->cmpQ) != NULL) {
185- removeQ(&h->cmpQ, c);
186- c->err_info->CommandStatus = CMD_HARDWARE_ERR;
187+ while (!hlist_empty(&h->cmpQ)) {
188+ c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
189+ removeQ(c);
190+ if (c->cmd_type != CMD_MSG_STALE)
191+ c->err_info->CommandStatus = CMD_HARDWARE_ERR;
192 if (c->cmd_type == CMD_RWREQ) {
193 complete_command(h, c, 0);
194 } else if (c->cmd_type == CMD_IOCTL_PEND)
195diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
196index 24a7efa..15e2b84 100644
197--- a/drivers/block/cciss.h
198+++ b/drivers/block/cciss.h
199@@ -89,8 +89,8 @@ struct ctlr_info
200 struct access_method access;
201
202 /* queue and queue Info */
203- CommandList_struct *reqQ;
204- CommandList_struct *cmpQ;
205+ struct hlist_head reqQ;
206+ struct hlist_head cmpQ;
207 unsigned int Qdepth;
208 unsigned int maxQsinceinit;
209 unsigned int maxSG;
210diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
211index 43bf559..e4ca588 100644
212--- a/drivers/block/cciss_cmd.h
213+++ b/drivers/block/cciss_cmd.h
214@@ -249,6 +249,7 @@ typedef struct _ErrorInfo_struct {
215 #define CMD_SCSI 0x03
216 #define CMD_MSG_DONE 0x04
217 #define CMD_MSG_TIMEOUT 0x05
218+#define CMD_MSG_STALE 0xff
219
220 /* This structure needs to be divisible by 8 for new
221 * indexing method.
222@@ -265,8 +266,7 @@ typedef struct _CommandList_struct {
223 int ctlr;
224 int cmd_type;
225 long cmdindex;
226- struct _CommandList_struct *prev;
227- struct _CommandList_struct *next;
228+ struct hlist_node list;
229 struct request * rq;
230 struct completion *waiting;
231 int retry_count;