aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
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