]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 18:06:41 +0000 (11:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 18:06:41 +0000 (11:06 -0700)
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  loop: mutex already unlocked in loop_clr_fd()
  cfq-iosched: don't let idling interfere with plugging
  block: remove unused REQ_UNPLUG
  cfq-iosched: kill two unused cfqq flags
  cfq-iosched: change dispatch logic to deal with single requests at the time
  mflash: initial support
  cciss: change to discover first memory BAR
  cciss: kernel scan thread for MSA2012
  cciss: fix residual count for block pc requests
  block: fix inconsistency in I/O stat accounting code
  block: elevator quiescing helpers

1  2 
drivers/block/cciss.c

diff --combined drivers/block/cciss.c
index a6c55432819bd17fc14e42e5edd1a4cbb7219a94,219c530c8da009f13adf0786a75a35182803153c..0ef6f08aa6eadfbdb685704eb5fe5f039ff8e474
@@@ -51,6 -51,7 +51,7 @@@
  #include <scsi/scsi_ioctl.h>
  #include <linux/cdrom.h>
  #include <linux/scatterlist.h>
+ #include <linux/kthread.h>
  
  #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
  #define DRIVER_NAME "HP CISS Driver (v 3.6.20)"
@@@ -186,6 -187,8 +187,8 @@@ static int sendcmd_withirq(__u8 cmd, in
                           __u8 page_code, int cmd_type);
  
  static void fail_all_cmds(unsigned long ctlr);
+ static int scan_thread(void *data);
+ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c);
  
  #ifdef CONFIG_PROC_FS
  static void cciss_procinit(int i);
@@@ -735,6 -738,12 +738,12 @@@ static int cciss_getgeo(struct block_de
        return 0;
  }
  
+ static void check_ioctl_unit_attention(ctlr_info_t *host, CommandList_struct *c)
+ {
+       if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+                       c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
+               (void)check_for_unit_attention(host, c);
+ }
  /*
   * ioctl
   */
@@@ -1029,6 -1038,8 +1038,8 @@@ static int cciss_ioctl(struct block_dev
                                         iocommand.buf_size,
                                         PCI_DMA_BIDIRECTIONAL);
  
+                       check_ioctl_unit_attention(host, c);
                        /* Copy the error information out */
                        iocommand.error_info = *(c->err_info);
                        if (copy_to_user
                                        (dma_addr_t) temp64.val, buff_size[i],
                                        PCI_DMA_BIDIRECTIONAL);
                        }
+                       check_ioctl_unit_attention(host, c);
                        /* Copy the error information out */
                        ioc->error_info = *(c->err_info);
                        if (copy_to_user(argp, ioc, sizeof(*ioc))) {
@@@ -1287,6 -1299,7 +1299,7 @@@ static void cciss_softirq_done(struct r
  {
        CommandList_struct *cmd = rq->completion_data;
        ctlr_info_t *h = hba[cmd->ctlr];
+       unsigned int nr_bytes;
        unsigned long flags;
        u64bit temp64;
        int i, ddir;
        printk("Done with %p\n", rq);
  #endif                                /* CCISS_DEBUG */
  
-       if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq)))
+       /*
+        * Store the full size and set the residual count for pc requests
+        */
+       nr_bytes = blk_rq_bytes(rq);
+       if (blk_pc_request(rq))
+               rq->data_len = cmd->err_info->ResidualCnt;
+       if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes))
                BUG();
  
        spin_lock_irqsave(&h->lock, flags);
@@@ -2585,12 -2605,14 +2605,14 @@@ static inline unsigned int make_status_
                ((driver_byte & 0xff) << 24);
  }
  
- static inline int evaluate_target_status(CommandList_struct *cmd)
+ static inline int evaluate_target_status(ctlr_info_t *h,
+                       CommandList_struct *cmd, int *retry_cmd)
  {
        unsigned char sense_key;
        unsigned char status_byte, msg_byte, host_byte, driver_byte;
        int error_value;
  
+       *retry_cmd = 0;
        /* If we get in here, it means we got "target status", that is, scsi status */
        status_byte = cmd->err_info->ScsiStatus;
        driver_byte = DRIVER_OK;
        if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
                error_value = 0;
  
+       if (check_for_unit_attention(h, cmd)) {
+               *retry_cmd = !blk_pc_request(cmd->rq);
+               return 0;
+       }
        if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
                if (error_value != 0)
                        printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
@@@ -2657,7 -2684,7 +2684,7 @@@ static inline void complete_command(ctl
  
        switch (cmd->err_info->CommandStatus) {
        case CMD_TARGET_STATUS:
-               rq->errors = evaluate_target_status(cmd);
+               rq->errors = evaluate_target_status(h, cmd, &retry_cmd);
                break;
        case CMD_DATA_UNDERRUN:
                if (blk_fs_request(cmd->rq)) {
@@@ -3008,6 -3035,63 +3035,63 @@@ static irqreturn_t do_cciss_intr(int ir
        return IRQ_HANDLED;
  }
  
+ static int scan_thread(void *data)
+ {
+       ctlr_info_t *h = data;
+       int rc;
+       DECLARE_COMPLETION_ONSTACK(wait);
+       h->rescan_wait = &wait;
+       for (;;) {
+               rc = wait_for_completion_interruptible(&wait);
+               if (kthread_should_stop())
+                       break;
+               if (!rc)
+                       rebuild_lun_table(h, 0);
+       }
+       return 0;
+ }
+ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c)
+ {
+       if (c->err_info->SenseInfo[2] != UNIT_ATTENTION)
+               return 0;
+       switch (c->err_info->SenseInfo[12]) {
+       case STATE_CHANGED:
+               printk(KERN_WARNING "cciss%d: a state change "
+                       "detected, command retried\n", h->ctlr);
+               return 1;
+       break;
+       case LUN_FAILED:
+               printk(KERN_WARNING "cciss%d: LUN failure "
+                       "detected, action required\n", h->ctlr);
+               return 1;
+       break;
+       case REPORT_LUNS_CHANGED:
+               printk(KERN_WARNING "cciss%d: report LUN data "
+                       "changed\n", h->ctlr);
+               if (h->rescan_wait)
+                       complete(h->rescan_wait);
+               return 1;
+       break;
+       case POWER_OR_RESET:
+               printk(KERN_WARNING "cciss%d: a power on "
+                       "or device reset detected\n", h->ctlr);
+               return 1;
+       break;
+       case UNIT_ATTENTION_CLEARED:
+               printk(KERN_WARNING "cciss%d: unit attention "
+                   "cleared by another initiator\n", h->ctlr);
+               return 1;
+       break;
+       default:
+               printk(KERN_WARNING "cciss%d: unknown "
+                       "unit attention detected\n", h->ctlr);
+                               return 1;
+       }
+ }
  /*
   *  We cannot read the structure directly, for portability we must use
   *   the io functions.
@@@ -3181,12 -3265,21 +3265,21 @@@ static int __devinit cciss_pci_init(ctl
   */
        cciss_interrupt_mode(c, pdev, board_id);
  
-       /*
-        * Memory base addr is first addr , the second points to the config
-        *   table
-        */
+       /* find the memory BAR */
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               if (pci_resource_flags(pdev, i) & IORESOURCE_MEM)
+                       break;
+       }
+       if (i == DEVICE_COUNT_RESOURCE) {
+               printk(KERN_WARNING "cciss: No memory BAR found\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+       c->paddr = pci_resource_start(pdev, i); /* addressing mode bits
+                                                * already removed
+                                                */
  
-       c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
  #ifdef CCISS_DEBUG
        printk("address 0 = %lx\n", c->paddr);
  #endif                                /* CCISS_DEBUG */
@@@ -3637,9 -3730,9 +3730,9 @@@ static int __devinit cciss_init_one(str
        hba[i]->pdev = pdev;
  
        /* configure PCI DMA stuff */
 -      if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
 +      if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
                dac = 1;
 -      else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
 +      else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
                dac = 0;
        else {
                printk(KERN_ERR "cciss: no suitable DMA available\n");
        hba[i]->busy_initializing = 0;
  
        rebuild_lun_table(hba[i], 1);
+       hba[i]->cciss_scan_thread = kthread_run(scan_thread, hba[i],
+                               "cciss_scan%02d", i);
+       if (IS_ERR(hba[i]->cciss_scan_thread))
+               return PTR_ERR(hba[i]->cciss_scan_thread);
        return 1;
  
  clean4:
@@@ -3828,6 -3926,7 +3926,7 @@@ static void __devexit cciss_remove_one(
                printk(KERN_ERR "cciss: Unable to remove device \n");
                return;
        }
        tmp_ptr = pci_get_drvdata(pdev);
        i = tmp_ptr->ctlr;
        if (hba[i] == NULL) {
                return;
        }
  
+       kthread_stop(hba[i]->cciss_scan_thread);
        remove_proc_entry(hba[i]->devname, proc_cciss);
        unregister_blkdev(hba[i]->major, hba[i]->devname);