aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorMike Miller <mikem@beardog.cca.cpqcorp.net>2006-04-10 18:38:07 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-04-17 17:24:57 -0400
commitca1e0484d9fe8a9048ac32b0f9894545f43704e8 (patch)
tree60069aefd37077a86072020713b046203762ff5a /drivers/block
parent75616cf9854b83eb83a968b1338ae0ee11c9673c (diff)
[PATCH] cciss: bug fix for crash when running hpacucli
Fix a crash when running hpacucli with multiple logical volumes on a cciss controller. We were not properly initializing the disk->queue and causing a fault. Thanks to Hasso Tepper for reporting the problem. Thanks to Steve Cameron for root causing the problem. Most of the patch just moves things around. The fix is a one-liner. Signed-off-by: Mike Miller <mike.miller@hp.com> Signed-off-by: Stephen Cameron <steve.cameron@hp.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c96
1 files changed, 49 insertions, 47 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1b0fd31c57c3..1319d8f20640 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1180,6 +1180,53 @@ static int revalidate_allvol(ctlr_info_t *host)
1180 return 0; 1180 return 0;
1181} 1181}
1182 1182
1183static inline void complete_buffers(struct bio *bio, int status)
1184{
1185 while (bio) {
1186 struct bio *xbh = bio->bi_next;
1187 int nr_sectors = bio_sectors(bio);
1188
1189 bio->bi_next = NULL;
1190 blk_finished_io(len);
1191 bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
1192 bio = xbh;
1193 }
1194
1195}
1196
1197static void cciss_softirq_done(struct request *rq)
1198{
1199 CommandList_struct *cmd = rq->completion_data;
1200 ctlr_info_t *h = hba[cmd->ctlr];
1201 unsigned long flags;
1202 u64bit temp64;
1203 int i, ddir;
1204
1205 if (cmd->Request.Type.Direction == XFER_READ)
1206 ddir = PCI_DMA_FROMDEVICE;
1207 else
1208 ddir = PCI_DMA_TODEVICE;
1209
1210 /* command did not need to be retried */
1211 /* unmap the DMA mapping for all the scatter gather elements */
1212 for(i=0; i<cmd->Header.SGList; i++) {
1213 temp64.val32.lower = cmd->SG[i].Addr.lower;
1214 temp64.val32.upper = cmd->SG[i].Addr.upper;
1215 pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
1216 }
1217
1218 complete_buffers(rq->bio, rq->errors);
1219
1220#ifdef CCISS_DEBUG
1221 printk("Done with %p\n", rq);
1222#endif /* CCISS_DEBUG */
1223
1224 spin_lock_irqsave(&h->lock, flags);
1225 end_that_request_last(rq, rq->errors);
1226 cmd_free(h, cmd,1);
1227 spin_unlock_irqrestore(&h->lock, flags);
1228}
1229
1183/* This function will check the usage_count of the drive to be updated/added. 1230/* This function will check the usage_count of the drive to be updated/added.
1184 * If the usage_count is zero then the drive information will be updated and 1231 * If the usage_count is zero then the drive information will be updated and
1185 * the disk will be re-registered with the kernel. If not then it will be 1232 * the disk will be re-registered with the kernel. If not then it will be
@@ -1248,6 +1295,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
1248 1295
1249 blk_queue_max_sectors(disk->queue, 512); 1296 blk_queue_max_sectors(disk->queue, 512);
1250 1297
1298 blk_queue_softirq_done(disk->queue, cciss_softirq_done);
1299
1251 disk->queue->queuedata = hba[ctlr]; 1300 disk->queue->queuedata = hba[ctlr];
1252 1301
1253 blk_queue_hardsect_size(disk->queue, 1302 blk_queue_hardsect_size(disk->queue,
@@ -2147,20 +2196,6 @@ static void start_io( ctlr_info_t *h)
2147 addQ (&(h->cmpQ), c); 2196 addQ (&(h->cmpQ), c);
2148 } 2197 }
2149} 2198}
2150
2151static inline void complete_buffers(struct bio *bio, int status)
2152{
2153 while (bio) {
2154 struct bio *xbh = bio->bi_next;
2155 int nr_sectors = bio_sectors(bio);
2156
2157 bio->bi_next = NULL;
2158 blk_finished_io(len);
2159 bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
2160 bio = xbh;
2161 }
2162
2163}
2164/* Assumes that CCISS_LOCK(h->ctlr) is held. */ 2199/* Assumes that CCISS_LOCK(h->ctlr) is held. */
2165/* Zeros out the error record and then resends the command back */ 2200/* Zeros out the error record and then resends the command back */
2166/* to the controller */ 2201/* to the controller */
@@ -2178,39 +2213,6 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
2178 start_io(h); 2213 start_io(h);
2179} 2214}
2180 2215
2181static void cciss_softirq_done(struct request *rq)
2182{
2183 CommandList_struct *cmd = rq->completion_data;
2184 ctlr_info_t *h = hba[cmd->ctlr];
2185 unsigned long flags;
2186 u64bit temp64;
2187 int i, ddir;
2188
2189 if (cmd->Request.Type.Direction == XFER_READ)
2190 ddir = PCI_DMA_FROMDEVICE;
2191 else
2192 ddir = PCI_DMA_TODEVICE;
2193
2194 /* command did not need to be retried */
2195 /* unmap the DMA mapping for all the scatter gather elements */
2196 for(i=0; i<cmd->Header.SGList; i++) {
2197 temp64.val32.lower = cmd->SG[i].Addr.lower;
2198 temp64.val32.upper = cmd->SG[i].Addr.upper;
2199 pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
2200 }
2201
2202 complete_buffers(rq->bio, rq->errors);
2203
2204#ifdef CCISS_DEBUG
2205 printk("Done with %p\n", rq);
2206#endif /* CCISS_DEBUG */
2207
2208 spin_lock_irqsave(&h->lock, flags);
2209 end_that_request_last(rq, rq->errors);
2210 cmd_free(h, cmd,1);
2211 spin_unlock_irqrestore(&h->lock, flags);
2212}
2213
2214/* checks the status of the job and calls complete buffers to mark all 2216/* checks the status of the job and calls complete buffers to mark all
2215 * buffers for the completed job. Note that this function does not need 2217 * buffers for the completed job. Note that this function does not need
2216 * to hold the hba/queue lock. 2218 * to hold the hba/queue lock.