aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorMike Miller <mike.miller@hp.com>2009-04-02 15:50:55 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-04-07 02:12:38 -0400
commit0a9279cc7cbe726e995c44a1acae81d446775816 (patch)
tree80b7eb06a7629f6e0ab0c865f791b6a421a0ef6e /drivers/block
parentac44e5b2ed62bf4acf9df84575d3f18c7a6fdf22 (diff)
cciss: kernel scan thread for MSA2012
The MSA2012 cannot inform the driver of configuration changes since all management is out of band. This is a departure from any storage we have supported in the past. We need some way to detect changes on the topology so we implement this kernel thread. In some instances there's nothing we can do from the driver (like LUN failure) so just print out a message. In the case where logical volumes are added or deleted we call rebuild_lun_table to refresh the driver's view of the world. Signed-off-by: Mike Miller <mike.miller@hp.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss.c88
-rw-r--r--drivers/block/cciss.h2
-rw-r--r--drivers/block/cciss_cmd.h23
3 files changed, 111 insertions, 2 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index f15b17708537..4e5441baa49d 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))) {
@@ -2593,12 +2605,14 @@ static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
2593 ((driver_byte & 0xff) << 24); 2605 ((driver_byte & 0xff) << 24);
2594} 2606}
2595 2607
2596static 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)
2597{ 2610{
2598 unsigned char sense_key; 2611 unsigned char sense_key;
2599 unsigned char status_byte, msg_byte, host_byte, driver_byte; 2612 unsigned char status_byte, msg_byte, host_byte, driver_byte;
2600 int error_value; 2613 int error_value;
2601 2614
2615 *retry_cmd = 0;
2602 /* 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 */
2603 status_byte = cmd->err_info->ScsiStatus; 2617 status_byte = cmd->err_info->ScsiStatus;
2604 driver_byte = DRIVER_OK; 2618 driver_byte = DRIVER_OK;
@@ -2626,6 +2640,11 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
2626 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))
2627 error_value = 0; 2641 error_value = 0;
2628 2642
2643 if (check_for_unit_attention(h, cmd)) {
2644 *retry_cmd = !blk_pc_request(cmd->rq);
2645 return 0;
2646 }
2647
2629 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ 2648 if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */
2630 if (error_value != 0) 2649 if (error_value != 0)
2631 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" 2650 printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION"
@@ -2665,7 +2684,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
2665 2684
2666 switch (cmd->err_info->CommandStatus) { 2685 switch (cmd->err_info->CommandStatus) {
2667 case CMD_TARGET_STATUS: 2686 case CMD_TARGET_STATUS:
2668 rq->errors = evaluate_target_status(cmd); 2687 rq->errors = evaluate_target_status(h, cmd, &retry_cmd);
2669 break; 2688 break;
2670 case CMD_DATA_UNDERRUN: 2689 case CMD_DATA_UNDERRUN:
2671 if (blk_fs_request(cmd->rq)) { 2690 if (blk_fs_request(cmd->rq)) {
@@ -3016,6 +3035,63 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
3016 return IRQ_HANDLED; 3035 return IRQ_HANDLED;
3017} 3036}
3018 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
3019/* 3095/*
3020 * We cannot read the structure directly, for portability we must use 3096 * We cannot read the structure directly, for portability we must use
3021 * the io functions. 3097 * the io functions.
@@ -3761,6 +3837,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
3761 hba[i]->busy_initializing = 0; 3837 hba[i]->busy_initializing = 0;
3762 3838
3763 rebuild_lun_table(hba[i], 1); 3839 rebuild_lun_table(hba[i], 1);
3840 hba[i]->cciss_scan_thread = kthread_run(scan_thread, hba[i],
3841 "cciss_scan%02d", i);
3842 if (IS_ERR(hba[i]->cciss_scan_thread))
3843 return PTR_ERR(hba[i]->cciss_scan_thread);
3844
3764 return 1; 3845 return 1;
3765 3846
3766clean4: 3847clean4:
@@ -3836,6 +3917,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
3836 printk(KERN_ERR "cciss: Unable to remove device \n"); 3917 printk(KERN_ERR "cciss: Unable to remove device \n");
3837 return; 3918 return;
3838 } 3919 }
3920
3839 tmp_ptr = pci_get_drvdata(pdev); 3921 tmp_ptr = pci_get_drvdata(pdev);
3840 i = tmp_ptr->ctlr; 3922 i = tmp_ptr->ctlr;
3841 if (hba[i] == NULL) { 3923 if (hba[i] == NULL) {
@@ -3844,6 +3926,8 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
3844 return; 3926 return;
3845 } 3927 }
3846 3928
3929 kthread_stop(hba[i]->cciss_scan_thread);
3930
3847 remove_proc_entry(hba[i]->devname, proc_cciss); 3931 remove_proc_entry(hba[i]->devname, proc_cciss);
3848 unregister_blkdev(hba[i]->major, hba[i]->devname); 3932 unregister_blkdev(hba[i]->major, hba[i]->devname);
3849 3933
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 15e2b84734e3..703e08038fb9 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -121,6 +121,8 @@ struct ctlr_info
121 struct sendcmd_reject_list scsi_rejects; 121 struct sendcmd_reject_list scsi_rejects;
122#endif 122#endif
123 unsigned char alive; 123 unsigned char alive;
124 struct completion *rescan_wait;
125 struct task_struct *cciss_scan_thread;
124}; 126};
125 127
126/* Defining the diffent access_menthods */ 128/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 24e22dea1a99..40b1b92dae7f 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -25,6 +25,29 @@
25#define CMD_TIMEOUT 0x000B 25#define CMD_TIMEOUT 0x000B
26#define CMD_UNABORTABLE 0x000C 26#define CMD_UNABORTABLE 0x000C
27 27
28/* Unit Attentions ASC's as defined for the MSA2012sa */
29#define POWER_OR_RESET 0x29
30#define STATE_CHANGED 0x2a
31#define UNIT_ATTENTION_CLEARED 0x2f
32#define LUN_FAILED 0x3e
33#define REPORT_LUNS_CHANGED 0x3f
34
35/* Unit Attentions ASCQ's as defined for the MSA2012sa */
36
37 /* These ASCQ's defined for ASC = POWER_OR_RESET */
38#define POWER_ON_RESET 0x00
39#define POWER_ON_REBOOT 0x01
40#define SCSI_BUS_RESET 0x02
41#define MSA_TARGET_RESET 0x03
42#define CONTROLLER_FAILOVER 0x04
43#define TRANSCEIVER_SE 0x05
44#define TRANSCEIVER_LVD 0x06
45
46 /* These ASCQ's defined for ASC = STATE_CHANGED */
47#define RESERVATION_PREEMPTED 0x03
48#define ASYM_ACCESS_CHANGED 0x06
49#define LUN_CAPACITY_CHANGED 0x09
50
28//transfer direction 51//transfer direction
29#define XFER_NONE 0x00 52#define XFER_NONE 0x00
30#define XFER_WRITE 0x01 53#define XFER_WRITE 0x01