aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c88
1 files changed, 39 insertions, 49 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 9f7c543cc04b..01e69383d9c0 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -164,7 +164,7 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
164 164
165static int cciss_revalidate(struct gendisk *disk); 165static int cciss_revalidate(struct gendisk *disk);
166static int rebuild_lun_table(ctlr_info_t *h, int first_time); 166static int rebuild_lun_table(ctlr_info_t *h, int first_time);
167static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, 167static int deregister_disk(ctlr_info_t *h, int drv_index,
168 int clear_all); 168 int clear_all);
169 169
170static void cciss_read_capacity(int ctlr, int logvol, int withirq, 170static void cciss_read_capacity(int ctlr, int logvol, int withirq,
@@ -215,31 +215,17 @@ static struct block_device_operations cciss_fops = {
215/* 215/*
216 * Enqueuing and dequeuing functions for cmdlists. 216 * Enqueuing and dequeuing functions for cmdlists.
217 */ 217 */
218static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) 218static inline void addQ(struct hlist_head *list, CommandList_struct *c)
219{ 219{
220 if (*Qptr == NULL) { 220 hlist_add_head(&c->list, list);
221 *Qptr = c;
222 c->next = c->prev = c;
223 } else {
224 c->prev = (*Qptr)->prev;
225 c->next = (*Qptr);
226 (*Qptr)->prev->next = c;
227 (*Qptr)->prev = c;
228 }
229} 221}
230 222
231static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 223static inline void removeQ(CommandList_struct *c)
232 CommandList_struct *c)
233{ 224{
234 if (c && c->next != c) { 225 if (WARN_ON(hlist_unhashed(&c->list)))
235 if (*Qptr == c) 226 return;
236 *Qptr = c->next; 227
237 c->prev->next = c->next; 228 hlist_del_init(&c->list);
238 c->next->prev = c->prev;
239 } else {
240 *Qptr = NULL;
241 }
242 return c;
243} 229}
244 230
245#include "cciss_scsi.c" /* For SCSI tape support */ 231#include "cciss_scsi.c" /* For SCSI tape support */
@@ -506,6 +492,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
506 c->cmdindex = i; 492 c->cmdindex = i;
507 } 493 }
508 494
495 INIT_HLIST_NODE(&c->list);
509 c->busaddr = (__u32) cmd_dma_handle; 496 c->busaddr = (__u32) cmd_dma_handle;
510 temp64.val = (__u64) err_dma_handle; 497 temp64.val = (__u64) err_dma_handle;
511 c->ErrDesc.Addr.lower = temp64.val32.lower; 498 c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -1492,8 +1479,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
1492 * which keeps the interrupt handler from starting 1479 * which keeps the interrupt handler from starting
1493 * the queue. 1480 * the queue.
1494 */ 1481 */
1495 ret = deregister_disk(h->gendisk[drv_index], 1482 ret = deregister_disk(h, drv_index, 0);
1496 &h->drv[drv_index], 0);
1497 h->drv[drv_index].busy_configuring = 0; 1483 h->drv[drv_index].busy_configuring = 0;
1498 } 1484 }
1499 1485
@@ -1711,8 +1697,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time)
1711 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); 1697 spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
1712 h->drv[i].busy_configuring = 1; 1698 h->drv[i].busy_configuring = 1;
1713 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); 1699 spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
1714 return_code = deregister_disk(h->gendisk[i], 1700 return_code = deregister_disk(h, i, 1);
1715 &h->drv[i], 1);
1716 h->drv[i].busy_configuring = 0; 1701 h->drv[i].busy_configuring = 0;
1717 } 1702 }
1718 } 1703 }
@@ -1782,15 +1767,19 @@ mem_msg:
1782 * the highest_lun should be left unchanged and the LunID 1767 * the highest_lun should be left unchanged and the LunID
1783 * should not be cleared. 1768 * should not be cleared.
1784*/ 1769*/
1785static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, 1770static int deregister_disk(ctlr_info_t *h, int drv_index,
1786 int clear_all) 1771 int clear_all)
1787{ 1772{
1788 int i; 1773 int i;
1789 ctlr_info_t *h = get_host(disk); 1774 struct gendisk *disk;
1775 drive_info_struct *drv;
1790 1776
1791 if (!capable(CAP_SYS_RAWIO)) 1777 if (!capable(CAP_SYS_RAWIO))
1792 return -EPERM; 1778 return -EPERM;
1793 1779
1780 drv = &h->drv[drv_index];
1781 disk = h->gendisk[drv_index];
1782
1794 /* make sure logical volume is NOT is use */ 1783 /* make sure logical volume is NOT is use */
1795 if (clear_all || (h->gendisk[0] == disk)) { 1784 if (clear_all || (h->gendisk[0] == disk)) {
1796 if (drv->usage_count > 1) 1785 if (drv->usage_count > 1)
@@ -2548,7 +2537,8 @@ static void start_io(ctlr_info_t *h)
2548{ 2537{
2549 CommandList_struct *c; 2538 CommandList_struct *c;
2550 2539
2551 while ((c = h->reqQ) != NULL) { 2540 while (!hlist_empty(&h->reqQ)) {
2541 c = hlist_entry(h->reqQ.first, CommandList_struct, list);
2552 /* can't do anything if fifo is full */ 2542 /* can't do anything if fifo is full */
2553 if ((h->access.fifo_full(h))) { 2543 if ((h->access.fifo_full(h))) {
2554 printk(KERN_WARNING "cciss: fifo full\n"); 2544 printk(KERN_WARNING "cciss: fifo full\n");
@@ -2556,14 +2546,14 @@ static void start_io(ctlr_info_t *h)
2556 } 2546 }
2557 2547
2558 /* Get the first entry from the Request Q */ 2548 /* Get the first entry from the Request Q */
2559 removeQ(&(h->reqQ), c); 2549 removeQ(c);
2560 h->Qdepth--; 2550 h->Qdepth--;
2561 2551
2562 /* Tell the controller execute command */ 2552 /* Tell the controller execute command */
2563 h->access.submit_command(h, c); 2553 h->access.submit_command(h, c);
2564 2554
2565 /* Put job onto the completed Q */ 2555 /* Put job onto the completed Q */
2566 addQ(&(h->cmpQ), c); 2556 addQ(&h->cmpQ, c);
2567 } 2557 }
2568} 2558}
2569 2559
@@ -2576,7 +2566,7 @@ static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
2576 memset(c->err_info, 0, sizeof(ErrorInfo_struct)); 2566 memset(c->err_info, 0, sizeof(ErrorInfo_struct));
2577 2567
2578 /* add it to software queue and then send it to the controller */ 2568 /* add it to software queue and then send it to the controller */
2579 addQ(&(h->reqQ), c); 2569 addQ(&h->reqQ, c);
2580 h->Qdepth++; 2570 h->Qdepth++;
2581 if (h->Qdepth > h->maxQsinceinit) 2571 if (h->Qdepth > h->maxQsinceinit)
2582 h->maxQsinceinit = h->Qdepth; 2572 h->maxQsinceinit = h->Qdepth;
@@ -2897,7 +2887,7 @@ static void do_cciss_request(struct request_queue *q)
2897 2887
2898 spin_lock_irq(q->queue_lock); 2888 spin_lock_irq(q->queue_lock);
2899 2889
2900 addQ(&(h->reqQ), c); 2890 addQ(&h->reqQ, c);
2901 h->Qdepth++; 2891 h->Qdepth++;
2902 if (h->Qdepth > h->maxQsinceinit) 2892 if (h->Qdepth > h->maxQsinceinit)
2903 h->maxQsinceinit = h->Qdepth; 2893 h->maxQsinceinit = h->Qdepth;
@@ -2985,16 +2975,12 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
2985 a = c->busaddr; 2975 a = c->busaddr;
2986 2976
2987 } else { 2977 } else {
2978 struct hlist_node *tmp;
2979
2988 a &= ~3; 2980 a &= ~3;
2989 if ((c = h->cmpQ) == NULL) { 2981 c = NULL;
2990 printk(KERN_WARNING 2982 hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
2991 "cciss: Completion of %08x ignored\n", 2983 if (c->busaddr == a)
2992 a1);
2993 continue;
2994 }
2995 while (c->busaddr != a) {
2996 c = c->next;
2997 if (c == h->cmpQ)
2998 break; 2984 break;
2999 } 2985 }
3000 } 2986 }
@@ -3002,8 +2988,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
3002 * If we've found the command, take it off the 2988 * If we've found the command, take it off the
3003 * completion Q and free it 2989 * completion Q and free it
3004 */ 2990 */
3005 if (c->busaddr == a) { 2991 if (c && c->busaddr == a) {
3006 removeQ(&h->cmpQ, c); 2992 removeQ(c);
3007 if (c->cmd_type == CMD_RWREQ) { 2993 if (c->cmd_type == CMD_RWREQ) {
3008 complete_command(h, c, 0); 2994 complete_command(h, c, 0);
3009 } else if (c->cmd_type == CMD_IOCTL_PEND) { 2995 } else if (c->cmd_type == CMD_IOCTL_PEND) {
@@ -3423,6 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
3423 return -1; 3409 return -1;
3424 3410
3425 hba[i]->busy_initializing = 1; 3411 hba[i]->busy_initializing = 1;
3412 INIT_HLIST_HEAD(&hba[i]->cmpQ);
3413 INIT_HLIST_HEAD(&hba[i]->reqQ);
3426 3414
3427 if (cciss_pci_init(hba[i], pdev) != 0) 3415 if (cciss_pci_init(hba[i], pdev) != 0)
3428 goto clean1; 3416 goto clean1;
@@ -3730,15 +3718,17 @@ static void fail_all_cmds(unsigned long ctlr)
3730 pci_disable_device(h->pdev); /* Make sure it is really dead. */ 3718 pci_disable_device(h->pdev); /* Make sure it is really dead. */
3731 3719
3732 /* move everything off the request queue onto the completed queue */ 3720 /* move everything off the request queue onto the completed queue */
3733 while ((c = h->reqQ) != NULL) { 3721 while (!hlist_empty(&h->reqQ)) {
3734 removeQ(&(h->reqQ), c); 3722 c = hlist_entry(h->reqQ.first, CommandList_struct, list);
3723 removeQ(c);
3735 h->Qdepth--; 3724 h->Qdepth--;
3736 addQ(&(h->cmpQ), c); 3725 addQ(&h->cmpQ, c);
3737 } 3726 }
3738 3727
3739 /* Now, fail everything on the completed queue with a HW error */ 3728 /* Now, fail everything on the completed queue with a HW error */
3740 while ((c = h->cmpQ) != NULL) { 3729 while (!hlist_empty(&h->cmpQ)) {
3741 removeQ(&h->cmpQ, c); 3730 c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
3731 removeQ(c);
3742 c->err_info->CommandStatus = CMD_HARDWARE_ERR; 3732 c->err_info->CommandStatus = CMD_HARDWARE_ERR;
3743 if (c->cmd_type == CMD_RWREQ) { 3733 if (c->cmd_type == CMD_RWREQ) {
3744 complete_command(h, c, 0); 3734 complete_command(h, c, 0);