aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 14:06:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 14:06:41 -0400
commit6a5d263866d699ebf6843105497afc86ee53de5b (patch)
tree439195e272631908cdc2e3e44abaf7e1c3447157 /drivers/block/cciss.c
parentaeeae86859f4319de0a4946b44771d9926eeed54 (diff)
parentffcd7dca3ab78f9f425971756e5e90024157f6be (diff)
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* '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
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c117
1 files changed, 109 insertions, 8 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index a6c55432819b..0ef6f08aa6ea 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -51,6 +51,7 @@
51#include <scsi/scsi_ioctl.h> 51#include <scsi/scsi_ioctl.h>
52#include <linux/cdrom.h> 52#include <linux/cdrom.h>
53#include <linux/scatterlist.h> 53#include <linux/scatterlist.h>
54#include <linux/kthread.h>
54 55
55#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) 56#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
56#define DRIVER_NAME "HP CISS Driver (v 3.6.20)" 57#define DRIVER_NAME "HP CISS Driver (v 3.6.20)"
@@ -186,6 +187,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
186 __u8 page_code, int cmd_type); 187 __u8 page_code, int cmd_type);
187 188
188static void fail_all_cmds(unsigned long ctlr); 189static void fail_all_cmds(unsigned long ctlr);
190static int scan_thread(void *data);
191static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c);
189 192
190#ifdef CONFIG_PROC_FS 193#ifdef CONFIG_PROC_FS
191static void cciss_procinit(int i); 194static void cciss_procinit(int i);
@@ -735,6 +738,12 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
735 return 0; 738 return 0;
736} 739}
737 740
741static void check_ioctl_unit_attention(ctlr_info_t *host, CommandList_struct *c)
742{
743 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
744 c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
745 (void)check_for_unit_attention(host, c);
746}
738/* 747/*
739 * ioctl 748 * ioctl
740 */ 749 */
@@ -1029,6 +1038,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1029 iocommand.buf_size, 1038 iocommand.buf_size,
1030 PCI_DMA_BIDIRECTIONAL); 1039 PCI_DMA_BIDIRECTIONAL);
1031 1040
1041 check_ioctl_unit_attention(host, c);
1042
1032 /* Copy the error information out */ 1043 /* Copy the error information out */
1033 iocommand.error_info = *(c->err_info); 1044 iocommand.error_info = *(c->err_info);
1034 if (copy_to_user 1045 if (copy_to_user
@@ -1180,6 +1191,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1180 (dma_addr_t) temp64.val, buff_size[i], 1191 (dma_addr_t) temp64.val, buff_size[i],
1181 PCI_DMA_BIDIRECTIONAL); 1192 PCI_DMA_BIDIRECTIONAL);
1182 } 1193 }
1194 check_ioctl_unit_attention(host, c);
1183 /* Copy the error information out */ 1195 /* Copy the error information out */
1184 ioc->error_info = *(c->err_info); 1196 ioc->error_info = *(c->err_info);
1185 if (copy_to_user(argp, ioc, sizeof(*ioc))) { 1197 if (copy_to_user(argp, ioc, sizeof(*ioc))) {
@@ -1287,6 +1299,7 @@ static void cciss_softirq_done(struct request *rq)
1287{ 1299{
1288 CommandList_struct *cmd = rq->completion_data; 1300 CommandList_struct *cmd = rq->completion_data;
1289 ctlr_info_t *h = hba[cmd->ctlr]; 1301 ctlr_info_t *h = hba[cmd->ctlr];
1302 unsigned int nr_bytes;
1290 unsigned long flags; 1303 unsigned long flags;
1291 u64bit temp64; 1304 u64bit temp64;
1292 int i, ddir; 1305 int i, ddir;
@@ -1308,7 +1321,14 @@ static void cciss_softirq_done(struct request *rq)
1308 printk("Done with %p\n", rq); 1321 printk("Done with %p\n", rq);
1309#endif /* CCISS_DEBUG */ 1322#endif /* CCISS_DEBUG */
1310 1323
1311 if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq))) 1324 /*
1325 * Store the full size and set the residual count for pc requests
1326 */
1327 nr_bytes = blk_rq_bytes(rq);
1328 if (blk_pc_request(rq))
1329 rq->data_len = cmd->err_info->ResidualCnt;
1330
1331 if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes))
1312 BUG(); 1332 BUG();
1313 1333
1314 spin_lock_irqsave(&h->lock, flags); 1334 spin_lock_irqsave(&h->lock, flags);
@@ -2585,12 +2605,14 @@ static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
2585 ((driver_byte & 0xff) << 24); 2605 ((driver_byte & 0xff) << 24);
2586} 2606}
2587 2607
2588static inline int evaluate_target_status(CommandList_struct *cmd) 2608static inline int evaluate_target_status(ctlr_info_t *h,
2609 CommandList_struct *cmd, int *retry_cmd)
2589{ 2610{
2590 unsigned char sense_key; 2611 unsigned char sense_key;
2591 unsigned char status_byte, msg_byte, host_byte, driver_byte; 2612 unsigned char status_byte, msg_byte, host_byte, driver_byte;
2592 int error_value; 2613 int error_value;
2593 2614
2615 *retry_cmd = 0;
2594 /* If we get in here, it means we got "target status", that is, scsi status */ 2616 /* If we get in here, it means we got "target status", that is, scsi status */
2595 status_byte = cmd->err_info->ScsiStatus; 2617 status_byte = cmd->err_info->ScsiStatus;
2596 driver_byte = DRIVER_OK; 2618 driver_byte = DRIVER_OK;
@@ -2618,6 +2640,11 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
2618 if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq)) 2640 if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq))
2619 error_value = 0; 2641 error_value = 0;
2620 2642
2643 if (check_for_unit_attention(h, cmd)) {
2644 *retry_cmd = !blk_pc_request(cmd->rq);
2645 return 0;
2646 }
2647
2621 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ 2648 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
2622 if (error_value != 0) 2649 if (error_value != 0)
2623 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" 2650 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
@@ -2657,7 +2684,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2657 2684
2658 switch (cmd->err_info->CommandStatus) { 2685 switch (cmd->err_info->CommandStatus) {
2659 case CMD_TARGET_STATUS: 2686 case CMD_TARGET_STATUS:
2660 rq->errors = evaluate_target_status(cmd); 2687 rq->errors = evaluate_target_status(h, cmd, &retry_cmd);
2661 break; 2688 break;
2662 case CMD_DATA_UNDERRUN: 2689 case CMD_DATA_UNDERRUN:
2663 if (blk_fs_request(cmd->rq)) { 2690 if (blk_fs_request(cmd->rq)) {
@@ -3008,6 +3035,63 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
3008 return IRQ_HANDLED; 3035 return IRQ_HANDLED;
3009} 3036}
3010 3037
3038static int scan_thread(void *data)
3039{
3040 ctlr_info_t *h = data;
3041 int rc;
3042 DECLARE_COMPLETION_ONSTACK(wait);
3043 h->rescan_wait = &wait;
3044
3045 for (;;) {
3046 rc = wait_for_completion_interruptible(&wait);
3047 if (kthread_should_stop())
3048 break;
3049 if (!rc)
3050 rebuild_lun_table(h, 0);
3051 }
3052 return 0;
3053}
3054
3055static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c)
3056{
3057 if (c->err_info->SenseInfo[2] != UNIT_ATTENTION)
3058 return 0;
3059
3060 switch (c->err_info->SenseInfo[12]) {
3061 case STATE_CHANGED:
3062 printk(KERN_WARNING "cciss%d: a state change "
3063 "detected, command retried\n", h->ctlr);
3064 return 1;
3065 break;
3066 case LUN_FAILED:
3067 printk(KERN_WARNING "cciss%d: LUN failure "
3068 "detected, action required\n", h->ctlr);
3069 return 1;
3070 break;
3071 case REPORT_LUNS_CHANGED:
3072 printk(KERN_WARNING "cciss%d: report LUN data "
3073 "changed\n", h->ctlr);
3074 if (h->rescan_wait)
3075 complete(h->rescan_wait);
3076 return 1;
3077 break;
3078 case POWER_OR_RESET:
3079 printk(KERN_WARNING "cciss%d: a power on "
3080 "or device reset detected\n", h->ctlr);
3081 return 1;
3082 break;
3083 case UNIT_ATTENTION_CLEARED:
3084 printk(KERN_WARNING "cciss%d: unit attention "
3085 "cleared by another initiator\n", h->ctlr);
3086 return 1;
3087 break;
3088 default:
3089 printk(KERN_WARNING "cciss%d: unknown "
3090 "unit attention detected\n", h->ctlr);
3091 return 1;
3092 }
3093}
3094
3011/* 3095/*
3012 * We cannot read the structure directly, for portability we must use 3096 * We cannot read the structure directly, for portability we must use
3013 * the io functions. 3097 * the io functions.
@@ -3181,12 +3265,21 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
3181 */ 3265 */
3182 cciss_interrupt_mode(c, pdev, board_id); 3266 cciss_interrupt_mode(c, pdev, board_id);
3183 3267
3184 /* 3268 /* find the memory BAR */
3185 * Memory base addr is first addr , the second points to the config 3269 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
3186 * table 3270 if (pci_resource_flags(pdev, i) & IORESOURCE_MEM)
3187 */ 3271 break;
3272 }
3273 if (i == DEVICE_COUNT_RESOURCE) {
3274 printk(KERN_WARNING "cciss: No memory BAR found\n");
3275 err = -ENODEV;
3276 goto err_out_free_res;
3277 }
3278
3279 c->paddr = pci_resource_start(pdev, i); /* addressing mode bits
3280 * already removed
3281 */
3188 3282
3189 c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
3190#ifdef CCISS_DEBUG 3283#ifdef CCISS_DEBUG
3191 printk("address 0 = %lx\n", c->paddr); 3284 printk("address 0 = %lx\n", c->paddr);
3192#endif /* CCISS_DEBUG */ 3285#endif /* CCISS_DEBUG */
@@ -3753,6 +3846,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
3753 hba[i]->busy_initializing = 0; 3846 hba[i]->busy_initializing = 0;
3754 3847
3755 rebuild_lun_table(hba[i], 1); 3848 rebuild_lun_table(hba[i], 1);
3849 hba[i]->cciss_scan_thread = kthread_run(scan_thread, hba[i],
3850 "cciss_scan%02d", i);
3851 if (IS_ERR(hba[i]->cciss_scan_thread))
3852 return PTR_ERR(hba[i]->cciss_scan_thread);
3853
3756 return 1; 3854 return 1;
3757 3855
3758clean4: 3856clean4:
@@ -3828,6 +3926,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
3828 printk(KERN_ERR "cciss: Unable to remove device \n"); 3926 printk(KERN_ERR "cciss: Unable to remove device \n");
3829 return; 3927 return;
3830 } 3928 }
3929
3831 tmp_ptr = pci_get_drvdata(pdev); 3930 tmp_ptr = pci_get_drvdata(pdev);
3832 i = tmp_ptr->ctlr; 3931 i = tmp_ptr->ctlr;
3833 if (hba[i] == NULL) { 3932 if (hba[i] == NULL) {
@@ -3836,6 +3935,8 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
3836 return; 3935 return;
3837 } 3936 }
3838 3937
3938 kthread_stop(hba[i]->cciss_scan_thread);
3939
3839 remove_proc_entry(hba[i]->devname, proc_cciss); 3940 remove_proc_entry(hba[i]->devname, proc_cciss);
3840 unregister_blkdev(hba[i]->major, hba[i]->devname); 3941 unregister_blkdev(hba[i]->major, hba[i]->devname);
3841 3942