Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142739
b: refs/heads/master
c: 0a9279c
h: refs/heads/master
i:
  142737: 0e9ed54
  142735: 25d3192
v: v3
  • Loading branch information
Mike Miller authored and Jens Axboe committed Apr 7, 2009
1 parent a388fa6 commit fb73377
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ac44e5b2ed62bf4acf9df84575d3f18c7a6fdf22
refs/heads/master: 0a9279cc7cbe726e995c44a1acae81d446775816
88 changes: 86 additions & 2 deletions trunk/drivers/block/cciss.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +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)"
Expand Down Expand Up @@ -186,6 +187,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
__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);
Expand Down Expand Up @@ -735,6 +738,12 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
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
*/
Expand Down Expand Up @@ -1029,6 +1038,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
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
Expand Down Expand Up @@ -1180,6 +1191,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
(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))) {
Expand Down Expand Up @@ -2593,12 +2605,14 @@ static inline unsigned int make_status_bytes(unsigned int scsi_status_byte,
((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;
Expand Down Expand Up @@ -2626,6 +2640,11 @@ static inline int evaluate_target_status(CommandList_struct *cmd)
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"
Expand Down Expand Up @@ -2665,7 +2684,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,

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)) {
Expand Down Expand Up @@ -3016,6 +3035,63 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id)
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.
Expand Down Expand Up @@ -3761,6 +3837,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
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:
Expand Down Expand Up @@ -3836,6 +3917,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
printk(KERN_ERR "cciss: Unable to remove device \n");
return;
}

tmp_ptr = pci_get_drvdata(pdev);
i = tmp_ptr->ctlr;
if (hba[i] == NULL) {
Expand All @@ -3844,6 +3926,8 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
return;
}

kthread_stop(hba[i]->cciss_scan_thread);

remove_proc_entry(hba[i]->devname, proc_cciss);
unregister_blkdev(hba[i]->major, hba[i]->devname);

Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/block/cciss.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ struct ctlr_info
struct sendcmd_reject_list scsi_rejects;
#endif
unsigned char alive;
struct completion *rescan_wait;
struct task_struct *cciss_scan_thread;
};

/* Defining the diffent access_menthods */
Expand Down
23 changes: 23 additions & 0 deletions trunk/drivers/block/cciss_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@
#define CMD_TIMEOUT 0x000B
#define CMD_UNABORTABLE 0x000C

/* Unit Attentions ASC's as defined for the MSA2012sa */
#define POWER_OR_RESET 0x29
#define STATE_CHANGED 0x2a
#define UNIT_ATTENTION_CLEARED 0x2f
#define LUN_FAILED 0x3e
#define REPORT_LUNS_CHANGED 0x3f

/* Unit Attentions ASCQ's as defined for the MSA2012sa */

/* These ASCQ's defined for ASC = POWER_OR_RESET */
#define POWER_ON_RESET 0x00
#define POWER_ON_REBOOT 0x01
#define SCSI_BUS_RESET 0x02
#define MSA_TARGET_RESET 0x03
#define CONTROLLER_FAILOVER 0x04
#define TRANSCEIVER_SE 0x05
#define TRANSCEIVER_LVD 0x06

/* These ASCQ's defined for ASC = STATE_CHANGED */
#define RESERVATION_PREEMPTED 0x03
#define ASYM_ACCESS_CHANGED 0x06
#define LUN_CAPACITY_CHANGED 0x09

//transfer direction
#define XFER_NONE 0x00
#define XFER_WRITE 0x01
Expand Down

0 comments on commit fb73377

Please sign in to comment.