]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/block/cciss.c
cciss: reformat error handling
[linux-2.6-omap-h63xx.git] / drivers / block / cciss.c
index 05dfe357527c231037365be190baef05b39ef5f3..b00be1427c3fd34833c7f5ab03cf494920dbc60f 100644 (file)
@@ -1291,13 +1291,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
        if (inq_buff == NULL)
                goto mem_msg;
 
+       /* testing to see if 16-byte CDBs are already being used */
+       if (h->cciss_read == CCISS_READ_16) {
+               cciss_read_capacity_16(h->ctlr, drv_index, 1,
+                       &total_size, &block_size);
+               goto geo_inq;
+       }
+
        cciss_read_capacity(ctlr, drv_index, 1,
                            &total_size, &block_size);
 
-       /* total size = last LBA + 1 */
-       /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
-       /* so we assume this volume this must be >2TB in size */
-       if (total_size == (__u32) 0) {
+       /* if read_capacity returns all F's this volume is >2TB in size */
+       /* so we switch to 16-byte CDB's for all read/write ops */
+       if (total_size == 0xFFFFFFFFULL) {
                cciss_read_capacity_16(ctlr, drv_index, 1,
                &total_size, &block_size);
                h->cciss_read = CCISS_READ_16;
@@ -1306,6 +1312,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
                h->cciss_read = CCISS_READ_10;
                h->cciss_write = CCISS_WRITE_10;
        }
+geo_inq:
        cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
                               inq_buff, &h->drv[drv_index]);
 
@@ -1432,7 +1439,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
 
                if (return_code == IO_OK) {
                        listlength =
-                               be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
+                               be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
                } else {        /* reading number of logical volumes failed */
                        printk(KERN_WARNING "cciss: report logical volume"
                               " command failed\n");
@@ -1908,6 +1915,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                               "does not support reading geometry\n");
                        drv->heads = 255;
                        drv->sectors = 32;      // Sectors per track
+                       drv->cylinders = total_size + 1;
                        drv->raid_level = RAID_UNKNOWN;
                } else {
                        drv->heads = inq_buff->data_byte[6];
@@ -1917,13 +1925,14 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                        drv->raid_level = inq_buff->data_byte[8];
                }
                drv->block_size = block_size;
-               drv->nr_blocks = total_size;
+               drv->nr_blocks = total_size + 1;
                t = drv->heads * drv->sectors;
                if (t > 1) {
-                       unsigned rem = sector_div(total_size, t);
+                       sector_t real_size = total_size + 1;
+                       unsigned long rem = sector_div(real_size, t);
                        if (rem)
-                               total_size++;
-                       drv->cylinders = total_size;
+                               real_size++;
+                       drv->cylinders = real_size;
                }
        } else {                /* Get geometry failed */
                printk(KERN_WARNING "cciss: reading geometry failed\n");
@@ -1953,16 +1962,16 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
                                ctlr, buf, sizeof(ReadCapdata_struct),
                                        1, logvol, 0, NULL, TYPE_CMD);
        if (return_code == IO_OK) {
-               *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
-               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+               *total_size = be32_to_cpu(*(__be32 *) buf->total_size);
+               *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
-       if (*total_size != (__u32) 0)
+       if (*total_size != 0)
                printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-               (unsigned long long)*total_size, *block_size);
+               (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -1989,15 +1998,15 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
                                1, logvol, 0, NULL, TYPE_CMD);
        }
        if (return_code == IO_OK) {
-               *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
-               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+               *total_size = be64_to_cpu(*(__be64 *) buf->total_size);
+               *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
        printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-              (unsigned long long)*total_size, *block_size);
+              (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -2340,95 +2349,99 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
        if (timeout)
                status = 0;
 
-       if (cmd->err_info->CommandStatus != 0) {        /* an error has occurred */
-               switch (cmd->err_info->CommandStatus) {
-                       unsigned char sense_key;
-               case CMD_TARGET_STATUS:
-                       status = 0;
+       if (cmd->err_info->CommandStatus == 0)  /* no error has occurred */
+               goto after_error_processing;
 
-                       if (cmd->err_info->ScsiStatus == 0x02) {
-                               printk(KERN_WARNING "cciss: cmd %p "
-                                      "has CHECK CONDITION "
-                                      " byte 2 = 0x%x\n", cmd,
-                                      cmd->err_info->SenseInfo[2]
-                                   );
-                               /* check the sense key */
-                               sense_key = 0xf & cmd->err_info->SenseInfo[2];
-                               /* no status or recovered error */
-                               if ((sense_key == 0x0) || (sense_key == 0x1)) {
-                                       status = 1;
-                               }
-                       } else {
-                               printk(KERN_WARNING "cciss: cmd %p "
-                                      "has SCSI Status 0x%x\n",
-                                      cmd, cmd->err_info->ScsiStatus);
+       switch (cmd->err_info->CommandStatus) {
+               unsigned char sense_key;
+       case CMD_TARGET_STATUS:
+               status = 0;
+
+               if (cmd->err_info->ScsiStatus == 0x02) {
+                       printk(KERN_WARNING "cciss: cmd %p "
+                              "has CHECK CONDITION "
+                              " byte 2 = 0x%x\n", cmd,
+                              cmd->err_info->SenseInfo[2]
+                           );
+                       /* check the sense key */
+                       sense_key = 0xf & cmd->err_info->SenseInfo[2];
+                       /* no status or recovered error */
+                       if ((sense_key == 0x0) || (sense_key == 0x1)) {
+                               status = 1;
                        }
-                       break;
-               case CMD_DATA_UNDERRUN:
-                       printk(KERN_WARNING "cciss: cmd %p has"
-                              " completed with data underrun "
-                              "reported\n", cmd);
-                       break;
-               case CMD_DATA_OVERRUN:
-                       printk(KERN_WARNING "cciss: cmd %p has"
-                              " completed with data overrun "
-                              "reported\n", cmd);
-                       break;
-               case CMD_INVALID:
-                       printk(KERN_WARNING "cciss: cmd %p is "
-                              "reported invalid\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_PROTOCOL_ERR:
-                       printk(KERN_WARNING "cciss: cmd %p has "
-                              "protocol error \n", cmd);
-                       status = 0;
-                       break;
-               case CMD_HARDWARE_ERR:
-                       printk(KERN_WARNING "cciss: cmd %p had "
-                              " hardware error\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_CONNECTION_LOST:
-                       printk(KERN_WARNING "cciss: cmd %p had "
-                              "connection lost\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_ABORTED:
-                       printk(KERN_WARNING "cciss: cmd %p was "
-                              "aborted\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_ABORT_FAILED:
-                       printk(KERN_WARNING "cciss: cmd %p reports "
-                              "abort failed\n", cmd);
-                       status = 0;
-                       break;
-               case CMD_UNSOLICITED_ABORT:
-                       printk(KERN_WARNING "cciss%d: unsolicited "
-                              "abort %p\n", h->ctlr, cmd);
-                       if (cmd->retry_count < MAX_CMD_RETRIES) {
-                               retry_cmd = 1;
-                               printk(KERN_WARNING
-                                      "cciss%d: retrying %p\n", h->ctlr, cmd);
-                               cmd->retry_count++;
-                       } else
-                               printk(KERN_WARNING
-                                      "cciss%d: %p retried too "
-                                      "many times\n", h->ctlr, cmd);
-                       status = 0;
-                       break;
-               case CMD_TIMEOUT:
-                       printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
-                       status = 0;
-                       break;
-               default:
-                       printk(KERN_WARNING "cciss: cmd %p returned "
-                              "unknown status %x\n", cmd,
-                              cmd->err_info->CommandStatus);
-                       status = 0;
+               } else {
+                       printk(KERN_WARNING "cciss: cmd %p "
+                              "has SCSI Status 0x%x\n",
+                              cmd, cmd->err_info->ScsiStatus);
                }
+               break;
+       case CMD_DATA_UNDERRUN:
+               printk(KERN_WARNING "cciss: cmd %p has"
+                      " completed with data underrun "
+                      "reported\n", cmd);
+               break;
+       case CMD_DATA_OVERRUN:
+               printk(KERN_WARNING "cciss: cmd %p has"
+                      " completed with data overrun "
+                      "reported\n", cmd);
+               break;
+       case CMD_INVALID:
+               printk(KERN_WARNING "cciss: cmd %p is "
+                      "reported invalid\n", cmd);
+               status = 0;
+               break;
+       case CMD_PROTOCOL_ERR:
+               printk(KERN_WARNING "cciss: cmd %p has "
+                      "protocol error \n", cmd);
+               status = 0;
+               break;
+       case CMD_HARDWARE_ERR:
+               printk(KERN_WARNING "cciss: cmd %p had "
+                      " hardware error\n", cmd);
+               status = 0;
+               break;
+       case CMD_CONNECTION_LOST:
+               printk(KERN_WARNING "cciss: cmd %p had "
+                      "connection lost\n", cmd);
+               status = 0;
+               break;
+       case CMD_ABORTED:
+               printk(KERN_WARNING "cciss: cmd %p was "
+                      "aborted\n", cmd);
+               status = 0;
+               break;
+       case CMD_ABORT_FAILED:
+               printk(KERN_WARNING "cciss: cmd %p reports "
+                      "abort failed\n", cmd);
+               status = 0;
+               break;
+       case CMD_UNSOLICITED_ABORT:
+               printk(KERN_WARNING "cciss%d: unsolicited "
+                      "abort %p\n", h->ctlr, cmd);
+               if (cmd->retry_count < MAX_CMD_RETRIES) {
+                       retry_cmd = 1;
+                       printk(KERN_WARNING
+                              "cciss%d: retrying %p\n", h->ctlr, cmd);
+                       cmd->retry_count++;
+               } else
+                       printk(KERN_WARNING
+                              "cciss%d: %p retried too "
+                              "many times\n", h->ctlr, cmd);
+               status = 0;
+               break;
+       case CMD_TIMEOUT:
+               printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
+               status = 0;
+               break;
+       default:
+               printk(KERN_WARNING "cciss: cmd %p returned "
+                      "unknown status %x\n", cmd,
+                      cmd->err_info->CommandStatus);
+               status = 0;
        }
+
+after_error_processing:
+
        /* We need to return this command */
        if (retry_cmd) {
                resend_cciss_cmd(h, cmd);
@@ -3119,8 +3132,9 @@ static void cciss_getgeometry(int cntl_num)
                }
                cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
 
-               /* total_size = last LBA + 1 */
-               if(total_size == (__u32) 0) {
+               /* If read_capacity returns all F's the logical is >2TB */
+               /* so we switch to 16-byte CDBs for all read/write ops */
+               if(total_size == 0xFFFFFFFFULL) {
                        cciss_read_capacity_16(cntl_num, i, 0,
                        &total_size, &block_size);
                        hba[cntl_num]->cciss_read = CCISS_READ_16;
@@ -3395,7 +3409,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        return -1;
 }
 
-static void __devexit cciss_remove_one(struct pci_dev *pdev)
+static void cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *tmp_ptr;
        int i, j;
@@ -3413,15 +3427,35 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
                       "already be removed \n");
                return;
        }
+
+       remove_proc_entry(hba[i]->devname, proc_cciss);
+       unregister_blkdev(hba[i]->major, hba[i]->devname);
+
+       /* remove it from the disk list */
+       for (j = 0; j < CISS_MAX_LUN; j++) {
+               struct gendisk *disk = hba[i]->gendisk[j];
+               if (disk) {
+                       request_queue_t *q = disk->queue;
+
+                       if (disk->flags & GENHD_FL_UP)
+                               del_gendisk(disk);
+                       if (q)
+                               blk_cleanup_queue(q);
+               }
+       }
+
+       cciss_unregister_scsi(i);       /* unhook from SCSI subsystem */
+
        /* Turn board interrupts off  and send the flush cache command */
        /* sendcmd will turn off interrupt, and send the flush...
         * To write all data in the battery backed cache to disks */
        memset(flush_buf, 0, 4);
        return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
                              TYPE_CMD);
-       if (return_code != IO_OK) {
-               printk(KERN_WARNING "Error Flushing cache on controller %d\n",
-                      i);
+       if (return_code == IO_OK) {
+               printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+       } else {
+               printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
        }
        free_irq(hba[i]->intr[2], hba[i]);
 
@@ -3433,22 +3467,6 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
 #endif                         /* CONFIG_PCI_MSI */
 
        iounmap(hba[i]->vaddr);
-       cciss_unregister_scsi(i);       /* unhook from SCSI subsystem */
-       unregister_blkdev(hba[i]->major, hba[i]->devname);
-       remove_proc_entry(hba[i]->devname, proc_cciss);
-
-       /* remove it from the disk list */
-       for (j = 0; j < CISS_MAX_LUN; j++) {
-               struct gendisk *disk = hba[i]->gendisk[j];
-               if (disk) {
-                       request_queue_t *q = disk->queue;
-
-                       if (disk->flags & GENHD_FL_UP)
-                               del_gendisk(disk);
-                       if (q)
-                               blk_cleanup_queue(q);
-               }
-       }
 
        pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct),
                            hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
@@ -3472,6 +3490,7 @@ static struct pci_driver cciss_pci_driver = {
        .probe = cciss_init_one,
        .remove = __devexit_p(cciss_remove_one),
        .id_table = cciss_pci_device_id,        /* id_table */
+       .shutdown = cciss_remove_one,
 };
 
 /*