From 862794fa3fd4c8a44ee22582418736c93e0d3c3a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 21 Feb 2007 09:28:00 +0100 Subject: [SCSI] zfcp: fix likely/unlikely usage zfcp_fsf_protstatus_eval() takes always the 'wrong' branch. Likely Profiling Results --------------------------------------------------------- [+- ] Type | # True | # False | Function:Filename@Line +unlikely | 11042| 0 zfcp_fsf_protstatus_eval() Acked-by: Swen Schillig Signed-off-by: Heiko Carstens Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index ef16f7ca4bb..4c0a59afd5c 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -299,9 +299,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) } /* log additional information provided by FSF (if any) */ - if (unlikely(qtcb->header.log_length)) { + if (likely(qtcb->header.log_length)) { /* do not trust them ;-) */ - if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) { + if (unlikely(qtcb->header.log_start > + sizeof(struct fsf_qtcb))) { ZFCP_LOG_NORMAL ("bug: ULP (FSF logging) log data starts " "beyond end of packet header. Ignored. " @@ -310,8 +311,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) sizeof(struct fsf_qtcb)); goto forget_log; } - if ((size_t) (qtcb->header.log_start + qtcb->header.log_length) - > sizeof(struct fsf_qtcb)) { + if (unlikely((size_t) (qtcb->header.log_start + + qtcb->header.log_length) > + sizeof(struct fsf_qtcb))) { ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " "beyond end of packet header. Ignored. " "(start=%i, length=%i, size=%li)\n", -- cgit v1.2.3 From 684b7fe976554d12e6266d7280c87a0f3feff02e Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 27 Feb 2007 22:39:44 -0500 Subject: [SCSI] constants.c: cleanup, verbose result printing Clean up constants.c and make result printing more user friendly: - Refactor the command and sense functions so that the actual formatting can be called from the various helper functions with the correct prefix. - Replace scsi_print_hostbyte() and scsi_print_driverbyte() with scsi_print_result() which is verbose when CONFIG_SCSI_CONSTANTS is on. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 267 +++++++++++++++++++++++++---------------------- include/scsi/scsi_dbg.h | 10 +- 2 files changed, 151 insertions(+), 126 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 61f6024b61b..611487545af 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -202,31 +202,29 @@ static const char * get_sa_name(const struct value_name_pair * arr, } /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */ -static void print_opcode_name(unsigned char * cdbp, int cdb_len, - int start_of_line) +static void print_opcode_name(unsigned char * cdbp, int cdb_len) { int sa, len, cdb0; const char * name; - const char * leadin = start_of_line ? KERN_INFO : ""; cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: len = cdbp[7] + 8; if (len < 10) { - printk("%sshort variable length command, " - "len=%d ext_len=%d", leadin, len, cdb_len); + printk("short variable length command, " + "len=%d ext_len=%d", len, cdb_len); break; } sa = (cdbp[8] << 8) + cdbp[9]; name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa); if (name) { - printk("%s%s", leadin, name); + printk("%s", name); if ((cdb_len > 0) && (len != cdb_len)) printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len); } else { - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); if ((cdb_len > 0) && (len != cdb_len)) printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len); @@ -236,83 +234,80 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len, sa = cdbp[1] & 0x1f; name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; case MAINTENANCE_OUT: sa = cdbp[1] & 0x1f; name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; case SERVICE_ACTION_IN_12: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; case SERVICE_ACTION_OUT_12: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; case SERVICE_ACTION_IN_16: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; case SERVICE_ACTION_OUT_16: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa); if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; default: if (cdb0 < 0xc0) { name = cdb_byte0_names[cdb0]; if (name) - printk("%s%s", leadin, name); + printk("%s", name); else - printk("%scdb[0]=0x%x (reserved)", - leadin, cdb0); + printk("cdb[0]=0x%x (reserved)", cdb0); } else - printk("%scdb[0]=0x%x (vendor)", leadin, cdb0); + printk("cdb[0]=0x%x (vendor)", cdb0); break; } } #else /* ifndef CONFIG_SCSI_CONSTANTS */ -static void print_opcode_name(unsigned char * cdbp, int cdb_len, - int start_of_line) +static void print_opcode_name(unsigned char * cdbp, int cdb_len) { int sa, len, cdb0; - const char * leadin = start_of_line ? KERN_INFO : ""; cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: len = cdbp[7] + 8; if (len < 10) { - printk("%sshort opcode=0x%x command, len=%d " - "ext_len=%d", leadin, cdb0, len, cdb_len); + printk("short opcode=0x%x command, len=%d " + "ext_len=%d", cdb0, len, cdb_len); break; } sa = (cdbp[8] << 8) + cdbp[9]; - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); if (len != cdb_len) printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len); break; @@ -323,49 +318,48 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len, case SERVICE_ACTION_IN_16: case SERVICE_ACTION_OUT_16: sa = cdbp[1] & 0x1f; - printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa); + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; default: if (cdb0 < 0xc0) - printk("%scdb[0]=0x%x", leadin, cdb0); + printk("cdb[0]=0x%x", cdb0); else - printk("%scdb[0]=0x%x (vendor)", leadin, cdb0); + printk("cdb[0]=0x%x (vendor)", cdb0); break; } } #endif -void __scsi_print_command(unsigned char *command) +void __scsi_print_command(unsigned char *cdb) { int k, len; - print_opcode_name(command, 0, 1); - if (VARIABLE_LENGTH_CMD == command[0]) - len = command[7] + 8; + print_opcode_name(cdb, 0); + if (VARIABLE_LENGTH_CMD == cdb[0]) + len = cdb[7] + 8; else - len = COMMAND_SIZE(command[0]); + len = COMMAND_SIZE(cdb[0]); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) - printk(" %02x", command[k]); + printk(" %02x", cdb[k]); printk("\n"); } EXPORT_SYMBOL(__scsi_print_command); -/* This function (perhaps with the addition of peripheral device type) - * is more approriate than __scsi_print_command(). Perhaps that static - * can be dropped later if it replaces the __scsi_print_command version. - */ -static void scsi_print_cdb(unsigned char *cdb, int cdb_len, int start_of_line) +void scsi_print_command(struct scsi_cmnd *cmd) { int k; - print_opcode_name(cdb, cdb_len, start_of_line); + scmd_printk(KERN_INFO, cmd, "CDB: "); + print_opcode_name(cmd->cmnd, cmd->cmd_len); + /* print out all bytes in cdb */ printk(":"); - for (k = 0; k < cdb_len; ++k) - printk(" %02x", cdb[k]); + for (k = 0; k < cmd->cmd_len; ++k) + printk(" %02x", cmd->cmnd[k]); printk("\n"); } +EXPORT_SYMBOL(scsi_print_command); /** * @@ -1176,67 +1170,77 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq) { } EXPORT_SYMBOL(scsi_extd_sense_format); -/* Print extended sense information; no leadin, no linefeed */ -static void +void scsi_show_extd_sense(unsigned char asc, unsigned char ascq) { - const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq); + const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq); if (extd_sense_fmt) { if (strstr(extd_sense_fmt, "%x")) { - printk("Additional sense: "); + printk("Add. Sense: "); printk(extd_sense_fmt, ascq); } else - printk("Additional sense: %s", extd_sense_fmt); + printk("Add. Sense: %s", extd_sense_fmt); } else { if (asc >= 0x80) - printk("<> ASC=0x%x ASCQ=0x%x", asc, ascq); + printk("<> ASC=0x%x ASCQ=0x%x", asc, + ascq); if (ascq >= 0x80) - printk("ASC=0x%x <> ASCQ=0x%x", asc, ascq); + printk("ASC=0x%x <> ASCQ=0x%x", asc, + ascq); else printk("ASC=0x%x ASCQ=0x%x", asc, ascq); } + + printk("\n"); } +EXPORT_SYMBOL(scsi_show_extd_sense); void -scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) +scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr) { const char *sense_txt; - /* An example of deferred is when an earlier write to disk cache - * succeeded, but now the disk discovers that it cannot write the - * data to the magnetic media. - */ - const char *error = scsi_sense_is_deferred(sshdr) ? - "<>" : "Current"; - printk(KERN_INFO "%s: %s", name, error); - if (sshdr->response_code >= 0x72) - printk(" [descriptor]"); sense_txt = scsi_sense_key_string(sshdr->sense_key); if (sense_txt) - printk(": sense key: %s\n", sense_txt); + printk("Sense Key : %s ", sense_txt); else - printk(": sense key=0x%x\n", sshdr->sense_key); - printk(KERN_INFO " "); - scsi_show_extd_sense(sshdr->asc, sshdr->ascq); + printk("Sense Key : 0x%x ", sshdr->sense_key); + + printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " : + "[current] "); + + if (sshdr->response_code >= 0x72) + printk("[descriptor]"); + printk("\n"); } +EXPORT_SYMBOL(scsi_show_sense_hdr); + +/* + * Print normalized SCSI sense header with a prefix. + */ +void +scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) +{ + printk(KERN_INFO "%s: ", name); + scsi_show_sense_hdr(sshdr); + printk(KERN_INFO "%s: ", name); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); +} EXPORT_SYMBOL(scsi_print_sense_hdr); -/* Print sense information */ void -__scsi_print_sense(const char *name, const unsigned char *sense_buffer, - int sense_len) +scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, + struct scsi_sense_hdr *sshdr) { int k, num, res; - unsigned int info; - struct scsi_sense_hdr ssh; - res = scsi_normalize_sense(sense_buffer, sense_len, &ssh); + res = scsi_normalize_sense(sense_buffer, sense_len, sshdr); if (0 == res) { /* this may be SCSI-1 sense data */ num = (sense_len < 32) ? sense_len : 32; - printk(KERN_INFO "Unrecognized sense data (in hex):"); + printk("Unrecognized sense data (in hex):"); for (k = 0; k < num; ++k) { if (0 == (k % 16)) { printk("\n"); @@ -1247,11 +1251,20 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, printk("\n"); return; } - scsi_print_sense_hdr(name, &ssh); - if (ssh.response_code < 0x72) { +} + +void +scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, + struct scsi_sense_hdr *sshdr) +{ + int k, num, res; + + if (sshdr->response_code < 0x72) + { /* only decode extras for "fixed" format now */ char buff[80]; int blen, fixed_valid; + unsigned int info; fixed_valid = sense_buffer[0] & 0x80; info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) | @@ -1281,13 +1294,13 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, res += snprintf(buff + res, blen - res, "ILI"); } if (res > 0) - printk(KERN_INFO "%s\n", buff); - } else if (ssh.additional_length > 0) { + printk("%s\n", buff); + } else if (sshdr->additional_length > 0) { /* descriptor format with sense descriptors */ - num = 8 + ssh.additional_length; + num = 8 + sshdr->additional_length; num = (sense_len < num) ? sense_len : num; - printk(KERN_INFO "Descriptor sense data with sense " - "descriptors (in hex):"); + printk("Descriptor sense data with sense descriptors " + "(in hex):"); for (k = 0; k < num; ++k) { if (0 == (k % 16)) { printk("\n"); @@ -1295,29 +1308,42 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, } printk("%02x ", sense_buffer[k]); } + printk("\n"); } + } -EXPORT_SYMBOL(__scsi_print_sense); -void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd) +/* Normalize and print sense buffer with name prefix */ +void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, + int sense_len) { - const char *name = devclass; - - if (cmd->request->rq_disk) - name = cmd->request->rq_disk->disk_name; - __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); + struct scsi_sense_hdr sshdr; + + printk(KERN_INFO "%s: ", name); + scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr); + scsi_show_sense_hdr(&sshdr); + scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr); + printk(KERN_INFO "%s: ", name); + scsi_show_extd_sense(sshdr.asc, sshdr.ascq); } -EXPORT_SYMBOL(scsi_print_sense); +EXPORT_SYMBOL(__scsi_print_sense); -void scsi_print_command(struct scsi_cmnd *cmd) +/* Normalize and print sense buffer in SCSI command */ +void scsi_print_sense(char *name, struct scsi_cmnd *cmd) { - /* Assume appended output (i.e. not at start of line) */ - sdev_printk("", cmd->device, "\n"); - printk(KERN_INFO " command: "); - scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0); + struct scsi_sense_hdr sshdr; + + scmd_printk(KERN_INFO, cmd, ""); + scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, + &sshdr); + scsi_show_sense_hdr(&sshdr); + scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, + &sshdr); + scmd_printk(KERN_INFO, cmd, ""); + scsi_show_extd_sense(sshdr.asc, sshdr.ascq); } -EXPORT_SYMBOL(scsi_print_command); +EXPORT_SYMBOL(scsi_print_sense); #ifdef CONFIG_SCSI_CONSTANTS @@ -1327,25 +1353,6 @@ static const char * const hostbyte_table[]={ "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"}; #define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table) -void scsi_print_hostbyte(int scsiresult) -{ - int hb = host_byte(scsiresult); - - printk("Hostbyte=0x%02x", hb); - if (hb < NUM_HOSTBYTE_STRS) - printk("(%s) ", hostbyte_table[hb]); - else - printk("is invalid "); -} -#else -void scsi_print_hostbyte(int scsiresult) -{ - printk("Hostbyte=0x%02x ", host_byte(scsiresult)); -} -#endif - -#ifdef CONFIG_SCSI_CONSTANTS - static const char * const driverbyte_table[]={ "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; @@ -1356,19 +1363,35 @@ static const char * const driversuggest_table[]={"SUGGEST_OK", "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"}; #define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table) -void scsi_print_driverbyte(int scsiresult) +void scsi_show_result(int result) { - int dr = (driver_byte(scsiresult) & DRIVER_MASK); - int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4); + int hb = host_byte(result); + int db = (driver_byte(result) & DRIVER_MASK); + int su = ((driver_byte(result) & SUGGEST_MASK) >> 4); - printk("Driverbyte=0x%02x ", driver_byte(scsiresult)); - printk("(%s,%s) ", - (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"), + printk("Result: hostbyte=%s driverbyte=%s,%s\n", + (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), + (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"), (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid")); } + #else -void scsi_print_driverbyte(int scsiresult) + +void scsi_show_result(int result) { - printk("Driverbyte=0x%02x ", driver_byte(scsiresult)); + printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n", + host_byte(result), driver_byte(result)); } + #endif +EXPORT_SYMBOL(scsi_show_result); + + +void scsi_print_result(struct scsi_cmnd *cmd) +{ + scmd_printk(KERN_INFO, cmd, ""); + scsi_show_result(cmd->result); +} +EXPORT_SYMBOL(scsi_print_result); + + diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 3bbbfbe8cbf..5a43a4cd96c 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -5,14 +5,16 @@ struct scsi_cmnd; struct scsi_sense_hdr; extern void scsi_print_command(struct scsi_cmnd *); -extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); extern void __scsi_print_command(unsigned char *); -extern void scsi_print_sense(const char *, struct scsi_cmnd *); +extern void scsi_show_extd_sense(unsigned char, unsigned char); +extern void scsi_show_sense_hdr(struct scsi_sense_hdr *); +extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); +extern void scsi_print_sense(char *, struct scsi_cmnd *); extern void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, int sense_len); -extern void scsi_print_driverbyte(int); -extern void scsi_print_hostbyte(int); +extern void scsi_show_result(int); +extern void scsi_print_result(struct scsi_cmnd *); extern void scsi_print_status(unsigned char); extern const char *scsi_sense_key_string(unsigned char); extern const char *scsi_extd_sense_format(unsigned char, unsigned char); -- cgit v1.2.3 From a4d04a4cd9881e89fdc62107b6b57053438f2b30 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 27 Feb 2007 22:40:27 -0500 Subject: [SCSI] Make error printing more verbose This patch enhances SCSI error printing by: - Making use of scsi_print_result() in the completion functions. - Having scmd_printk() output the disk name (when applicable). Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 47 +++++++++++++++++----------------------------- drivers/scsi/scsi_lib.c | 4 +--- include/scsi/scsi_device.h | 8 ++++++-- 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 1c89ee3e69b..4c1e3133476 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -344,7 +344,6 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost) void scsi_log_send(struct scsi_cmnd *cmd) { unsigned int level; - struct scsi_device *sdev; /* * If ML QUEUE log level is greater than or equal to: @@ -361,22 +360,17 @@ void scsi_log_send(struct scsi_cmnd *cmd) level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS); if (level > 1) { - sdev = cmd->device; - sdev_printk(KERN_INFO, sdev, "send "); + scmd_printk(KERN_INFO, cmd, "Send: "); if (level > 2) printk("0x%p ", cmd); - /* - * spaces to match disposition and cmd->result - * output in scsi_log_completion. - */ - printk(" "); + printk("\n"); scsi_print_command(cmd); if (level > 3) { printk(KERN_INFO "buffer = 0x%p, bufflen = %d," " done = 0x%p, queuecommand 0x%p\n", cmd->request_buffer, cmd->request_bufflen, cmd->done, - sdev->host->hostt->queuecommand); + cmd->device->host->hostt->queuecommand); } } @@ -386,7 +380,6 @@ void scsi_log_send(struct scsi_cmnd *cmd) void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) { unsigned int level; - struct scsi_device *sdev; /* * If ML COMPLETE log level is greater than or equal to: @@ -405,8 +398,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) SCSI_LOG_MLCOMPLETE_BITS); if (((level > 0) && (cmd->result || disposition != SUCCESS)) || (level > 1)) { - sdev = cmd->device; - sdev_printk(KERN_INFO, sdev, "done "); + scmd_printk(KERN_INFO, cmd, "Done: "); if (level > 2) printk("0x%p ", cmd); /* @@ -415,40 +407,35 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) */ switch (disposition) { case SUCCESS: - printk("SUCCESS"); + printk("SUCCESS\n"); break; case NEEDS_RETRY: - printk("RETRY "); + printk("RETRY\n"); break; case ADD_TO_MLQUEUE: - printk("MLQUEUE"); + printk("MLQUEUE\n"); break; case FAILED: - printk("FAILED "); + printk("FAILED\n"); break; case TIMEOUT_ERROR: /* * If called via scsi_times_out. */ - printk("TIMEOUT"); + printk("TIMEOUT\n"); break; default: - printk("UNKNOWN"); + printk("UNKNOWN\n"); } - printk(" %8x ", cmd->result); + scsi_print_result(cmd); scsi_print_command(cmd); - if (status_byte(cmd->result) & CHECK_CONDITION) { - /* - * XXX The scsi_print_sense formatting/prefix - * doesn't match this function. - */ + if (status_byte(cmd->result) & CHECK_CONDITION) scsi_print_sense("", cmd); - } - if (level > 3) { - printk(KERN_INFO "scsi host busy %d failed %d\n", - sdev->host->host_busy, - sdev->host->host_failed); - } + if (level > 3) + scmd_printk(KERN_INFO, cmd, + "scsi host busy %d failed %d\n", + cmd->device->host->host_busy, + cmd->device->host->host_failed); } } } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9f7482d0b59..5f955707d90 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -968,9 +968,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (result) { if (!(req->cmd_flags & REQ_QUIET)) { - scmd_printk(KERN_INFO, cmd, - "SCSI error: return code = 0x%08x\n", - result); + scsi_print_result(cmd); if (driver_byte(result) & DRIVER_SENSE) scsi_print_sense("", cmd); } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9dd37e2f5a8..c86e6ce143d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -5,6 +5,7 @@ #include #include #include +#include #include struct request_queue; @@ -154,8 +155,11 @@ struct scsi_device { #define sdev_printk(prefix, sdev, fmt, a...) \ dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a) -#define scmd_printk(prefix, scmd, fmt, a...) \ - dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a) +#define scmd_printk(prefix, scmd, fmt, a...) \ + (scmd)->request->rq_disk ? \ + sdev_printk(prefix, (scmd)->device, "[%s] " fmt, \ + (scmd)->request->rq_disk->disk_name, ##a) : \ + sdev_printk(prefix, (scmd)->device, fmt, ##a) enum scsi_target_state { STARGET_RUNNING = 1, -- cgit v1.2.3 From e73aec8247032ee730b5f38edf48922c4f72522e Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 27 Feb 2007 22:40:55 -0500 Subject: [SCSI] sd: make printing use a common prefix Make SCSI disk printing more consistent: - Define sd_printk(), sd_print_sense_hdr() and sd_print_result() - Move relevant header bits into sd.h - Remove all the legacy disk_name passing and use scsi_disk pointers where possible - Switch printk() lines to the new sd_ functions so that output is consistent Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 253 ++++++++++++++++++++---------------------------------- include/scsi/sd.h | 70 +++++++++++++++ 2 files changed, 165 insertions(+), 158 deletions(-) create mode 100644 include/scsi/sd.h diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5a8f55fea5f..b5562b851e7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -58,16 +58,10 @@ #include #include #include +#include #include "scsi_logging.h" -/* - * More than enough for everybody ;) The huge number of majors - * is a leftover from 16bit dev_t days, we don't really need that - * much numberspace. - */ -#define SD_MAJORS 16 - MODULE_AUTHOR("Eric Youngdale"); MODULE_DESCRIPTION("SCSI disk (sd) driver"); MODULE_LICENSE("GPL"); @@ -89,45 +83,6 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); -/* - * This is limited by the naming scheme enforced in sd_probe, - * add another character to it if you really need more disks. - */ -#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) - -/* - * Time out in seconds for disks and Magneto-opticals (which are slower). - */ -#define SD_TIMEOUT (30 * HZ) -#define SD_MOD_TIMEOUT (75 * HZ) - -/* - * Number of allowed retries - */ -#define SD_MAX_RETRIES 5 -#define SD_PASSTHROUGH_RETRIES 1 - -/* - * Size of the initial data buffer for mode and read capacity data - */ -#define SD_BUF_SIZE 512 - -struct scsi_disk { - struct scsi_driver *driver; /* always &sd_template */ - struct scsi_device *device; - struct class_device cdev; - struct gendisk *disk; - unsigned int openers; /* protected by BKL for now, yuck */ - sector_t capacity; /* size in 512-byte sectors */ - u32 index; - u8 media_present; - u8 write_prot; - unsigned WCE : 1; /* state of disk WCE bit */ - unsigned RCD : 1; /* state of disk RCD bit, unused */ - unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ -}; -#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) - static DEFINE_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); @@ -136,20 +91,6 @@ static DEFINE_SPINLOCK(sd_index_lock); * object after last put) */ static DEFINE_MUTEX(sd_ref_mutex); -static int sd_revalidate_disk(struct gendisk *disk); -static void sd_rw_intr(struct scsi_cmnd * SCpnt); - -static int sd_probe(struct device *); -static int sd_remove(struct device *); -static void sd_shutdown(struct device *dev); -static void sd_rescan(struct device *); -static int sd_init_command(struct scsi_cmnd *); -static int sd_issue_flush(struct device *, sector_t *); -static void sd_prepare_flush(request_queue_t *, struct request *); -static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - unsigned char *buffer); -static void scsi_disk_release(struct class_device *cdev); - static const char *sd_cache_types[] = { "write through", "none", "write back", "write back, no read (daft)" @@ -199,7 +140,7 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, SD_MAX_RETRIES, &data, &sshdr)) { if (scsi_sense_valid(&sshdr)) - scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr); + sd_print_sense_hdr(sdkp, &sshdr); return -EINVAL; } sd_revalidate_disk(sdkp->disk); @@ -407,7 +348,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) */ if (sdp->sector_size == 1024) { if ((block & 1) || (rq->nr_sectors & 1)) { - printk(KERN_ERR "sd: Bad block number requested"); + scmd_printk(KERN_ERR, SCpnt, + "Bad block number requested\n"); return 0; } else { block = block >> 1; @@ -416,7 +358,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) } if (sdp->sector_size == 2048) { if ((block & 3) || (rq->nr_sectors & 3)) { - printk(KERN_ERR "sd: Bad block number requested"); + scmd_printk(KERN_ERR, SCpnt, + "Bad block number requested\n"); return 0; } else { block = block >> 2; @@ -425,7 +368,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) } if (sdp->sector_size == 4096) { if ((block & 7) || (rq->nr_sectors & 7)) { - printk(KERN_ERR "sd: Bad block number requested"); + scmd_printk(KERN_ERR, SCpnt, + "Bad block number requested\n"); return 0; } else { block = block >> 3; @@ -442,7 +386,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->cmnd[0] = READ_6; SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { - printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags); + scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); return 0; } @@ -490,7 +434,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) * during operation and thus turned off * use_10_for_rw. */ - printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n"); + scmd_printk(KERN_ERR, SCpnt, + "FUA write on READ/WRITE(6) drive\n"); return 0; } @@ -786,9 +731,10 @@ not_present: return 1; } -static int sd_sync_cache(struct scsi_device *sdp) +static int sd_sync_cache(struct scsi_disk *sdkp) { int retries, res; + struct scsi_device *sdp = sdkp->device; struct scsi_sense_hdr sshdr; if (!scsi_device_online(sdp)) @@ -809,12 +755,10 @@ static int sd_sync_cache(struct scsi_device *sdp) break; } - if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " - "host = %d, driver = %02x\n ", - status_byte(res), msg_byte(res), - host_byte(res), driver_byte(res)); - if (driver_byte(res) & DRIVER_SENSE) - scsi_print_sense_hdr("sd", &sshdr); + if (res) { + sd_print_result(sdkp, res); + if (driver_byte(res) & DRIVER_SENSE) + sd_print_sense_hdr(sdkp, &sshdr); } return res; @@ -823,14 +767,13 @@ static int sd_sync_cache(struct scsi_device *sdp) static int sd_issue_flush(struct device *dev, sector_t *error_sector) { int ret = 0; - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (!sdkp) return -ENODEV; if (sdkp->WCE) - ret = sd_sync_cache(sdp); + ret = sd_sync_cache(sdkp); scsi_disk_put(sdkp); return ret; } @@ -1025,7 +968,7 @@ static int media_not_present(struct scsi_disk *sdkp, * spinup disk - called only in sd_revalidate_disk() */ static void -sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) +sd_spinup_disk(struct scsi_disk *sdkp) { unsigned char cmd[10]; unsigned long spintime_expire = 0; @@ -1069,9 +1012,10 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { /* no sense, TUR either succeeded or failed * with a status error */ - if(!spintime && !scsi_status_is_good(the_result)) - printk(KERN_NOTICE "%s: Unit Not Ready, " - "error = 0x%x\n", diskname, the_result); + if(!spintime && !scsi_status_is_good(the_result)) { + sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); + sd_print_result(sdkp, the_result); + } break; } @@ -1096,8 +1040,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) */ } else if (sense_valid && sshdr.sense_key == NOT_READY) { if (!spintime) { - printk(KERN_NOTICE "%s: Spinning up disk...", - diskname); + sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); cmd[0] = START_STOP; cmd[1] = 1; /* Return immediately */ memset((void *) &cmd[2], 0, 8); @@ -1130,9 +1073,8 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) /* we don't understand the sense code, so it's * probably pointless to loop */ if(!spintime) { - printk(KERN_NOTICE "%s: Unit Not Ready, " - "sense:\n", diskname); - scsi_print_sense_hdr("", &sshdr); + sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); + sd_print_sense_hdr(sdkp, &sshdr); } break; } @@ -1151,8 +1093,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) * read disk capacity */ static void -sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - unsigned char *buffer) +sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) { unsigned char cmd[16]; int the_result, retries; @@ -1191,18 +1132,12 @@ repeat: } while (the_result && retries); if (the_result && !longrc) { - printk(KERN_NOTICE "%s : READ CAPACITY failed.\n" - "%s : status=%x, message=%02x, host=%d, driver=%02x \n", - diskname, diskname, - status_byte(the_result), - msg_byte(the_result), - host_byte(the_result), - driver_byte(the_result)); - + sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n"); + sd_print_result(sdkp, the_result); if (driver_byte(the_result) & DRIVER_SENSE) - scsi_print_sense_hdr("sd", &sshdr); + sd_print_sense_hdr(sdkp, &sshdr); else - printk("%s : sense not available. \n", diskname); + sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); /* Set dirty bit for removable devices if not ready - * sometimes drives will not report this properly. */ @@ -1218,16 +1153,10 @@ repeat: return; } else if (the_result && longrc) { /* READ CAPACITY(16) has been failed */ - printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n" - "%s : status=%x, message=%02x, host=%d, driver=%02x \n", - diskname, diskname, - status_byte(the_result), - msg_byte(the_result), - host_byte(the_result), - driver_byte(the_result)); - printk(KERN_NOTICE "%s : use 0xffffffff as device size\n", - diskname); - + sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n"); + sd_print_result(sdkp, the_result); + sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n"); + sdkp->capacity = 1 + (sector_t) 0xffffffff; goto got_data; } @@ -1238,14 +1167,14 @@ repeat: if (buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0xff && buffer[3] == 0xff) { if(sizeof(sdkp->capacity) > 4) { - printk(KERN_NOTICE "%s : very big device. try to use" - " READ CAPACITY(16).\n", diskname); + sd_printk(KERN_NOTICE, sdkp, "Very big device. " + "Trying to use READ CAPACITY(16).\n"); longrc = 1; goto repeat; } - printk(KERN_ERR "%s: too big for this kernel. Use a " - "kernel compiled with support for large block " - "devices.\n", diskname); + sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use " + "a kernel compiled with support for large " + "block devices.\n"); sdkp->capacity = 0; goto got_data; } @@ -1284,8 +1213,8 @@ repeat: got_data: if (sector_size == 0) { sector_size = 512; - printk(KERN_NOTICE "%s : sector size 0 reported, " - "assuming 512.\n", diskname); + sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, " + "assuming 512.\n"); } if (sector_size != 512 && @@ -1293,8 +1222,8 @@ got_data: sector_size != 2048 && sector_size != 4096 && sector_size != 256) { - printk(KERN_NOTICE "%s : unsupported sector size " - "%d.\n", diskname, sector_size); + sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", + sector_size); /* * The user might want to re-format the drive with * a supported sectorsize. Once this happens, it @@ -1327,10 +1256,10 @@ got_data: mb -= sz - 974; sector_div(mb, 1950); - printk(KERN_NOTICE "SCSI device %s: " - "%llu %d-byte hdwr sectors (%llu MB)\n", - diskname, (unsigned long long)sdkp->capacity, - hard_sector, (unsigned long long)mb); + sd_printk(KERN_NOTICE, sdkp, + "%llu %d-byte hardware sectors (%llu MB)\n", + (unsigned long long)sdkp->capacity, + hard_sector, (unsigned long long)mb); } /* Rescale capacity to 512-byte units */ @@ -1362,8 +1291,7 @@ sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage, * called with buffer of length SD_BUF_SIZE */ static void -sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, - unsigned char *buffer) +sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) { int res; struct scsi_device *sdp = sdkp->device; @@ -1371,7 +1299,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, set_disk_ro(sdkp->disk, 0); if (sdp->skip_ms_page_3f) { - printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname); + sd_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n"); return; } @@ -1403,15 +1331,16 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, } if (!scsi_status_is_good(res)) { - printk(KERN_WARNING - "%s: test WP failed, assume Write Enabled\n", diskname); + sd_printk(KERN_WARNING, sdkp, + "Test WP failed, assume Write Enabled\n"); } else { sdkp->write_prot = ((data.device_specific & 0x80) != 0); set_disk_ro(sdkp->disk, sdkp->write_prot); - printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname, - sdkp->write_prot ? "on" : "off"); - printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n", - diskname, buffer[0], buffer[1], buffer[2], buffer[3]); + sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", + sdkp->write_prot ? "on" : "off"); + sd_printk(KERN_DEBUG, sdkp, + "Mode Sense: %02x %02x %02x %02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); } } @@ -1420,8 +1349,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, * called with buffer of length SD_BUF_SIZE */ static void -sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, - unsigned char *buffer) +sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) { int len = 0, res; struct scsi_device *sdp = sdkp->device; @@ -1450,8 +1378,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, if (!data.header_length) { modepage = 6; - printk(KERN_ERR "%s: missing header in MODE_SENSE response\n", - diskname); + sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); } /* that went OK, now ask for the proper length */ @@ -1478,13 +1405,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, int offset = data.header_length + data.block_descriptor_length; if (offset >= SD_BUF_SIZE - 2) { - printk(KERN_ERR "%s: malformed MODE SENSE response", - diskname); + sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); goto defaults; } if ((buffer[offset] & 0x3f) != modepage) { - printk(KERN_ERR "%s: got wrong page\n", diskname); + sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); goto defaults; } @@ -1498,14 +1424,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, sdkp->DPOFUA = (data.device_specific & 0x10) != 0; if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { - printk(KERN_NOTICE "SCSI device %s: uses " - "READ/WRITE(6), disabling FUA\n", diskname); + sd_printk(KERN_NOTICE, sdkp, + "Uses READ/WRITE(6), disabling FUA\n"); sdkp->DPOFUA = 0; } - printk(KERN_NOTICE "SCSI device %s: " - "write cache: %s, read cache: %s, %s\n", - diskname, + sd_printk(KERN_NOTICE, sdkp, + "Write cache: %s, read cache: %s, %s\n", sdkp->WCE ? "enabled" : "disabled", sdkp->RCD ? "disabled" : "enabled", sdkp->DPOFUA ? "supports DPO and FUA" @@ -1518,15 +1443,13 @@ bad_sense: if (scsi_sense_valid(&sshdr) && sshdr.sense_key == ILLEGAL_REQUEST && sshdr.asc == 0x24 && sshdr.ascq == 0x0) - printk(KERN_NOTICE "%s: cache data unavailable\n", - diskname); /* Invalid field in CDB */ + /* Invalid field in CDB */ + sd_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n"); else - printk(KERN_ERR "%s: asking for cache data failed\n", - diskname); + sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n"); defaults: - printk(KERN_ERR "%s: assuming drive cache: write through\n", - diskname); + sd_printk(KERN_ERR, sdkp, "Assuming drive cache: write through\n"); sdkp->WCE = 0; sdkp->RCD = 0; sdkp->DPOFUA = 0; @@ -1555,8 +1478,8 @@ static int sd_revalidate_disk(struct gendisk *disk) buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA); if (!buffer) { - printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " - "failure.\n"); + sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory " + "allocation failure.\n"); goto out; } @@ -1568,16 +1491,16 @@ static int sd_revalidate_disk(struct gendisk *disk) sdkp->WCE = 0; sdkp->RCD = 0; - sd_spinup_disk(sdkp, disk->disk_name); + sd_spinup_disk(sdkp); /* * Without media there is no reason to ask; moreover, some devices * react badly if we do. */ if (sdkp->media_present) { - sd_read_capacity(sdkp, disk->disk_name, buffer); - sd_read_write_protect_flag(sdkp, disk->disk_name, buffer); - sd_read_cache_type(sdkp, disk->disk_name, buffer); + sd_read_capacity(sdkp, buffer); + sd_read_write_protect_flag(sdkp, buffer); + sd_read_cache_type(sdkp, buffer); } /* @@ -1709,8 +1632,8 @@ static int sd_probe(struct device *dev) dev_set_drvdata(dev, sdkp); add_disk(gd); - sdev_printk(KERN_NOTICE, sdp, "Attached scsi %sdisk %s\n", - sdp->removable ? "removable " : "", gd->disk_name); + sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", + sdp->removable ? "removable " : ""); return 0; @@ -1781,16 +1704,14 @@ static void scsi_disk_release(struct class_device *cdev) */ static void sd_shutdown(struct device *dev) { - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (!sdkp) return; /* this can happen */ if (sdkp->WCE) { - printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n", - sdkp->disk->disk_name); - sd_sync_cache(sdp); + sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); + sd_sync_cache(sdkp); } scsi_disk_put(sdkp); } @@ -1852,3 +1773,19 @@ static void __exit exit_sd(void) module_init(init_sd); module_exit(exit_sd); + +static void sd_print_sense_hdr(struct scsi_disk *sdkp, + struct scsi_sense_hdr *sshdr) +{ + sd_printk(KERN_INFO, sdkp, ""); + scsi_show_sense_hdr(sshdr); + sd_printk(KERN_INFO, sdkp, ""); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); +} + +static void sd_print_result(struct scsi_disk *sdkp, int result) +{ + sd_printk(KERN_INFO, sdkp, ""); + scsi_show_result(result); +} + diff --git a/include/scsi/sd.h b/include/scsi/sd.h new file mode 100644 index 00000000000..82e6a84b77e --- /dev/null +++ b/include/scsi/sd.h @@ -0,0 +1,70 @@ +#ifndef _SCSI_DISK_H +#define _SCSI_DISK_H + +/* + * More than enough for everybody ;) The huge number of majors + * is a leftover from 16bit dev_t days, we don't really need that + * much numberspace. + */ +#define SD_MAJORS 16 + +/* + * This is limited by the naming scheme enforced in sd_probe, + * add another character to it if you really need more disks. + */ +#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) + +/* + * Time out in seconds for disks and Magneto-opticals (which are slower). + */ +#define SD_TIMEOUT (30 * HZ) +#define SD_MOD_TIMEOUT (75 * HZ) + +/* + * Number of allowed retries + */ +#define SD_MAX_RETRIES 5 +#define SD_PASSTHROUGH_RETRIES 1 + +/* + * Size of the initial data buffer for mode and read capacity data + */ +#define SD_BUF_SIZE 512 + +struct scsi_disk { + struct scsi_driver *driver; /* always &sd_template */ + struct scsi_device *device; + struct class_device cdev; + struct gendisk *disk; + unsigned int openers; /* protected by BKL for now, yuck */ + sector_t capacity; /* size in 512-byte sectors */ + u32 index; + u8 media_present; + u8 write_prot; + unsigned WCE : 1; /* state of disk WCE bit */ + unsigned RCD : 1; /* state of disk RCD bit, unused */ + unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ +}; +#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) + +static int sd_revalidate_disk(struct gendisk *disk); +static void sd_rw_intr(struct scsi_cmnd * SCpnt); +static int sd_probe(struct device *); +static int sd_remove(struct device *); +static void sd_shutdown(struct device *dev); +static void sd_rescan(struct device *); +static int sd_init_command(struct scsi_cmnd *); +static int sd_issue_flush(struct device *, sector_t *); +static void sd_prepare_flush(request_queue_t *, struct request *); +static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); +static void scsi_disk_release(struct class_device *cdev); +static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); +static void sd_print_result(struct scsi_disk *, int); + +#define sd_printk(prefix, sdsk, fmt, a...) \ + (sdsk)->disk ? \ + sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ + (sdsk)->disk->disk_name, ##a) : \ + sdev_printk(prefix, (sdsk)->device, fmt, ##a) + +#endif /* _SCSI_DISK_H */ -- cgit v1.2.3 From fa0d34be06213e02a4df29a9d34ca915728a8434 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 27 Feb 2007 22:41:19 -0500 Subject: [SCSI] sd: convert logging to new printk helpers Convert the sd.c SCSI logging calls to scmd_printk()/sd_printk() instead of plain printk(). Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b5562b851e7..30a4aa0c873 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -312,15 +312,19 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) unsigned int this_count = SCpnt->request_bufflen >> 9; unsigned int timeout = sdp->timeout; - SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " - "count=%d\n", disk->disk_name, - (unsigned long long)block, this_count)); + SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, + "sd_init_command: block=%llu, " + "count=%d\n", + (unsigned long long)block, + this_count)); if (!sdp || !scsi_device_online(sdp) || block + rq->nr_sectors > get_capacity(disk)) { - SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", - rq->nr_sectors)); - SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Finishing %ld sectors\n", + rq->nr_sectors)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Retry with 0x%p\n", SCpnt)); return 0; } @@ -332,8 +336,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ return 0; } - SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n", - disk->disk_name, (unsigned long long)block)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", + (unsigned long long)block)); /* * If we have a 1K hardware sectorsize, prevent access to single @@ -390,9 +394,11 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) return 0; } - SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", - disk->disk_name, (rq_data_dir(rq) == WRITE) ? - "writing" : "reading", this_count, rq->nr_sectors)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "%s %d/%ld 512 byte blocks.\n", + (rq_data_dir(rq) == WRITE) ? + "writing" : "reading", this_count, + rq->nr_sectors)); SCpnt->cmnd[1] = 0; @@ -494,7 +500,7 @@ static int sd_open(struct inode *inode, struct file *filp) return -ENXIO; - SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name)); + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); sdev = sdkp->device; @@ -564,7 +570,7 @@ static int sd_release(struct inode *inode, struct file *filp) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdev = sdkp->device; - SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name)); + SCSI_LOG_HLQUEUE(3, sdkp_printk(KERN_INFO, sdkp, "sd_release\n")); if (!--sdkp->openers && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) @@ -677,8 +683,7 @@ static int sd_media_changed(struct gendisk *disk) struct scsi_device *sdp = sdkp->device; int retval; - SCSI_LOG_HLQUEUE(3, printk("sd_media_changed: disk=%s\n", - disk->disk_name)); + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n")); if (!sdp->removable) return 0; @@ -871,12 +876,14 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) sense_deferred = scsi_sense_is_deferred(&sshdr); } #ifdef CONFIG_SCSI_LOGGING - SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", - SCpnt->request->rq_disk->disk_name, result)); + SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); if (sense_valid) { - SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[respc,sk,asc," - "ascq]=%x,%x,%x,%x\n", sshdr.response_code, - sshdr.sense_key, sshdr.asc, sshdr.ascq)); + SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, + "sd_rw_intr: sb[respc,sk,asc," + "ascq]=%x,%x,%x,%x\n", + sshdr.response_code, + sshdr.sense_key, sshdr.asc, + sshdr.ascq)); } #endif if (driver_byte(result) != DRIVER_SENSE && @@ -1467,7 +1474,8 @@ static int sd_revalidate_disk(struct gendisk *disk) unsigned char *buffer; unsigned ordered; - SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, + "sd_revalidate_disk\n")); /* * If the device is offline, don't try and read capacity or any -- cgit v1.2.3 From 62d42a62770dd66da2d3df693e70f4e5fae1716a Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 28 Feb 2007 12:37:06 -0500 Subject: [SCSI] constants.c: Update ASC list and make it const Add missing additional sense code and provide pointer to upstream reference (from Doug Gilbert). Add missing const (from Michael Tokarev). Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 611487545af..2a458d66b6f 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -404,7 +404,11 @@ struct error_info { const char * text; }; -static struct error_info additional[] = +/* + * The canonical list of T10 Additional Sense Codes is available at: + * http://www.t10.org/lists/asc-num.txt + */ +static const struct error_info additional[] = { {0x0000, "No additional sense information"}, {0x0001, "Filemark detected"}, @@ -708,6 +712,7 @@ static struct error_info additional[] = {0x2F00, "Commands cleared by another initiator"}, {0x2F01, "Commands cleared by power loss notification"}, + {0x2F02, "Commands cleared by device server"}, {0x3000, "Incompatible medium installed"}, {0x3001, "Cannot read medium - unknown format"}, -- cgit v1.2.3 From 779ea1207b6a43943faa44f41be7311263315604 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:15 -0600 Subject: [SCSI] libiscsi: flush work before freeing connection It's possible that we call iscsi_xmitworker after iscsi_conn_release which causes a oops. This patch flushes the workqueue. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7c75771c77f..6346a913c36 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1597,6 +1597,9 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) wake_up(&conn->ehwait); } + /* flush queued up work because we free the connection below */ + scsi_flush_work(session->host); + spin_lock_bh(&session->lock); kfree(conn->data); kfree(conn->persistent_address); -- cgit v1.2.3 From 05db888a46866fd4eae643792c162e1a5c1a8612 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:16 -0600 Subject: [SCSI] libiscsi: clear mtask Consolidate the mtask clearing code. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6346a913c36..0ad484f87b1 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -577,7 +577,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) } EXPORT_SYMBOL_GPL(iscsi_conn_failure); -static int iscsi_xmit_imm_task(struct iscsi_conn *conn) +static int iscsi_xmit_mtask(struct iscsi_conn *conn) { struct iscsi_hdr *hdr = conn->mtask->hdr; int rc, was_logout = 0; @@ -591,6 +591,9 @@ static int iscsi_xmit_imm_task(struct iscsi_conn *conn) if (rc) return rc; + /* done with this in-progress mtask */ + conn->mtask = NULL; + if (was_logout) { set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); return -ENODATA; @@ -643,11 +646,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) conn->ctask = NULL; } if (conn->mtask) { - rc = iscsi_xmit_imm_task(conn); + rc = iscsi_xmit_mtask(conn); if (rc) goto again; - /* done with this in-progress mtask */ - conn->mtask = NULL; } /* process immediate first */ @@ -658,12 +659,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - rc = iscsi_xmit_imm_task(conn); + rc = iscsi_xmit_mtask(conn); if (rc) goto again; } - /* done with this mtask */ - conn->mtask = NULL; } /* process command queue */ @@ -701,12 +700,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - rc = tt->xmit_mgmt_task(conn, conn->mtask); - if (rc) + rc = iscsi_xmit_mtask(conn); + if (rc) goto again; } - /* done with this mtask */ - conn->mtask = NULL; } return -ENODATA; -- cgit v1.2.3 From bf32ed33e97ac7905fa5a2bf49a634c2eaf62457 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:17 -0600 Subject: [SCSI] iscsi: rename DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH This patch renames DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH to avoid confusion with the drivers default values (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH is the iscsi RFC specific default). Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iser_initiator.c | 2 +- drivers/scsi/iscsi_tcp.c | 6 +++--- drivers/scsi/libiscsi.c | 2 +- include/scsi/iscsi_proto.h | 12 +++++++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 89e37283c83..3261bb32728 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -201,7 +201,7 @@ static int iser_post_receive_control(struct iscsi_conn *conn) * what's common for both schemes is that the connection is not started */ if (conn->c_stage != ISCSI_CONN_STARTED) - rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN; else /* FIXME till user space sets conn->max_recv_dlength correctly */ rx_data_size = 128; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 8f55e143143..6fd08458349 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -527,12 +527,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) * than 8K, but there are no targets that currently do this. * For now we fail until we find a vendor that needs it */ - if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH < + if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) { printk(KERN_ERR "iscsi_tcp: received buffer of len %u " "but conn buffer is only %u (opcode %0x)\n", tcp_conn->in.datalen, - DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode); + ISCSI_DEF_MAX_RECV_SEG_LEN, opcode); rc = ISCSI_ERR_PROTO; break; } @@ -1762,7 +1762,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) * due to strange issues with iser these are not set * in iscsi_conn_setup */ - conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); if (!tcp_conn) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 0ad484f87b1..04707d667c9 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1520,7 +1520,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) } spin_unlock_bh(&session->lock); - data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); + data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); if (!data) goto login_mtask_data_alloc_fail; conn->login_mtask->data = conn->data = data; diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 4a44278ed76..8d1e4e8026f 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -588,7 +588,17 @@ struct iscsi_reject { #define VALUE_MAXLEN 255 #define TARGET_NAME_MAXLEN VALUE_MAXLEN -#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 +#define ISCSI_DEF_MAX_RECV_SEG_LEN 8192 +#define ISCSI_MIN_MAX_RECV_SEG_LEN 512 +#define ISCSI_MAX_MAX_RECV_SEG_LEN 16777215 + +#define ISCSI_DEF_FIRST_BURST_LEN 65536 +#define ISCSI_MIN_FIRST_BURST_LEN 512 +#define ISCSI_MAX_FIRST_BURST_LEN 16777215 + +#define ISCSI_DEF_MAX_BURST_LEN 262144 +#define ISCSI_MIN_MAX_BURST_LEN 512 +#define ISCSI_MAX_MAX_BURST_LEN 16777215 /************************* RFC 3720 End *****************************/ -- cgit v1.2.3 From 41be14442213b6dbeea3cba2ed18a2923666278c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:18 -0600 Subject: [SCSI] iscsi transport: use atomic for session_nr allocations qla4xxx and iscsi_tcp or iser could be creating sessions at the same time, so make session_nr id allocation atomic. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index ce0d14af33c..ff05c84479c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -49,7 +49,7 @@ struct iscsi_internal { struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; }; -static int iscsi_session_nr; /* sysfs session id for next new session */ +static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ /* * list of registered transports and lock that must @@ -300,7 +300,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) int err; ihost = shost->shost_data; - session->sid = iscsi_session_nr++; + session->sid = atomic_add_return(1, &iscsi_session_nr); session->target_id = target_id; snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", @@ -1419,6 +1419,8 @@ static __init int iscsi_transport_init(void) printk(KERN_INFO "Loading iSCSI transport class v%s.\n", ISCSI_TRANSPORT_VERSION); + atomic_set(&iscsi_session_nr, 0); + err = class_register(&iscsi_transport_class); if (err) return err; -- cgit v1.2.3 From 8eb00539d92187ade7e4cc24a1a36ab248ee8639 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:19 -0600 Subject: [SCSI] libiscsi: use get_unaligned Dave Miller meantioned that the data buffer in a past sense fixup patch was not gauranteed to be aligned properly for ia64. This patch has libiscsi use get_unalinged to make sure. There are a couple more places in the digest handling we may need to do this, but we are in the middle of fixing that code for big endien systems so just the sense access is fixed here. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 04707d667c9..3f5b9b445b2 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -269,14 +270,14 @@ invalid_datalen: goto out; } - senselen = be16_to_cpu(*(__be16 *)data); + senselen = be16_to_cpu(get_unaligned((__be16 *) data)); if (datalen < senselen) goto invalid_datalen; memcpy(sc->sense_buffer, data + 2, min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); debug_scsi("copied %d bytes of sense\n", - min(senselen, SCSI_SENSE_BUFFERSIZE)); + min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); } if (sc->sc_data_direction == DMA_TO_DEVICE) -- cgit v1.2.3 From 8231f0eddbe425cc3b54f2d723bb03531925272e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:20 -0600 Subject: [SCSI] iscsi_tcp: increase max_sectors For a while now, the block layer has seperated max sectors and max hw sectors. Software iscsi has no limit so this patch increases max hw sectors, so we can support large pass through commands. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6fd08458349..861cb9be40b 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2138,6 +2138,7 @@ static struct scsi_host_template iscsi_sht = { .change_queue_depth = iscsi_change_queue_depth, .can_queue = ISCSI_XMIT_CMDS_MAX - 1, .sg_tablesize = ISCSI_SG_TABLESIZE, + .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, .eh_host_reset_handler = iscsi_eh_host_reset, -- cgit v1.2.3 From 0f238418b6d41cdfc85f2f399848429ff6fbfbd0 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 28 Feb 2007 17:32:21 -0600 Subject: [SCSI] iscsi_tcp: print useful error message when iscsi crc23c allocation fails People do not read the README and seem to like to unselect the crc32c module even though iscsi_tcp selects it for them. This patch spits a error that tells the user that they really do need the module. Hopefully, we will get fewer people asking about this now. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 861cb9be40b..c9a3abf9e7b 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1777,14 +1777,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, CRYPTO_ALG_ASYNC); tcp_conn->tx_hash.flags = 0; - if (IS_ERR(tcp_conn->tx_hash.tfm)) + if (IS_ERR(tcp_conn->tx_hash.tfm)) { + printk(KERN_ERR "Could not create connection due to crc32c " + "loading error %ld. Make sure the crc32c module is " + "built as a module or into the kernel\n", + PTR_ERR(tcp_conn->tx_hash.tfm)); goto free_tcp_conn; + } tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, CRYPTO_ALG_ASYNC); tcp_conn->rx_hash.flags = 0; - if (IS_ERR(tcp_conn->rx_hash.tfm)) + if (IS_ERR(tcp_conn->rx_hash.tfm)) { + printk(KERN_ERR "Could not create connection due to crc32c " + "loading error %ld. Make sure the crc32c module is " + "built as a module or into the kernel\n", + PTR_ERR(tcp_conn->rx_hash.tfm)); goto free_tx_tfm; + } return cls_conn; -- cgit v1.2.3 From 181011e04a2a32f8d5df212254239ac9a3c8ab5e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 3 Mar 2007 09:55:54 +0900 Subject: [SCSI] tgt: rm bio hacks in scsi tgt scsi tgt breaks up a command into multple scatterlists if we cannot fit all the data in one. This was because the block rq helpers did not support large requests and because we can get a command of any old size so it is hard to preallocate pages for scatterlist large enough (we cannot really preallocate pages with the bio map user path). In 2.6.20, we added large request support to the block layer helper, blk_rq_map_user. And at LSF, we talked about increasing SCSI_MAX_PHYS_SEGMENTS for scsi tgt if we want to support really really :) large (greater than 256 * PAGE_SIZE in the worst mapping case) requests. The only target currently implemented does not even support the multiple scatterlists stuff and only supports smaller requests, so this patch just coverts scsi tgt to use blk_rq_map_user. Signed-off-by: Mike Christie Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_lib.c | 133 +++++++++++--------------------------------- include/scsi/scsi_cmnd.h | 3 - 2 files changed, 34 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index d402aff5f31..47c29a98c92 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -28,7 +28,6 @@ #include #include #include -#include <../drivers/md/dm-bio-list.h> #include "scsi_tgt_priv.h" @@ -42,9 +41,8 @@ static struct kmem_cache *scsi_tgt_cmd_cache; struct scsi_tgt_cmd { /* TODO replace work with James b's code */ struct work_struct work; - /* TODO replace the lists with a large bio */ - struct bio_list xfer_done_list; - struct bio_list xfer_list; + /* TODO fix limits of some drivers */ + struct bio *bio; struct list_head hash_list; struct request *rq; @@ -93,7 +91,12 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, if (!tcmd) goto put_dev; - rq = blk_get_request(shost->uspace_req_q, write, gfp_mask); + /* + * The blk helpers are used to the READ/WRITE requests + * transfering data from a initiator point of view. Since + * we are in target mode we want the opposite. + */ + rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask); if (!rq) goto free_tcmd; @@ -111,8 +114,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, rq->cmd_flags |= REQ_TYPE_BLOCK_PC; rq->end_io_data = tcmd; - bio_list_init(&tcmd->xfer_list); - bio_list_init(&tcmd->xfer_done_list); tcmd->rq = rq; return cmd; @@ -157,22 +158,6 @@ void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) } EXPORT_SYMBOL_GPL(scsi_host_put_command); -static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) -{ - struct bio *bio; - - /* must call bio_endio in case bio was bounced */ - while ((bio = bio_list_pop(&tcmd->xfer_done_list))) { - bio_endio(bio, bio->bi_size, 0); - bio_unmap_user(bio); - } - - while ((bio = bio_list_pop(&tcmd->xfer_list))) { - bio_endio(bio, bio->bi_size, 0); - bio_unmap_user(bio); - } -} - static void cmd_hashlist_del(struct scsi_cmnd *cmd) { struct request_queue *q = cmd->request->q; @@ -185,6 +170,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); } +static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) +{ + blk_rq_unmap_user(tcmd->bio); +} + static void scsi_tgt_cmd_destroy(struct work_struct *work) { struct scsi_tgt_cmd *tcmd = @@ -193,16 +183,6 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction, rq_data_dir(cmd->request)); - /* - * We fix rq->cmd_flags here since when we told bio_map_user - * to write vm for WRITE commands, blk_rq_bio_prep set - * rq_data_dir the flags to READ. - */ - if (cmd->sc_data_direction == DMA_TO_DEVICE) - cmd->request->cmd_flags |= REQ_RW; - else - cmd->request->cmd_flags &= ~REQ_RW; - scsi_unmap_user_pages(tcmd); scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); } @@ -215,6 +195,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, struct list_head *head; tcmd->tag = tag; + tcmd->bio = NULL; INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); spin_lock_irqsave(&qdata->cmd_hash_lock, flags); head = &qdata->cmd_hash[cmd_hashfn(tag)]; @@ -419,52 +400,33 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, struct request *rq = cmd->request; void *uaddr = tcmd->buffer; unsigned int len = tcmd->bufflen; - struct bio *bio; int err; - while (len > 0) { - dprintk("%lx %u\n", (unsigned long) uaddr, len); - bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw); - if (IS_ERR(bio)) { - err = PTR_ERR(bio); - dprintk("fail to map %lx %u %d %x\n", - (unsigned long) uaddr, len, err, cmd->cmnd[0]); - goto unmap_bios; - } - - uaddr += bio->bi_size; - len -= bio->bi_size; - + dprintk("%lx %u\n", (unsigned long) uaddr, len); + err = blk_rq_map_user(q, rq, uaddr, len); + if (err) { /* - * The first bio is added and merged. We could probably - * try to add others using scsi_merge_bio() but for now - * we keep it simple. The first bio should be pretty large - * (either hitting the 1 MB bio pages limit or a queue limit) - * already but for really large IO we may want to try and - * merge these. + * TODO: need to fixup sg_tablesize, max_segment_size, + * max_sectors, etc for modern HW and software drivers + * where this value is bogus. + * + * TODO2: we can alloc a reserve buffer of max size + * we can handle and do the slow copy path for really large + * IO. */ - if (!rq->bio) { - blk_rq_bio_prep(q, rq, bio); - rq->data_len = bio->bi_size; - } else - /* put list of bios to transfer in next go around */ - bio_list_add(&tcmd->xfer_list, bio); + eprintk("Could not handle request of size %u.\n", len); + return err; } - cmd->offset = 0; + tcmd->bio = rq->bio; err = scsi_tgt_init_cmd(cmd, GFP_KERNEL); if (err) - goto unmap_bios; + goto unmap_rq; return 0; -unmap_bios: - if (rq->bio) { - bio_unmap_user(rq->bio); - while ((bio = bio_list_pop(&tcmd->xfer_list))) - bio_unmap_user(bio); - } - +unmap_rq: + scsi_unmap_user_pages(tcmd); return err; } @@ -473,12 +435,10 @@ static int scsi_tgt_transfer_data(struct scsi_cmnd *); static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd) { struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - struct bio *bio; int err; /* should we free resources here on error ? */ if (cmd->result) { -send_uspace_err: err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); if (err <= 0) /* the tgt uspace eh will have to pick this up */ @@ -490,34 +450,8 @@ send_uspace_err: cmd, cmd->request_bufflen, tcmd->bufflen); scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); - bio_list_add(&tcmd->xfer_done_list, cmd->request->bio); - tcmd->buffer += cmd->request_bufflen; - cmd->offset += cmd->request_bufflen; - - if (!tcmd->xfer_list.head) { - scsi_tgt_transfer_response(cmd); - return; - } - - dprintk("cmd2 %p request_bufflen %u bufflen %u\n", - cmd, cmd->request_bufflen, tcmd->bufflen); - - bio = bio_list_pop(&tcmd->xfer_list); - BUG_ON(!bio); - - blk_rq_bio_prep(cmd->request->q, cmd->request, bio); - cmd->request->data_len = bio->bi_size; - err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC); - if (err) { - cmd->result = DID_ERROR << 16; - goto send_uspace_err; - } - - if (scsi_tgt_transfer_data(cmd)) { - cmd->result = DID_NO_CONNECT << 16; - goto send_uspace_err; - } + scsi_tgt_transfer_response(cmd); } static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd) @@ -617,8 +551,9 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, } cmd = rq->special; - dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd, - result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]); + dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n", + cmd, cmd->cmnd[0], result, len, cmd->request_bufflen, + rq_data_dir(rq), cmd->cmnd[0]); if (result == TASK_ABORTED) { scsi_tgt_abort_cmd(shost, cmd); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index d6948d0e8cd..a2e0c103249 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -73,9 +73,6 @@ struct scsi_cmnd { unsigned short use_sg; /* Number of pieces of scatter-gather */ unsigned short sglist_len; /* size of malloc'd scatter-gather list */ - /* offset in cmd we are at (for multi-transfer tgt cmds) */ - unsigned offset; - unsigned underflow; /* Return error if less than this amount is transferred */ -- cgit v1.2.3 From bc7e380a6a4c94f79a49c36bdb28062a750b3c2b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Mar 2007 09:55:54 +0900 Subject: [SCSI] tgt: fix sesnse buffer problems This patch simplify the way to notify LLDs of the command completion and addresses the following sense buffer problems: - can't handle both data and sense. - forces user-space to use aligned sense buffer tgt copies sense_data from userspace to cmnd->sense_buffer (if necessary), maps user-space pages (if necessary) and then calls host->transfer_response (host->transfer_data is removed). Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvstgt.c | 21 ++----- drivers/scsi/scsi_tgt_if.c | 6 +- drivers/scsi/scsi_tgt_lib.c | 120 ++++++++------------------------------- drivers/scsi/scsi_tgt_priv.h | 5 +- include/scsi/scsi_host.h | 19 ++----- include/scsi/scsi_tgt_if.h | 6 +- 6 files changed, 44 insertions(+), 133 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 4368ca0e827..a7fbd10817a 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -273,23 +273,9 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, rest -= mlen; } out: - return 0; } -static int ibmvstgt_transfer_data(struct scsi_cmnd *sc, - void (*done)(struct scsi_cmnd *)) -{ - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - int err; - - err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); - - done(sc); - - return err; -} - static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) { @@ -297,7 +283,11 @@ static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; struct srp_target *target = iue->target; - dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); + dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], + cmd->usg_sg); + + if (sc->use_sg) + srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); spin_lock_irqsave(&target->lock, flags); list_del(&iue->ilist); @@ -794,7 +784,6 @@ static struct scsi_host_template ibmvstgt_sht = { .use_clustering = DISABLE_CLUSTERING, .max_sectors = DEFAULT_MAX_SECTORS, .transfer_response = ibmvstgt_cmd_done, - .transfer_data = ibmvstgt_transfer_data, .eh_abort_handler = ibmvstgt_eh_abort_handler, .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, .shost_attrs = ibmvstgt_attrs, diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index 0e08817fdec..ca22ddf8174 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c @@ -179,10 +179,12 @@ static int event_recv_msg(struct tgt_event *ev) switch (ev->hdr.type) { case TGT_UEVENT_CMD_RSP: err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, - ev->p.cmd_rsp.tag, ev->p.cmd_rsp.result, - ev->p.cmd_rsp.len, + ev->p.cmd_rsp.tag, ev->p.cmd_rsp.uaddr, + ev->p.cmd_rsp.len, + ev->p.cmd_rsp.sense_uaddr, + ev->p.cmd_rsp.sense_len, ev->p.cmd_rsp.rw); break; case TGT_UEVENT_TSK_MGMT_RSP: diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 47c29a98c92..dc8781a68d7 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -47,9 +47,6 @@ struct scsi_tgt_cmd { struct list_head hash_list; struct request *rq; u64 tag; - - void *buffer; - unsigned bufflen; }; #define TGT_HASH_ORDER 4 @@ -330,10 +327,14 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); scsi_tgt_uspace_send_status(cmd, tcmd->tag); + + if (cmd->request_buffer) + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); + queue_work(scsi_tgtd, &tcmd->work); } -static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd) +static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); int err; @@ -346,30 +347,12 @@ static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd) case SCSI_MLQUEUE_DEVICE_BUSY: return -EAGAIN; } - return 0; } -static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - int err; - - err = __scsi_tgt_transfer_response(cmd); - if (!err) - return; - - cmd->result = DID_BUS_BUSY << 16; - err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); - if (err <= 0) - /* the eh will have to pick this up */ - printk(KERN_ERR "Could not send cmd %p status\n", cmd); -} - static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) { struct request *rq = cmd->request; - struct scsi_tgt_cmd *tcmd = rq->end_io_data; int count; cmd->use_sg = rq->nr_phys_segments; @@ -379,31 +362,28 @@ static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) cmd->request_bufflen = rq->data_len; - dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg, - rq_data_dir(rq)); + dprintk("cmd %p cnt %d %lu\n", cmd, cmd->use_sg, rq_data_dir(rq)); count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer); if (likely(count <= cmd->use_sg)) { cmd->use_sg = count; return 0; } - eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg); + eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg); scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); return -EINVAL; } /* TODO: test this crap and replace bio_map_user with new interface maybe */ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, - int rw) + unsigned long uaddr, unsigned int len, int rw) { struct request_queue *q = cmd->request->q; struct request *rq = cmd->request; - void *uaddr = tcmd->buffer; - unsigned int len = tcmd->bufflen; int err; - dprintk("%lx %u\n", (unsigned long) uaddr, len); - err = blk_rq_map_user(q, rq, uaddr, len); + dprintk("%lx %u\n", uaddr, len); + err = blk_rq_map_user(q, rq, (void *)uaddr, len); if (err) { /* * TODO: need to fixup sg_tablesize, max_segment_size, @@ -430,45 +410,6 @@ unmap_rq: return err; } -static int scsi_tgt_transfer_data(struct scsi_cmnd *); - -static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - int err; - - /* should we free resources here on error ? */ - if (cmd->result) { - err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); - if (err <= 0) - /* the tgt uspace eh will have to pick this up */ - printk(KERN_ERR "Could not send cmd %p status\n", cmd); - return; - } - - dprintk("cmd %p request_bufflen %u bufflen %u\n", - cmd, cmd->request_bufflen, tcmd->bufflen); - - scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); - tcmd->buffer += cmd->request_bufflen; - scsi_tgt_transfer_response(cmd); -} - -static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd) -{ - int err; - struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd); - - err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done); - switch (err) { - case SCSI_MLQUEUE_HOST_BUSY: - case SCSI_MLQUEUE_DEVICE_BUSY: - return -EAGAIN; - default: - return 0; - } -} - static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, unsigned len) { @@ -518,8 +459,9 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } -int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, - unsigned long uaddr, u8 rw) +int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, + unsigned long uaddr, u32 len, unsigned long sense_uaddr, + u32 sense_len, u8 rw) { struct Scsi_Host *shost; struct scsi_cmnd *cmd; @@ -564,36 +506,20 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, * in the request_* values */ tcmd = cmd->request->end_io_data; - tcmd->buffer = (void *)uaddr; - tcmd->bufflen = len; cmd->result = result; - if (!tcmd->bufflen || cmd->request_buffer) { - err = __scsi_tgt_transfer_response(cmd); - goto done; - } - - /* - * TODO: Do we need to handle case where request does not - * align with LLD. - */ - err = scsi_map_user_pages(rq->end_io_data, cmd, rw); - if (err) { - eprintk("%p %d\n", cmd, err); - err = -EAGAIN; - goto done; - } + if (cmd->result == SAM_STAT_CHECK_CONDITION) + scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len); - /* userspace failure */ - if (cmd->result) { - if (status_byte(cmd->result) == CHECK_CONDITION) - scsi_tgt_copy_sense(cmd, uaddr, len); - err = __scsi_tgt_transfer_response(cmd); - goto done; + if (len) { + err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw); + if (err) { + eprintk("%p %d\n", cmd, err); + err = -EAGAIN; + goto done; + } } - /* ask the target LLD to transfer the data to the buffer */ - err = scsi_tgt_transfer_data(cmd); - + err = scsi_tgt_transfer_response(cmd); done: scsi_host_put(shost); return err; diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h index 84488c51ff6..e9e6db1c417 100644 --- a/drivers/scsi/scsi_tgt_priv.h +++ b/drivers/scsi/scsi_tgt_priv.h @@ -18,8 +18,9 @@ extern int scsi_tgt_if_init(void); extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag); extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, - unsigned long uaddr, u8 rw); +extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, + unsigned long uaddr, u32 len, unsigned long sense_uaddr, + u32 sense_len, u8 rw); extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, struct scsi_lun *scsilun, void *data); extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 7f1f411d07a..965b6b8ffec 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -129,6 +129,11 @@ struct scsi_host_template { * the LLD. When the driver is finished processing the command * the done callback is invoked. * + * This is called to inform the LLD to transfer + * cmd->request_bufflen bytes. The cmd->use_sg speciefies the + * number of scatterlist entried in the command and + * cmd->request_buffer contains the scatterlist. + * * return values: see queuecommand * * If the LLD accepts the cmd, it should set the result to an @@ -139,20 +144,6 @@ struct scsi_host_template { /* TODO: rename */ int (* transfer_response)(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); - /* - * This is called to inform the LLD to transfer cmd->request_bufflen - * bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg - * speciefies the number of scatterlist entried in the command - * and cmd->request_buffer contains the scatterlist. - * - * If the command cannot be processed in one transfer_data call - * becuase a scatterlist within the LLD's limits cannot be - * created then transfer_data will be called multiple times. - * It is initially called from process context, and later - * calls are from the interrup context. - */ - int (* transfer_data)(struct scsi_cmnd *, - void (*done)(struct scsi_cmnd *)); /* Used as callback for the completion of task management request. */ int (* tsk_mgmt_response)(u64 mid, int result); diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h index 07d6e77ae89..4cf9dff29a2 100644 --- a/include/scsi/scsi_tgt_if.h +++ b/include/scsi/scsi_tgt_if.h @@ -45,11 +45,13 @@ struct tgt_event { /* user-> kernel */ struct { int host_no; - uint32_t len; int result; + aligned_u64 tag; aligned_u64 uaddr; + aligned_u64 sense_uaddr; + uint32_t len; + uint32_t sense_len; uint8_t rw; - aligned_u64 tag; } cmd_rsp; struct { int host_no; -- cgit v1.2.3 From e8f8248cbadcd8cb1b737fc57a01bccca4fb7aec Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Mar 2007 09:55:55 +0900 Subject: [SCSI] tgt: fix scsi command leak The failure to map user-space pages leads to scsi command leak. It can happens mostly because of user-space daemon bugs (or OOM). This patch makes tgt just notify a LLD of the failure with sense when blk_rq_map_user() fails. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_lib.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index dc8781a68d7..c05dff95bd9 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -459,6 +459,16 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } +static void scsi_tgt_build_sense(unsigned char *sense_buffer, unsigned char key, + unsigned char asc, unsigned char asq) +{ + sense_buffer[0] = 0x70; + sense_buffer[2] = key; + sense_buffer[7] = 0xa; + sense_buffer[12] = asc; + sense_buffer[13] = asq; +} + int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, unsigned long uaddr, u32 len, unsigned long sense_uaddr, u32 sense_len, u8 rw) @@ -514,9 +524,16 @@ int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, if (len) { err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw); if (err) { - eprintk("%p %d\n", cmd, err); - err = -EAGAIN; - goto done; + /* + * user-space daemon bugs or OOM + * TODO: we can do better for OOM. + */ + eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n", + cmd, err, uaddr, len, rw); + cmd->result = SAM_STAT_CHECK_CONDITION; + memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + scsi_tgt_build_sense(cmd->sense_buffer, + HARDWARE_ERROR, 0, 0); } } err = scsi_tgt_transfer_response(cmd); -- cgit v1.2.3 From 38891cb6b0de3f5986e6a7688c5ae17c18b000a9 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sat, 10 Mar 2007 17:16:26 -0500 Subject: [SCSI] pci2000: Delete unused header file. This driver was removed a while ago by commit 099175c94a221fa2723b7273883c98cd32efe900 However, it seems that pci2000.h wasn't properly eliminated, so remove it now. Signed-off-by: Robert P. J. Day Signed-off-by: James Bottomley --- drivers/scsi/pci2000.h | 197 ------------------------------------------------- 1 file changed, 197 deletions(-) delete mode 100644 drivers/scsi/pci2000.h diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h deleted file mode 100644 index 0ebd8ce9e1d..00000000000 --- a/drivers/scsi/pci2000.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** - * Perceptive Solutions, Inc. PCI-2000 device driver for Linux. - * - * pci2000.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters - * - * Copyright (c) 1997-1999 Perceptive Solutions, Inc. - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - * Technical updates and product information at: - * http://www.psidisk.com - * - * Please send questions, comments, bug reports to: - * tech@psidisk.com Technical Support - * - ****************************************************************************/ -#ifndef _PCI2000_H -#define _PCI2000_H - -#include - -#ifndef PSI_EIDE_SCSIOP -#define PSI_EIDE_SCSIOP 1 - -#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s)) - -/************************************************/ -/* definition of standard data types */ -/************************************************/ -#define CHAR char -#define UCHAR unsigned char -#define SHORT short -#define USHORT unsigned short -#define BOOL long -#define LONG long -#define ULONG unsigned long -#define VOID void - -typedef CHAR *PCHAR; -typedef UCHAR *PUCHAR; -typedef SHORT *PSHORT; -typedef USHORT *PUSHORT; -typedef BOOL *PBOOL; -typedef LONG *PLONG; -typedef ULONG *PULONG; -typedef VOID *PVOID; - - -/************************************************/ -/* Misc. macros */ -/************************************************/ -#define ANY2SCSI(up, p) \ -((UCHAR *)up)[0] = (((ULONG)(p)) >> 8); \ -((UCHAR *)up)[1] = ((ULONG)(p)); - -#define SCSI2LONG(up) \ -( (((long)*(((UCHAR *)up))) << 16) \ -+ (((long)(((UCHAR *)up)[1])) << 8) \ -+ ((long)(((UCHAR *)up)[2])) ) - -#define XANY2SCSI(up, p) \ -((UCHAR *)up)[0] = ((long)(p)) >> 24; \ -((UCHAR *)up)[1] = ((long)(p)) >> 16; \ -((UCHAR *)up)[2] = ((long)(p)) >> 8; \ -((UCHAR *)up)[3] = ((long)(p)); - -#define XSCSI2LONG(up) \ -( (((long)(((UCHAR *)up)[0])) << 24) \ -+ (((long)(((UCHAR *)up)[1])) << 16) \ -+ (((long)(((UCHAR *)up)[2])) << 8) \ -+ ((long)(((UCHAR *)up)[3])) ) - -/************************************************/ -/* SCSI CDB operation codes */ -/************************************************/ -#define SCSIOP_TEST_UNIT_READY 0x00 -#define SCSIOP_REZERO_UNIT 0x01 -#define SCSIOP_REWIND 0x01 -#define SCSIOP_REQUEST_BLOCK_ADDR 0x02 -#define SCSIOP_REQUEST_SENSE 0x03 -#define SCSIOP_FORMAT_UNIT 0x04 -#define SCSIOP_READ_BLOCK_LIMITS 0x05 -#define SCSIOP_REASSIGN_BLOCKS 0x07 -#define SCSIOP_READ6 0x08 -#define SCSIOP_RECEIVE 0x08 -#define SCSIOP_WRITE6 0x0A -#define SCSIOP_PRINT 0x0A -#define SCSIOP_SEND 0x0A -#define SCSIOP_SEEK6 0x0B -#define SCSIOP_TRACK_SELECT 0x0B -#define SCSIOP_SLEW_PRINT 0x0B -#define SCSIOP_SEEK_BLOCK 0x0C -#define SCSIOP_PARTITION 0x0D -#define SCSIOP_READ_REVERSE 0x0F -#define SCSIOP_WRITE_FILEMARKS 0x10 -#define SCSIOP_FLUSH_BUFFER 0x10 -#define SCSIOP_SPACE 0x11 -#define SCSIOP_INQUIRY 0x12 -#define SCSIOP_VERIFY6 0x13 -#define SCSIOP_RECOVER_BUF_DATA 0x14 -#define SCSIOP_MODE_SELECT 0x15 -#define SCSIOP_RESERVE_UNIT 0x16 -#define SCSIOP_RELEASE_UNIT 0x17 -#define SCSIOP_COPY 0x18 -#define SCSIOP_ERASE 0x19 -#define SCSIOP_MODE_SENSE 0x1A -#define SCSIOP_START_STOP_UNIT 0x1B -#define SCSIOP_STOP_PRINT 0x1B -#define SCSIOP_LOAD_UNLOAD 0x1B -#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C -#define SCSIOP_SEND_DIAGNOSTIC 0x1D -#define SCSIOP_MEDIUM_REMOVAL 0x1E -#define SCSIOP_READ_CAPACITY 0x25 -#define SCSIOP_READ 0x28 -#define SCSIOP_WRITE 0x2A -#define SCSIOP_SEEK 0x2B -#define SCSIOP_LOCATE 0x2B -#define SCSIOP_WRITE_VERIFY 0x2E -#define SCSIOP_VERIFY 0x2F -#define SCSIOP_SEARCH_DATA_HIGH 0x30 -#define SCSIOP_SEARCH_DATA_EQUAL 0x31 -#define SCSIOP_SEARCH_DATA_LOW 0x32 -#define SCSIOP_SET_LIMITS 0x33 -#define SCSIOP_READ_POSITION 0x34 -#define SCSIOP_SYNCHRONIZE_CACHE 0x35 -#define SCSIOP_COMPARE 0x39 -#define SCSIOP_COPY_COMPARE 0x3A -#define SCSIOP_WRITE_DATA_BUFF 0x3B -#define SCSIOP_READ_DATA_BUFF 0x3C -#define SCSIOP_CHANGE_DEFINITION 0x40 -#define SCSIOP_READ_SUB_CHANNEL 0x42 -#define SCSIOP_READ_TOC 0x43 -#define SCSIOP_READ_HEADER 0x44 -#define SCSIOP_PLAY_AUDIO 0x45 -#define SCSIOP_PLAY_AUDIO_MSF 0x47 -#define SCSIOP_PLAY_TRACK_INDEX 0x48 -#define SCSIOP_PLAY_TRACK_RELATIVE 0x49 -#define SCSIOP_PAUSE_RESUME 0x4B -#define SCSIOP_LOG_SELECT 0x4C -#define SCSIOP_LOG_SENSE 0x4D -#define SCSIOP_MODE_SELECT10 0x55 -#define SCSIOP_MODE_SENSE10 0x5A -#define SCSIOP_LOAD_UNLOAD_SLOT 0xA6 -#define SCSIOP_MECHANISM_STATUS 0xBD -#define SCSIOP_READ_CD 0xBE - -// SCSI read capacity structure -typedef struct _READ_CAPACITY_DATA - { - ULONG blks; /* total blocks (converted to little endian) */ - ULONG blksiz; /* size of each (converted to little endian) */ - } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; - -// SCSI inquiry data -typedef struct _INQUIRYDATA - { - UCHAR DeviceType :5; - UCHAR DeviceTypeQualifier :3; - UCHAR DeviceTypeModifier :7; - UCHAR RemovableMedia :1; - UCHAR Versions; - UCHAR ResponseDataFormat; - UCHAR AdditionalLength; - UCHAR Reserved[2]; - UCHAR SoftReset :1; - UCHAR CommandQueue :1; - UCHAR Reserved2 :1; - UCHAR LinkedCommands :1; - UCHAR Synchronous :1; - UCHAR Wide16Bit :1; - UCHAR Wide32Bit :1; - UCHAR RelativeAddressing :1; - UCHAR VendorId[8]; - UCHAR ProductId[16]; - UCHAR ProductRevisionLevel[4]; - UCHAR VendorSpecific[20]; - UCHAR Reserved3[40]; - } INQUIRYDATA, *PINQUIRYDATA; - -#endif - -// function prototypes -int Pci2000_Detect (struct scsi_host_template *tpnt); -int Pci2000_Command (Scsi_Cmnd *SCpnt); -int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); -int Pci2000_Abort (Scsi_Cmnd *SCpnt); -int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int flags); -int Pci2000_Release (struct Scsi_Host *pshost); -int Pci2000_BiosParam (struct scsi_device *sdev, - struct block_device *bdev, - sector_t capacity, int geom[]); - -#endif -- cgit v1.2.3 From 56937f7b78d3e495a9f557775f3c3ea1d50ca7b3 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 11 Mar 2007 12:25:33 -0500 Subject: [SCSI] sd: typo fix: sdkp_printk should be sd_printk Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 30a4aa0c873..12e18bb5456 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -570,7 +570,7 @@ static int sd_release(struct inode *inode, struct file *filp) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdev = sdkp->device; - SCSI_LOG_HLQUEUE(3, sdkp_printk(KERN_INFO, sdkp, "sd_release\n")); + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); if (!--sdkp->openers && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) -- cgit v1.2.3 From 1544d67738c864245b8a061fb72093daeea8d4f1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 20 Feb 2007 11:17:03 -0800 Subject: [SCSI] fusion: kernel-doc warning fixes Fix kernel-doc warnings in fusion driver code. Signed-off-by: Randy Dunlap Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 22 +++++++--------------- drivers/message/fusion/mptscsih.c | 15 ++++++++++----- drivers/message/fusion/mptspi.c | 11 +++++------ 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 083acfd91d8..0a2d7db7b63 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -4739,12 +4739,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) } /** - * mpt_inactive_raid_list_free - * - * This clears this link list. - * - * @ioc - pointer to per adapter structure - * + * mpt_inactive_raid_list_free - This clears this link list. + * @ioc : pointer to per adapter structure **/ static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) @@ -4764,15 +4760,11 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) } /** - * mpt_inactive_raid_volumes - * - * This sets up link list of phy_disk_nums for devices belonging in an inactive volume - * - * @ioc - pointer to per adapter structure - * @channel - volume channel - * @id - volume target id - * + * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume * + * @ioc : pointer to per adapter structure + * @channel : volume channel + * @id : volume target id **/ static void mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) @@ -6663,7 +6655,7 @@ union loginfo_type { /** * mpt_iocstatus_info_config - IOCSTATUS information for config pages * @ioc: Pointer to MPT_ADAPTER structure - * ioc_status: U32 IOCStatus word from IOC + * @ioc_status: U32 IOCStatus word from IOC * @mf: Pointer to MPT request frame * * Refer to lsi/mpi.h. diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 2a3e9e66d4e..eef00ed139b 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1537,21 +1537,23 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_TMHandler - Generic handler for SCSI Task Management. - * Fall through to mpt_HardResetHandler if: not operational, too many - * failed TM requests or handshake failure. - * - * @ioc: Pointer to MPT_ADAPTER structure + * @hd: Pointer to MPT SCSI HOST structure * @type: Task Management type + * @channel: channel number for task management * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) + * @timeout: timeout for task management control + * + * Fall through to mpt_HardResetHandler if: not operational, too many + * failed TM requests or handshake failure. * * Remark: Currently invoked from a non-interrupt thread (_bh). * * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC * will be active. * - * Returns 0 for SUCCESS, or FAILED. + * Returns 0 for SUCCESS, or %FAILED. **/ int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) @@ -1650,9 +1652,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c * mptscsih_IssueTaskMgmt - Generic send Task Management function. * @hd: Pointer to MPT_SCSI_HOST structure * @type: Task Management type + * @channel: channel number for task management * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) + * @timeout: timeout for task management control * * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) * or a non-interrupt thread. In the former, must not call schedule(). @@ -2022,6 +2026,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) /** * mptscsih_tm_wait_for_completion - wait for completion of TM task * @hd: Pointer to MPT host structure. + * @timeout: timeout value * * Returns {SUCCESS,FAILED}. */ diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 85f21b54cb7..755dec6b7ac 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -96,14 +96,13 @@ static int mptspiTaskCtx = -1; static int mptspiInternalCtx = -1; /* Used only for internal commands */ /** - * mptspi_setTargetNegoParms - Update the target negotiation - * parameters based on the the Inquiry data, adapter capabilities, - * and NVRAM settings - * + * mptspi_setTargetNegoParms - Update the target negotiation parameters * @hd: Pointer to a SCSI Host Structure - * @vtarget: per target private data + * @target: per target private data * @sdev: SCSI device * + * Update the target negotiation parameters based on the the Inquiry + * data, adapter capabilities, and NVRAM settings. **/ static void mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, @@ -234,7 +233,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /** * mptspi_writeIOCPage4 - write IOC Page 4 * @hd: Pointer to a SCSI Host Structure - * @channel: + * @channel: channel number * @id: write IOC Page4 for this ID & Bus * * Return: -EAGAIN if unable to obtain a Message Frame -- cgit v1.2.3 From 840c2835a1c867281d27158378a9d34f593a7664 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 11 Mar 2007 14:16:43 -0500 Subject: [SCSI] make scsi_wait_scan always modular Currently scsi_wait_scan is only built modular if SCSI is modular. However, it's perfectly possible for a built in SCSI still to have modular drivers and thus need scsi_wait_scan as a module. Therefore, scsi_wait_scan should always be built as a module (unless the kernel doesn't support modules). Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 6 ++++++ drivers/scsi/Makefile | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4cd280e8696..f3bc0f459de 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -241,6 +241,12 @@ config SCSI_SCAN_ASYNC You can override this choice by specifying "scsi_mod.scan=sync" or async on the kernel's command line. +config SCSI_WAIT_SCAN + tristate + default m + depends on SCSI + depends on MODULES + menu "SCSI Transports" depends on SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 79ecf4ebe6e..41c7883b24a 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -145,7 +145,7 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o # This goes last, so that "real" scsi devices probe earlier obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o -obj-$(CONFIG_SCSI) += scsi_wait_scan.o +obj-$(CONFIG_SCSI_WAIT_SCAN) += scsi_wait_scan.o scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ -- cgit v1.2.3 From b889d531b635da66ce2704a47febfed68173d9db Mon Sep 17 00:00:00 2001 From: Malahal Naineni Date: Mon, 12 Mar 2007 10:41:26 -0700 Subject: [SCSI] qla2xxx: fix RSCN handling on big-endian systems qla2xxx driver fails to handle RSCN events affecting area or domain due to an endian issue on big endian systems. This fixes the port_id_t structure on big endian systems. Signed-off-by: Malahal Naineni Acked-by: Seokmann Ju Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 05f4f2a378e..e8948b679f5 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1478,14 +1478,17 @@ typedef union { uint32_t b24 : 24; struct { - uint8_t d_id[3]; - uint8_t rsvd_1; - } r; - - struct { +#ifdef __BIG_ENDIAN + uint8_t domain; + uint8_t area; + uint8_t al_pa; +#elif __LITTLE_ENDIAN uint8_t al_pa; uint8_t area; uint8_t domain; +#else +#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!" +#endif uint8_t rsvd_1; } b; } port_id_t; -- cgit v1.2.3 From ed6770863945e6695f403c7b951395dab298c392 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 12 Mar 2007 10:41:27 -0700 Subject: [SCSI] qla2xxx: Add scan_[start|finish]() callbacks for ISP24xx HBAs. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 68f5d24b938..f67ef38b29d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -157,6 +157,8 @@ static struct scsi_host_template qla24xx_driver_template = { .slave_alloc = qla2xxx_slave_alloc, .slave_destroy = qla2xxx_slave_destroy, + .scan_finished = qla2xxx_scan_finished, + .scan_start = qla2xxx_scan_start, .change_queue_depth = qla2x00_change_queue_depth, .change_queue_type = qla2x00_change_queue_type, .this_id = -1, -- cgit v1.2.3 From 40a2e34a94c336b716f631b2952d233e1ba76e3c Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 12 Mar 2007 10:41:28 -0700 Subject: [SCSI] qla2xxx: Add cond_resched() calls during HBA flash manipulation. We're observing soft lockups during HBA FLASH retrieval and update. Add cond_resched() each time around the tight-loops during flash read()s/write()s. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_sup.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index ff1dd4175a7..362d041419f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -466,6 +466,7 @@ qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) udelay(10); else rval = QLA_FUNCTION_TIMEOUT; + cond_resched(); } /* TODO: What happens if we time out? */ @@ -508,6 +509,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) udelay(10); else rval = QLA_FUNCTION_TIMEOUT; + cond_resched(); } return rval; } @@ -1255,6 +1257,7 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data, } udelay(10); barrier(); + cond_resched(); } return status; } @@ -1403,6 +1406,7 @@ qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr, if (saddr % 100) udelay(10); *tmp_buf = data; + cond_resched(); } } @@ -1689,6 +1693,7 @@ update_flash: rval = QLA_FUNCTION_FAILED; break; } + cond_resched(); } } while (0); qla2x00_flash_disable(ha); -- cgit v1.2.3 From fecf97882a8f1e9b52627c30322232c18060aa2c Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 12 Mar 2007 10:41:29 -0700 Subject: [SCSI] qla2xxx: Drop acquisition of hardware_lock during flash manipulations. There's no need given, I/O has been quiesced, RISC interrupts have been disabled, and finally the RISC has been paused. Flash manipulation on ISP21xx, ISP22xx, and ISP23xx parts requires the RISC to go through a full reset to recover. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_sup.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 362d041419f..206bda093da 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1453,7 +1453,6 @@ uint8_t * qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, uint32_t offset, uint32_t length) { - unsigned long flags; uint32_t addr, midpoint; uint8_t *data; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -1462,7 +1461,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, qla2x00_suspend_hba(ha); /* Go with read. */ - spin_lock_irqsave(&ha->hardware_lock, flags); midpoint = ha->optrom_size / 2; qla2x00_flash_enable(ha); @@ -1477,7 +1475,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, *data = qla2x00_read_flash_byte(ha, addr); } qla2x00_flash_disable(ha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Resume HBA. */ qla2x00_resume_hba(ha); @@ -1491,7 +1488,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, { int rval; - unsigned long flags; uint8_t man_id, flash_id, sec_number, data; uint16_t wd; uint32_t addr, liter, sec_mask, rest_addr; @@ -1504,7 +1500,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, sec_number = 0; /* Reset ISP chip. */ - spin_lock_irqsave(&ha->hardware_lock, flags); WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); @@ -1697,7 +1692,6 @@ update_flash: } } while (0); qla2x00_flash_disable(ha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Resume HBA. */ qla2x00_resume_hba(ha); -- cgit v1.2.3 From 27d940352840bb7a55c351b5b5d6e042fcaf8d47 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 12 Mar 2007 10:41:30 -0700 Subject: [SCSI] qla2xxx: Allow the extended-error-logging flag to be dynamic. The module parameter, ql2xextended_error_logging, can now be set dynamically by writing to the following sysfs entry: /sys/module/qla2xxx/parameters/ql2xextended_error_logging This alleviates the need for the driver to be unloaded and reloaded in order to enable logging. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f67ef38b29d..b6c96a8e033 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -62,7 +62,7 @@ MODULE_PARM_DESC(ql2xallocfwdump, "vary by ISP type. Default is 1 - allocate memory."); int ql2xextended_error_logging; -module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR); +module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xextended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging. 1 - log errors."); -- cgit v1.2.3 From 457620b47a5398e779584fc3c470683fbb3d1c8d Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 12 Mar 2007 10:41:31 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.01.07-k6. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 61347aee55c..dc85495c337 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k5" +#define QLA2XXX_VERSION "8.01.07-k6" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -- cgit v1.2.3 From c3d2350a8420dbf9d48f5f8a0fb72117bfcbc1b0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 12 Mar 2007 14:16:35 -0500 Subject: [SCSI] fc_transport: update potential link speeds This patch updates the FC transport for all speeds identified in SM-HBA. Note: it does not sync the "bit" definitions, as that is actually insulated from user-space via the sysfs text string. (I could do it, but it does introduce a potential binary-incompatibility). Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 ++ include/scsi/scsi_transport_fc.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 58afdb40170..14c4f065b2b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -200,6 +200,8 @@ static const struct { { FC_PORTSPEED_2GBIT, "2 Gbit" }, { FC_PORTSPEED_4GBIT, "4 Gbit" }, { FC_PORTSPEED_10GBIT, "10 Gbit" }, + { FC_PORTSPEED_8GBIT, "8 Gbit" }, + { FC_PORTSPEED_16GBIT, "16 Gbit" }, { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, }; fc_bitfield_name_search(port_speed, fc_port_speed_names) diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 798f7c7ee42..1e797308640 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -108,6 +108,8 @@ enum fc_port_state { #define FC_PORTSPEED_2GBIT 2 #define FC_PORTSPEED_4GBIT 4 #define FC_PORTSPEED_10GBIT 8 +#define FC_PORTSPEED_8GBIT 0x10 +#define FC_PORTSPEED_16GBIT 0x20 #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ /* -- cgit v1.2.3 From a52decafbe3fdca5e8430d4f58ffcec1f4a6302c Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 13 Mar 2007 10:07:15 +0900 Subject: [SCSI] tgt: remove the code to build sense tgt notifies a LLD of the failure with sense when it hits the user-space daemon bugs. However, tgt doesn't know anything about SCSI devices that initiators talks to. So it's impossible to send proper sense buffer (format and contents). This patch changes tgt not to notify a LLD of the failure with bogus sense. Instead, tgt just re-queues the failure command to the internal list so that it will be freed cleanly later on when the scsi_host is removed. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_lib.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index c05dff95bd9..2570f48a69c 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -459,16 +459,6 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } -static void scsi_tgt_build_sense(unsigned char *sense_buffer, unsigned char key, - unsigned char asc, unsigned char asq) -{ - sense_buffer[0] = 0x70; - sense_buffer[2] = key; - sense_buffer[7] = 0xa; - sense_buffer[12] = asc; - sense_buffer[13] = asq; -} - int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, unsigned long uaddr, u32 len, unsigned long sense_uaddr, u32 sense_len, u8 rw) @@ -528,12 +518,21 @@ int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, * user-space daemon bugs or OOM * TODO: we can do better for OOM. */ + struct scsi_tgt_queuedata *qdata; + struct list_head *head; + unsigned long flags; + eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n", cmd, err, uaddr, len, rw); - cmd->result = SAM_STAT_CHECK_CONDITION; - memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - scsi_tgt_build_sense(cmd->sense_buffer, - HARDWARE_ERROR, 0, 0); + + qdata = shost->uspace_req_q->queuedata; + head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)]; + + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + list_add(&tcmd->hash_list, head); + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); + + goto done; } } err = scsi_tgt_transfer_response(cmd); -- cgit v1.2.3 From b22f687dd28a7a8886b918294b4d558ef175c07d Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Tue, 13 Mar 2007 16:53:28 -0400 Subject: [SCSI] set resid in scsi_io_completion() even for check condition Some targets can return both valid data and sense information. Always update the request data_len from the SCSI command residual. Callers should interpret sense data to determine what parts of the data are valid in case of a CHECK CONDITION status. Signed-off-by: Pete Wyckoff Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5f955707d90..be8e6558b89 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -848,8 +848,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) memcpy(req->sense, cmd->sense_buffer, len); req->sense_len = len; } - } else - req->data_len = cmd->resid; + } + req->data_len = cmd->resid; } /* -- cgit v1.2.3 From 8418852d11f0bbaeebeedd4243560d8fdc85410d Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:05 -0700 Subject: [SCSI] aacraid: add restart adapter platform function Received from Mark Salyzyn, This patch updates the adapter restart function to deal with some adapters that have specific IOP reset needs. Since the code for restarting the adapter was in two places, changed over to utilizing a platform function in one place. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 4 ++++ drivers/scsi/aacraid/commsup.c | 13 +------------ drivers/scsi/aacraid/rx.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 39ecd0d22eb..7e25c0bbd64 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -497,6 +497,7 @@ struct adapter_ops void (*adapter_enable_int)(struct aac_dev *dev); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); int (*adapter_check_health)(struct aac_dev *dev); + int (*adapter_restart)(struct aac_dev *dev, int bled); /* Transport operations */ int (*adapter_ioremap)(struct aac_dev * dev, u32 size); irqreturn_t (*adapter_intr)(int irq, void *dev_id); @@ -1060,6 +1061,9 @@ struct aac_dev #define aac_adapter_check_health(dev) \ (dev)->a_ops.adapter_check_health(dev) +#define aac_adapter_restart(dev,bled) \ + (dev)->a_ops.adapter_restart(dev,bled) + #define aac_adapter_ioremap(dev, size) \ (dev)->a_ops.adapter_ioremap(dev, size) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 1b97f60652b..55bf6f395e9 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1035,7 +1035,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) static int _aac_reset_adapter(struct aac_dev *aac) { int index, quirks; - u32 ret; int retval; struct Scsi_Host *host; struct scsi_device *dev; @@ -1059,20 +1058,10 @@ static int _aac_reset_adapter(struct aac_dev *aac) * If a positive health, means in a known DEAD PANIC * state and the adapter could be reset to `try again'. */ - retval = aac_adapter_check_health(aac); - if (retval == 0) - retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS, - 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); - if (retval) - retval = aac_adapter_sync_cmd(aac, IOP_RESET, - 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); + retval = aac_adapter_restart(aac, aac_adapter_check_health(aac)); if (retval) goto out; - if (ret != 0x00000001) { - retval = -ENODEV; - goto out; - } /* * Loop through the fibs, close the synchronous FIBS diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index d242e2611d6..00e3cba9d8e 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -460,22 +460,31 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) return 0; } -static int aac_rx_restart_adapter(struct aac_dev *dev) +static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) { u32 var; - printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", - dev->name, dev->id); - - if (aac_rx_check_health(dev) <= 0) - return 1; - if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, - &var, NULL, NULL, NULL, NULL)) - return 1; + if (bled) + printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", + dev->name, dev->id, bled); + else + bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, + 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); + if (bled) + bled = aac_adapter_sync_cmd(dev, IOP_RESET, + 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); + + if (bled) + return -EINVAL; + if (var == 0x3803000F) { /* USE_OTHER_METHOD */ + rx_writel(dev, MUnit.reserved2, 3); + msleep(5000); /* Delay 5 seconds */ + var = 0x00000001; + } if (var != 0x00000001) - return 1; + return -EINVAL; if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) - return 1; + return -ENODEV; return 0; } @@ -532,9 +541,12 @@ int _aac_rx_init(struct aac_dev *dev) * Check to see if the board panic'd while booting. */ status = rx_readl(dev, MUnit.OMRx[0]); - if (status & KERNEL_PANIC) - if (aac_rx_restart_adapter(dev)) + if (status & KERNEL_PANIC) { + if ((status = aac_rx_check_health(dev)) <= 0) goto error_iounmap; + if (aac_rx_restart_adapter(dev, status)) + goto error_iounmap; + } /* * Check to see if the board failed any self tests. */ @@ -572,6 +584,7 @@ int _aac_rx_init(struct aac_dev *dev) dev->a_ops.adapter_notify = aac_rx_notify_adapter; dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_check_health = aac_rx_check_health; + dev->a_ops.adapter_restart = aac_rx_restart_adapter; /* * First clear out all interrupts. Then enable the one's that we -- cgit v1.2.3 From a8166a52968216ae079a5530ac3269147de2ef31 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:22 -0700 Subject: [SCSI] aacraid: Fix struct element name issue Received from Mark Salyzyn, This patch is to resolve a namespace issue that will result from a patch expected in the future that adds a new interface; rationalized as correcting a long term issue where hw_fib, instead of hw_fib_va, refers to the virtual address space and hw_fib_pa refers to the physical address space. A small fragment of this patch also cleans up an unused variable that was close to the patch fragments. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 4 +-- drivers/scsi/aacraid/commctrl.c | 16 ++++++------ drivers/scsi/aacraid/commsup.c | 54 +++++++++++++++++++---------------------- drivers/scsi/aacraid/dpcsup.c | 8 +++--- drivers/scsi/aacraid/rx.c | 4 +-- 5 files changed, 41 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 7e25c0bbd64..9ca594b33d1 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -834,7 +834,7 @@ struct fib { */ struct list_head fiblink; void *data; - struct hw_fib *hw_fib; /* Actual shared object */ + struct hw_fib *hw_fib_va; /* Actual shared object */ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ }; @@ -1821,7 +1821,7 @@ int aac_fib_send(u16 command, struct fib * context, unsigned long size, int prio int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); int aac_fib_complete(struct fib * context); -#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) +#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) struct aac_dev *aac_init_adapter(struct aac_dev *dev); int aac_get_config_status(struct aac_dev *dev, int commit_flag); int aac_get_containers(struct aac_dev *dev); diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index e21070f4eac..83d5680e132 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -69,7 +69,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) return -ENOMEM; } - kfib = fibptr->hw_fib; + kfib = fibptr->hw_fib_va; /* * First copy in the header so that we can check the size field. */ @@ -91,9 +91,9 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) goto cleanup; } /* Highjack the hw_fib */ - hw_fib = fibptr->hw_fib; + hw_fib = fibptr->hw_fib_va; hw_fib_pa = fibptr->hw_fib_pa; - fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa); + fibptr->hw_fib_va = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa); memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size); memcpy(kfib, hw_fib, dev->max_fib_size); } @@ -137,7 +137,7 @@ cleanup: if (hw_fib) { pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa); fibptr->hw_fib_pa = hw_fib_pa; - fibptr->hw_fib = hw_fib; + fibptr->hw_fib_va = hw_fib; } if (retval != -EINTR) aac_fib_free(fibptr); @@ -282,15 +282,15 @@ return_fib: fib = list_entry(entry, struct fib, fiblink); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { - kfree(fib->hw_fib); + if (copy_to_user(f.fib, fib->hw_fib_va, sizeof(struct hw_fib))) { + kfree(fib->hw_fib_va); kfree(fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ - kfree(fib->hw_fib); + kfree(fib->hw_fib_va); kfree(fib); status = 0; } else { @@ -340,7 +340,7 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) /* * Free the space occupied by this copy of the fib. */ - kfree(fib->hw_fib); + kfree(fib->hw_fib_va); kfree(fib); } /* diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 55bf6f395e9..e67ff13eb35 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -94,7 +94,7 @@ void aac_fib_map_free(struct aac_dev *dev) int aac_fib_setup(struct aac_dev * dev) { struct fib *fibptr; - struct hw_fib *hw_fib_va; + struct hw_fib *hw_fib; dma_addr_t hw_fib_pa; int i; @@ -106,24 +106,24 @@ int aac_fib_setup(struct aac_dev * dev) if (i<0) return -ENOMEM; - hw_fib_va = dev->hw_fib_va; + hw_fib = dev->hw_fib_va; hw_fib_pa = dev->hw_fib_pa; - memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); + memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); /* * Initialise the fibs */ for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) { fibptr->dev = dev; - fibptr->hw_fib = hw_fib_va; - fibptr->data = (void *) fibptr->hw_fib->data; + fibptr->hw_fib_va = hw_fib; + fibptr->data = (void *) fibptr->hw_fib_va->data; fibptr->next = fibptr+1; /* Forward chain the fibs */ init_MUTEX_LOCKED(&fibptr->event_wait); spin_lock_init(&fibptr->event_lock); - hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); - hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size); + hw_fib->header.XferState = cpu_to_le32(0xffffffff); + hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); fibptr->hw_fib_pa = hw_fib_pa; - hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size); + hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size); hw_fib_pa = hw_fib_pa + dev->max_fib_size; } /* @@ -166,7 +166,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) * Null out fields that depend on being zero at the start of * each I/O */ - fibptr->hw_fib->header.XferState = 0; + fibptr->hw_fib_va->header.XferState = 0; fibptr->callback = NULL; fibptr->callback_data = NULL; @@ -191,10 +191,10 @@ void aac_fib_free(struct fib *fibptr) fibptr->next = fibptr->dev->timeout_fib; fibptr->dev->timeout_fib = fibptr; } else { - if (fibptr->hw_fib->header.XferState != 0) { + if (fibptr->hw_fib_va->header.XferState != 0) { printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", (void*)fibptr, - le32_to_cpu(fibptr->hw_fib->header.XferState)); + le32_to_cpu(fibptr->hw_fib_va->header.XferState)); } fibptr->next = fibptr->dev->free_fib; fibptr->dev->free_fib = fibptr; @@ -211,7 +211,7 @@ void aac_fib_free(struct fib *fibptr) void aac_fib_init(struct fib *fibptr) { - struct hw_fib *hw_fib = fibptr->hw_fib; + struct hw_fib *hw_fib = fibptr->hw_fib_va; hw_fib->header.StructType = FIB_MAGIC; hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); @@ -231,7 +231,7 @@ void aac_fib_init(struct fib *fibptr) static void fib_dealloc(struct fib * fibptr) { - struct hw_fib *hw_fib = fibptr->hw_fib; + struct hw_fib *hw_fib = fibptr->hw_fib_va; BUG_ON(hw_fib->header.StructType != FIB_MAGIC); hw_fib->header.XferState = 0; } @@ -386,7 +386,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, void *callback_data) { struct aac_dev * dev = fibptr->dev; - struct hw_fib * hw_fib = fibptr->hw_fib; + struct hw_fib * hw_fib = fibptr->hw_fib_va; unsigned long flags = 0; unsigned long qflags; @@ -430,7 +430,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, */ hw_fib->header.Command = cpu_to_le16(command); hw_fib->header.XferState |= cpu_to_le32(SentFromHost); - fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ + fibptr->hw_fib_va->header.Flags = 0; /* 0 the flags field - internal only*/ /* * Set the size of the Fib we want to send to the adapter */ @@ -462,7 +462,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState))); - dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); + dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib_va)); dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); @@ -624,7 +624,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) { - struct hw_fib * hw_fib = fibptr->hw_fib; + struct hw_fib * hw_fib = fibptr->hw_fib_va; struct aac_dev * dev = fibptr->dev; struct aac_queue * q; unsigned long nointr = 0; @@ -688,7 +688,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) int aac_fib_complete(struct fib *fibptr) { - struct hw_fib * hw_fib = fibptr->hw_fib; + struct hw_fib * hw_fib = fibptr->hw_fib_va; /* * Check for a fib which has already been completed @@ -774,9 +774,8 @@ void aac_printf(struct aac_dev *dev, u32 val) #define AIF_SNIFF_TIMEOUT (30*HZ) static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { - struct hw_fib * hw_fib = fibptr->hw_fib; + struct hw_fib * hw_fib = fibptr->hw_fib_va; struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; - int busy; u32 container; struct scsi_device *device; enum { @@ -988,9 +987,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) * behind you. */ - busy = 0; - - /* * Find the scsi_device associated with the SCSI address, * and mark it as changed, invalidating the cache. This deals @@ -1068,8 +1064,8 @@ static int _aac_reset_adapter(struct aac_dev *aac) */ for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { struct fib *fib = &aac->fibs[index]; - if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && - (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) { + if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && + (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) { unsigned long flagv; spin_lock_irqsave(&fib->event_lock, flagv); up(&fib->event_wait); @@ -1237,7 +1233,7 @@ int aac_check_health(struct aac_dev * aac) memset(hw_fib, 0, sizeof(struct hw_fib)); memset(fib, 0, sizeof(struct fib)); - fib->hw_fib = hw_fib; + fib->hw_fib_va = hw_fib; fib->dev = aac; aac_fib_init(fib); fib->type = FSAFS_NTC_FIB_CONTEXT; @@ -1343,11 +1339,11 @@ int aac_command_thread(void *data) * do anything at this point since we don't have * anything defined for this thread to do. */ - hw_fib = fib->hw_fib; + hw_fib = fib->hw_fib_va; memset(fib, 0, sizeof(struct fib)); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof( struct fib ); - fib->hw_fib = hw_fib; + fib->hw_fib_va = hw_fib; fib->data = hw_fib->data; fib->dev = dev; /* @@ -1474,7 +1470,7 @@ int aac_command_thread(void *data) */ memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); memcpy(newfib, fib, sizeof(struct fib)); - newfib->hw_fib = hw_newfib; + newfib->hw_fib_va = hw_newfib; /* * Put the FIB onto the * fibctx's fibs diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d38b628be1a..26f4d563d95 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -73,7 +73,7 @@ unsigned int aac_response_normal(struct aac_queue * q) u32 index = le32_to_cpu(entry->addr); fast = index & 0x01; fib = &dev->fibs[index >> 2]; - hwfib = fib->hw_fib; + hwfib = fib->hw_fib_va; aac_consumer_free(dev, q, HostNormRespQueue); /* @@ -193,7 +193,7 @@ unsigned int aac_command_normal(struct aac_queue *q) INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof(struct fib); - fib->hw_fib = hw_fib; + fib->hw_fib_va = hw_fib; fib->data = hw_fib->data; fib->dev = dev; @@ -259,7 +259,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof(struct fib); - fib->hw_fib = hw_fib; + fib->hw_fib_va = hw_fib; fib->data = hw_fib->data; fib->dev = dev; @@ -271,7 +271,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) } else { int fast = index & 0x01; struct fib * fib = &dev->fibs[index >> 2]; - struct hw_fib * hwfib = fib->hw_fib; + struct hw_fib * hwfib = fib->hw_fib_va; /* * Remove this fib from the Outstanding I/O queue. diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 00e3cba9d8e..6f8a19462e4 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -387,7 +387,7 @@ static int aac_rx_deliver_producer(struct fib * fib) unsigned long nointr = 0; spin_lock_irqsave(q->lock, qflags); - aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr); + aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); q->numpending++; *(q->headers.producer) = cpu_to_le32(Index + 1); @@ -437,7 +437,7 @@ static int aac_rx_deliver_message(struct fib * fib) device += sizeof(u32); writel((u32)(addr >> 32), device); device += sizeof(u32); - writel(le16_to_cpu(fib->hw_fib->header.Size), device); + writel(le16_to_cpu(fib->hw_fib_va->header.Size), device); rx_writel(dev, MUnit.InboundQueue, Index); return 0; } -- cgit v1.2.3 From fe76df4235986cfacc2d3b71cef7c42bc1a6dd6c Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 12:55:07 -0700 Subject: [SCSI] aacraid: Fix blocking issue with container probing function (cast update) Received from Mark Salyzyn, The aac_probe_container call blocks. This is an issue because it is called on occasion in the context of the queuecommand handler. Once in a blue moon this has resulted in a kernel panic sleeping during interrupt; or problems with some embedded system versions of the kernel that depend on queuecommand to not block. This ugly patch rewrites the aac_probe_container call into a new routine _aac_probe_container that is an asynchronous state machine to complete the series of operations. The legacy blocking aac_probe_container call used in other areas of the driver (during initialization scanning for all targets and in the separate hot-add/remove [aacraid] thread) merely issues _aac_probe_container and then simple spins calling schedule() waiting for completion. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 311 +++++++++++++++++++++++------------------- 1 file changed, 169 insertions(+), 142 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index d789e61bdc4..1610f0670c7 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -258,13 +258,10 @@ int aac_get_containers(struct aac_dev *dev) u32 index; int status = 0; struct fib * fibptr; - unsigned instance; struct aac_get_container_count *dinfo; struct aac_get_container_count_resp *dresp; int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - instance = dev->scsi_host_ptr->unique_id; - if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; @@ -284,88 +281,35 @@ int aac_get_containers(struct aac_dev *dev) maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); aac_fib_complete(fibptr); } + aac_fib_free(fibptr); if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - fsa_dev_ptr = kmalloc( - sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); - if (!fsa_dev_ptr) { - aac_fib_free(fibptr); + fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, + GFP_KERNEL); + if (!fsa_dev_ptr) return -ENOMEM; - } memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); dev->fsa_dev = fsa_dev_ptr; dev->maximum_num_containers = maximum_num_containers; - for (index = 0; index < dev->maximum_num_containers; index++) { - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - + for (index = 0; index < dev->maximum_num_containers; ) { fsa_dev_ptr[index].devname[0] = '\0'; - aac_fib_init(fibptr); - dinfo = (struct aac_query_mount *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); + status = aac_probe_container(dev, index); - status = aac_fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0 ) { + if (status < 0) { printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); break; } - dresp = (struct aac_mount *)fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { - dinfo->command = cpu_to_le32(VM_NameServe64); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); - if (aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL) < 0) - continue; - } else - dresp->mnt[0].capacityhigh = 0; - - dprintk ((KERN_DEBUG - "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n", - (int)index, (int)le32_to_cpu(dresp->status), - (int)le32_to_cpu(dresp->mnt[0].vol), - (int)le32_to_cpu(dresp->mnt[0].state), - ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32))); - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr[index].valid = 1; - fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[index].size - = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr[index].ro = 1; - } - aac_fib_complete(fibptr); /* * If there are no more containers, then stop asking. */ - if ((index + 1) >= le32_to_cpu(dresp->count)){ + if (++index >= status) break; - } } - aac_fib_free(fibptr); return status; } @@ -473,85 +417,185 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) return -1; } -/** - * aac_probe_container - query a logical volume - * @dev: device to query - * @cid: container identifier - * - * Queries the controller about the given volume. The volume information - * is updated in the struct fsa_dev_info structure rather than returned. - */ - -int aac_probe_container(struct aac_dev *dev, int cid) +static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) { - struct fsa_dev_info *fsa_dev_ptr; - int status; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; - fsa_dev_ptr = dev->fsa_dev; - if (!fsa_dev_ptr) - return -ENOMEM; - instance = dev->scsi_host_ptr->unique_id; + if (fsa_dev_ptr[scmd_id(scsicmd)].valid) + return aac_scsi_cmd(scsicmd); - if (!(fibptr = aac_fib_alloc(dev))) - return -ENOMEM; + scsicmd->result = DID_NO_CONNECT << 16; + scsicmd->scsi_done(scsicmd); + return 0; +} + +static int _aac_probe_container2(void * context, struct fib * fibptr) +{ + struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + int (*callback)(struct scsi_cmnd *); + + scsicmd->SCp.Status = 0; + if (fsa_dev_ptr) { + struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); + fsa_dev_ptr += scmd_id(scsicmd); + + if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + fsa_dev_ptr->valid = 1; + fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr->size + = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); + fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0); + } + if ((fsa_dev_ptr->valid & 1) == 0) + fsa_dev_ptr->valid = 0; + scsicmd->SCp.Status = le32_to_cpu(dresp->count); + } + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); + scsicmd->SCp.ptr = NULL; + return (*callback)(scsicmd); +} + +static int _aac_probe_container1(void * context, struct fib * fibptr) +{ + struct scsi_cmnd * scsicmd; + struct aac_mount * dresp; + struct aac_query_mount *dinfo; + int status; + + dresp = (struct aac_mount *) fib_data(fibptr); + dresp->mnt[0].capacityhigh = 0; + if ((le32_to_cpu(dresp->status) != ST_OK) || + ((le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) == FSCS_HIDDEN))) + return _aac_probe_container2(context, fibptr); + scsicmd = (struct scsi_cmnd *) context; + scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(cid); + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); status = aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 0, 1, + (fib_callback) _aac_probe_container2, + (void *) scsicmd); + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } if (status < 0) { - printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n"); - goto error; + /* Inherit results from VM_NameServe, if any */ + dresp->status = cpu_to_le32(ST_OK); + return _aac_probe_container2(context, fibptr); } + return 0; +} - dresp = (struct aac_mount *) fib_data(fibptr); +static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)) +{ + struct fib * fibptr; + int status = -ENOMEM; - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { - dinfo->command = cpu_to_le32(VM_NameServe64); - dinfo->count = cpu_to_le32(cid); - dinfo->type = cpu_to_le32(FT_FILESYS); + if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) { + struct aac_query_mount *dinfo; - if (aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL) < 0) - goto error; - } else - dresp->mnt[0].capacityhigh = 0; + aac_fib_init(fibptr); + + dinfo = (struct aac_query_mount *)fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); + dinfo->type = cpu_to_le32(FT_FILESYS); + scsicmd->SCp.ptr = (char *)callback; - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr[cid].valid = 1; - fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[cid].size - = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr[cid].ro = 1; + status = aac_fib_send(ContainerCommand, + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 0, 1, + (fib_callback) _aac_probe_container1, + (void *) scsicmd); + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } + if (status < 0) { + scsicmd->SCp.ptr = NULL; + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + } + } + if (status < 0) { + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + if (fsa_dev_ptr) { + fsa_dev_ptr += scmd_id(scsicmd); + if ((fsa_dev_ptr->valid & 1) == 0) { + fsa_dev_ptr->valid = 0; + return (*callback)(scsicmd); + } + } } + return status; +} -error: - aac_fib_complete(fibptr); - aac_fib_free(fibptr); +/** + * aac_probe_container - query a logical volume + * @dev: device to query + * @cid: container identifier + * + * Queries the controller about the given volume. The volume information + * is updated in the struct fsa_dev_info structure rather than returned. + */ +static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd) +{ + scsicmd->device = NULL; + return 0; +} +int aac_probe_container(struct aac_dev *dev, int cid) +{ + struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); + struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL); + int status; + + if (!scsicmd || !scsidev) { + kfree(scsicmd); + kfree(scsidev); + return -ENOMEM; + } + scsicmd->list.next = NULL; + scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1; + + scsicmd->device = scsidev; + scsidev->sdev_state = 0; + scsidev->id = cid; + scsidev->host = dev->scsi_host_ptr; + + if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) + while (scsicmd->device == scsidev) + schedule(); + status = scsicmd->SCp.Status; + kfree(scsicmd); + kfree(scsidev); return status; } @@ -1646,29 +1690,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case TEST_UNIT_READY: if (dev->in_reset) return -1; - spin_unlock_irq(host->host_lock); - aac_probe_container(dev, cid); - if ((fsa_dev_ptr[cid].valid & 1) == 0) - fsa_dev_ptr[cid].valid = 0; - spin_lock_irq(host->host_lock); - if (fsa_dev_ptr[cid].valid == 0) { - scsicmd->result = DID_NO_CONNECT << 16; - scsicmd->scsi_done(scsicmd); - return 0; - } + return _aac_probe_container(scsicmd, + aac_probe_container_callback2); default: break; } } - /* - * If the target container still doesn't exist, - * return failure - */ - if (fsa_dev_ptr[cid].valid == 0) { - scsicmd->result = DID_BAD_TARGET << 16; - scsicmd->scsi_done(scsicmd); - return 0; - } } else { /* check for physical non-dasd devices */ if ((dev->nondasd_support == 1) || expose_physicals) { if (dev->in_reset) -- cgit v1.2.3 From 33bb3b296207ff4f9e3b8dddb623e645ee1b8809 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:27:21 -0700 Subject: [SCSI] aacraid: Fix ioctl handling when adapter resets Received from Mark Salyzyn, Outstanding ioctl calls still have some problems with aborting cleanly in the face of a reset iop recovery action should the adapter ever enter into a Firmware Assert (BlinkLED) condition. The enclosed patch resolves some uncovered flawed handling. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commctrl.c | 7 +++++++ drivers/scsi/aacraid/commsup.c | 20 ++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 83d5680e132..3a8e7cac9ee 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -64,6 +64,9 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) unsigned size; int retval; + if (dev->in_reset) { + return -EBUSY; + } fibptr = aac_fib_alloc(dev); if(fibptr == NULL) { return -ENOMEM; @@ -469,6 +472,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) int i; + if (dev->in_reset) { + dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n")); + return -EBUSY; + } if (!capable(CAP_SYS_ADMIN)){ dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); return -EPERM; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index e67ff13eb35..c933df30f58 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -513,15 +513,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } udelay(5); } - } else if (down_interruptible(&fibptr->event_wait)) { - spin_lock_irqsave(&fibptr->event_lock, flags); - if (fibptr->done == 0) { - fibptr->done = 2; /* Tell interrupt we aborted */ - spin_unlock_irqrestore(&fibptr->event_lock, flags); - return -EINTR; - } + } else + (void)down_interruptible(&fibptr->event_wait); + spin_lock_irqsave(&fibptr->event_lock, flags); + if (fibptr->done == 0) { + fibptr->done = 2; /* Tell interrupt we aborted */ spin_unlock_irqrestore(&fibptr->event_lock, flags); + return -EINTR; } + spin_unlock_irqrestore(&fibptr->event_lock, flags); BUG_ON(fibptr->done == 0); if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ @@ -1062,7 +1062,7 @@ static int _aac_reset_adapter(struct aac_dev *aac) /* * Loop through the fibs, close the synchronous FIBS */ - for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { + for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { struct fib *fib = &aac->fibs[index]; if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) { @@ -1071,8 +1071,12 @@ static int _aac_reset_adapter(struct aac_dev *aac) up(&fib->event_wait); spin_unlock_irqrestore(&fib->event_lock, flagv); schedule(); + retval = 0; } } + /* Give some extra time for ioctls to complete. */ + if (retval == 0) + ssleep(2); index = aac->cardtype; /* -- cgit v1.2.3 From 9e7c349c91db3a9f9ac6cd74a693c4093c7d4571 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:55 -0700 Subject: [SCSI] aacraid: remove un-needed references to container id (cid) Received from Mark Salyzyn, This little patch removes the ',cid)' container identification argument from some of the functions. The argument is used in some cases as merely a debug helper and thus not used, and in others, the value can be quickly acquired from the scsi command in their single solitary use in the procedure rather than wasting resources on passing the argument in from above. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 1610f0670c7..3d21d7dd2e5 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -375,7 +375,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) /** * aac_get_container_name - get container name, none blocking. */ -static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) +static int aac_get_container_name(struct scsi_cmnd * scsicmd) { int status; struct aac_get_name *dinfo; @@ -392,7 +392,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) dinfo->command = cpu_to_le32(VM_ContainerConfig); dinfo->type = cpu_to_le32(CT_READ_NAME); - dinfo->cid = cpu_to_le32(cid); + dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); status = aac_fib_send(ContainerCommand, @@ -1361,7 +1361,7 @@ static void io_callback(void *context, struct fib * fibptr) scsicmd->scsi_done(scsicmd); } -static int aac_read(struct scsi_cmnd * scsicmd, int cid) +static int aac_read(struct scsi_cmnd * scsicmd) { u64 lba; u32 count; @@ -1375,7 +1375,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) */ switch (scsicmd->cmnd[0]) { case READ_6: - dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd))); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; @@ -1385,7 +1385,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) count = 256; break; case READ_16: - dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 56) | ((u64)scsicmd->cmnd[3] << 48) | @@ -1399,7 +1399,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; break; case READ_12: - dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | @@ -1409,7 +1409,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; break; default: - dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | @@ -1449,7 +1449,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) return 0; } -static int aac_write(struct scsi_cmnd * scsicmd, int cid) +static int aac_write(struct scsi_cmnd * scsicmd) { u64 lba; u32 count; @@ -1468,7 +1468,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) if (count == 0) count = 256; } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ - dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 56) | ((u64)scsicmd->cmnd[3] << 48) | @@ -1480,14 +1480,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ - dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; } else { - dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } @@ -1567,7 +1567,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) cmd->scsi_done(cmd); } -static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) +static int aac_synchronize(struct scsi_cmnd *scsicmd) { int status; struct fib *cmd_fibcontext; @@ -1612,7 +1612,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) synchronizecmd = fib_data(cmd_fibcontext); synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); - synchronizecmd->cid = cpu_to_le32(cid); + synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); synchronizecmd->count = cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); @@ -1760,7 +1760,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); - return aac_get_container_name(scsicmd, cid); + return aac_get_container_name(scsicmd); } case SERVICE_ACTION_IN: if (!(dev->raw_io_interface) || @@ -1926,7 +1926,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) min(sizeof(fsa_dev_ptr[cid].devname), sizeof(scsicmd->request->rq_disk->disk_name) + 1)); - return aac_read(scsicmd, cid); + return aac_read(scsicmd); case WRITE_6: case WRITE_10: @@ -1934,11 +1934,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case WRITE_16: if (dev->in_reset) return -1; - return aac_write(scsicmd, cid); + return aac_write(scsicmd); case SYNCHRONIZE_CACHE: /* Issue FIB to tell Firmware to flush it's cache */ - return aac_synchronize(scsicmd, cid); + return aac_synchronize(scsicmd); default: /* -- cgit v1.2.3 From f2b1a06ad46209c6e631e3099138d1fa3f14d3a8 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:27:32 -0700 Subject: [SCSI] aacraid: fix srb ioctl for 64 bits Received from Mark Salyzyn, The raw srb ioctl is supposed to be able to take packets with 32 and 64 bit virtual address SG elements, it did not handle the frames with 64 bit SG elements well when communicating with 64 bit DMA capable adapters, and it did not handle the 32 bit limited DMA adapters at all. The enclosed patch now handles all four quadrants (32 bit / 64 bit SG elements in SRB requests + 32 bit or 64 bit DMA capable adapters) This fix is required before Java based management applications in a 64 bit user space can submit raw srb requests to the array physical components via the ioctl mechanism, the allocated user memory pool on 64 bit machines under this environment forced the management software's hands to submit 64 bit user space virtual address SG elements in via the ioctl. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commctrl.c | 259 ++++++++++++++++++++++++---------------- 1 file changed, 157 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 3a8e7cac9ee..987e35e4078 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -468,7 +468,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) void *sg_list[32]; u32 sg_indx = 0; u32 byte_count = 0; - u32 actual_fibsize = 0; + u32 actual_fibsize64, actual_fibsize = 0; int i; @@ -481,7 +481,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) return -EPERM; } /* - * Allocate and initialize a Fib then setup a BlockWrite command + * Allocate and initialize a Fib then setup a SRB command */ if (!(srbfib = aac_fib_alloc(dev))) { return -ENOMEM; @@ -548,129 +548,183 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -EINVAL; goto cleanup; } - if (dev->dac_support == 1) { + actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) + + ((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry)); + actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) * + (sizeof(struct sgentry64) - sizeof(struct sgentry)); + /* User made a mistake - should not continue */ + if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) { + dprintk((KERN_DEBUG"aacraid: Bad Size specified in " + "Raw SRB command calculated fibsize=%lu;%lu " + "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu " + "issued fibsize=%d\n", + actual_fibsize, actual_fibsize64, user_srbcmd->sg.count, + sizeof(struct aac_srb), sizeof(struct sgentry), + sizeof(struct sgentry64), fibsize)); + rcode = -EINVAL; + goto cleanup; + } + if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) { + dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n")); + rcode = -EINVAL; + goto cleanup; + } + byte_count = 0; + if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) { struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg; struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; - struct user_sgmap* usg; - byte_count = 0; /* * This should also catch if user used the 32 bit sgmap */ - actual_fibsize = sizeof(struct aac_srb) - - sizeof(struct sgentry) + - ((upsg->count & 0xff) * - sizeof(struct sgentry)); - if(actual_fibsize != fibsize){ // User made a mistake - should not continue - dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n")); - rcode = -EINVAL; - goto cleanup; - } - usg = kmalloc(actual_fibsize - sizeof(struct aac_srb) - + sizeof(struct sgmap), GFP_KERNEL); - if (!usg) { - dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n")); - rcode = -ENOMEM; - goto cleanup; - } - memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb) - + sizeof(struct sgmap)); - actual_fibsize = sizeof(struct aac_srb) - - sizeof(struct sgentry) + ((usg->count & 0xff) * - sizeof(struct sgentry64)); - if ((data_dir == DMA_NONE) && upsg->count) { - kfree (usg); - dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n")); - rcode = -EINVAL; - goto cleanup; - } + if (actual_fibsize64 == fibsize) { + actual_fibsize = actual_fibsize64; + for (i = 0; i < upsg->count; i++) { + u64 addr; + void* p; + /* Does this really need to be GFP_DMA? */ + p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA); + if(p == 0) { + dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + upsg->sg[i].count,i,upsg->count)); + rcode = -ENOMEM; + goto cleanup; + } + addr = (u64)upsg->sg[i].addr[0]; + addr += ((u64)upsg->sg[i].addr[1]) << 32; + sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_list[i] = p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ + dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir); - for (i = 0; i < usg->count; i++) { - u64 addr; - void* p; - /* Does this really need to be GFP_DMA? */ - p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); - if(p == 0) { - kfree (usg); - dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", - usg->sg[i].count,i,usg->count)); + psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); + psg->sg[i].addr[1] = cpu_to_le32(addr>>32); + byte_count += upsg->sg[i].count; + psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); + } + } else { + struct user_sgmap* usg; + usg = kmalloc(actual_fibsize - sizeof(struct aac_srb) + + sizeof(struct sgmap), GFP_KERNEL); + if (!usg) { + dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n")); rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(long)usg->sg[i].addr; - sg_list[i] = p; // save so we can clean up later - sg_indx = i; - - if( flags & SRB_DataOut ){ - if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ + memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb) + + sizeof(struct sgmap)); + actual_fibsize = actual_fibsize64; + + for (i = 0; i < usg->count; i++) { + u64 addr; + void* p; + /* Does this really need to be GFP_DMA? */ + p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); + if(p == 0) { kfree (usg); - dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); - rcode = -EFAULT; + dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + usg->sg[i].count,i,usg->count)); + rcode = -ENOMEM; goto cleanup; } - } - addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir); + sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr; + sg_list[i] = p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ + kfree (usg); + dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir); - psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); - psg->sg[i].addr[1] = cpu_to_le32(addr>>32); - psg->sg[i].count = cpu_to_le32(usg->sg[i].count); - byte_count += usg->sg[i].count; + psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); + psg->sg[i].addr[1] = cpu_to_le32(addr>>32); + byte_count += usg->sg[i].count; + psg->sg[i].count = cpu_to_le32(usg->sg[i].count); + } + kfree (usg); } - kfree (usg); - srbcmd->count = cpu_to_le32(byte_count); psg->count = cpu_to_le32(sg_indx+1); status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); } else { struct user_sgmap* upsg = &user_srbcmd->sg; struct sgmap* psg = &srbcmd->sg; - byte_count = 0; - - actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); - if(actual_fibsize != fibsize){ // User made a mistake - should not continue - dprintk((KERN_DEBUG"aacraid: Bad Size specified in " - "Raw SRB command calculated fibsize=%d " - "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d " - "issued fibsize=%d\n", - actual_fibsize, user_srbcmd->sg.count, - sizeof(struct aac_srb), sizeof(struct sgentry), - fibsize)); - rcode = -EINVAL; - goto cleanup; - } - if ((data_dir == DMA_NONE) && upsg->count) { - dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n")); - rcode = -EINVAL; - goto cleanup; - } - for (i = 0; i < upsg->count; i++) { - dma_addr_t addr; - void* p; - p = kmalloc(upsg->sg[i].count, GFP_KERNEL); - if(p == 0) { - dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", - upsg->sg[i].count, i, upsg->count)); - rcode = -ENOMEM; - goto cleanup; - } - sg_user[i] = (void __user *)(long)upsg->sg[i].addr; - sg_list[i] = p; // save so we can clean up later - sg_indx = i; - - if( flags & SRB_DataOut ){ - if(copy_from_user(p, sg_user[i], - upsg->sg[i].count)) { - dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); - rcode = -EFAULT; + + if (actual_fibsize64 == fibsize) { + struct user_sgmap64* usg = (struct user_sgmap64 *)upsg; + for (i = 0; i < upsg->count; i++) { + u64 addr; + void* p; + /* Does this really need to be GFP_DMA? */ + p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); + if(p == 0) { + dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + usg->sg[i].count,i,usg->count)); + rcode = -ENOMEM; goto cleanup; } + addr = (u64)usg->sg[i].addr[0]; + addr += ((u64)usg->sg[i].addr[1]) << 32; + sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_list[i] = p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p,sg_user[i],usg->sg[i].count)){ + dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir); + + psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff); + byte_count += usg->sg[i].count; + psg->sg[i].count = cpu_to_le32(usg->sg[i].count); } - addr = pci_map_single(dev->pdev, p, - upsg->sg[i].count, data_dir); + } else { + for (i = 0; i < upsg->count; i++) { + dma_addr_t addr; + void* p; + p = kmalloc(upsg->sg[i].count, GFP_KERNEL); + if(p == 0) { + dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + upsg->sg[i].count, i, upsg->count)); + rcode = -ENOMEM; + goto cleanup; + } + sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr; + sg_list[i] = p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p, sg_user[i], + upsg->sg[i].count)) { + dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, + upsg->sg[i].count, data_dir); - psg->sg[i].addr = cpu_to_le32(addr); - psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); - byte_count += upsg->sg[i].count; + psg->sg[i].addr = cpu_to_le32(addr); + byte_count += upsg->sg[i].count; + psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); + } } srbcmd->count = cpu_to_le32(byte_count); psg->count = cpu_to_le32(sg_indx+1); @@ -689,7 +743,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) if( flags & SRB_DataIn ) { for(i = 0 ; i <= sg_indx; i++){ - byte_count = le32_to_cpu((dev->dac_support == 1) + byte_count = le32_to_cpu( + (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count : srbcmd->sg.sg[i].count); if(copy_to_user(sg_user[i], sg_list[i], byte_count)){ -- cgit v1.2.3 From 03d4433721880bf1972c924b168e4e1dd3c59d53 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:27:45 -0700 Subject: [SCSI] aacraid: Improved error handling Received from Mark Salyzyn, This set of fixes improve error handling stability of the driver. A popular manifestation of the problems is an NULL pointer reference in the interrupt handler when referencing portions of the scsi command context, or in the scsi_done handling when an offlined device is referenced. The aacraid driver currently does not get notification of orphaned command completions due to devices going offline. The driver also fails to handle the commands that are finished by the error handler, and thus can complete again later at the hands of the adapter causing situations of completion of an invalid scsi command context. Test Unit Ready calls abort assuming that the abort was successful, but are not, and thus when the interrupt from the adapter occurs, they reference invalid command contexts. We add in a TIMED_OUT flag to inform the aacraid FIB context that the interrupt service should merely release the driver resources and not complete the command up. We take advantage of this with the abort handler as well for select abortable commands. And we detect and react if a command that can not be aborted is currently still outstanding to the controller when reissued by the retry mechanism. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 51 +++++++++++++++++++++++++++++++-- drivers/scsi/aacraid/aacraid.h | 1 - drivers/scsi/aacraid/commsup.c | 23 ++++++--------- drivers/scsi/aacraid/dpcsup.c | 24 ++++++++-------- drivers/scsi/aacraid/linit.c | 64 +++++++++++++++++++++++++++++++++++++++--- 5 files changed, 130 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 3d21d7dd2e5..0c4e27eb652 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. int expose_physicals = -1; module_param(expose_physicals, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); + + +static inline int aac_valid_context(struct scsi_cmnd *scsicmd, + struct fib *fibptr) { + struct scsi_device *device; + + if (unlikely(!scsicmd || !scsicmd->scsi_done )) { + dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")) +; + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + return 0; + } + scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + device = scsicmd->device; + if (unlikely(!device || !scsi_device_online(device))) { + dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n")); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + return 0; + } + return 1; +} + /** * aac_get_config_status - check the adapter configuration * @common: adapter to query @@ -342,6 +366,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return; + dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); @@ -431,9 +458,14 @@ static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) static int _aac_probe_container2(void * context, struct fib * fibptr) { - struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; - struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + struct fsa_dev_info *fsa_dev_ptr; int (*callback)(struct scsi_cmnd *); + struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; + + if (!aac_valid_context(scsicmd, fibptr)) + return 0; + + fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; scsicmd->SCp.Status = 0; if (fsa_dev_ptr) { @@ -477,6 +509,9 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return 0; + aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); @@ -1287,6 +1322,9 @@ static void io_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return; + dev = (struct aac_dev *)scsicmd->device->host->hostdata; cid = scmd_id(scsicmd); @@ -1534,6 +1572,9 @@ static void synchronize_callback(void *context, struct fib *fibptr) cmd = context; cmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(cmd, fibptr)) + return; + dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); @@ -2086,6 +2127,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + + if (!aac_valid_context(scsicmd, fibptr)) + return; + dev = (struct aac_dev *)scsicmd->device->host->hostdata; BUG_ON(fibptr == NULL); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 9ca594b33d1..2c0994b448d 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -971,7 +971,6 @@ struct aac_dev struct fib *fibs; struct fib *free_fib; - struct fib *timeout_fib; spinlock_t fib_lock; struct aac_queue_block *queues; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index c933df30f58..a23d7e5de5b 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) * @fibptr: fib to free up * * Frees up a fib and places it on the appropriate queue - * (either free or timed out) */ void aac_fib_free(struct fib *fibptr) @@ -186,19 +185,15 @@ void aac_fib_free(struct fib *fibptr) unsigned long flags; spin_lock_irqsave(&fibptr->dev->fib_lock, flags); - if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { + if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) aac_config.fib_timeouts++; - fibptr->next = fibptr->dev->timeout_fib; - fibptr->dev->timeout_fib = fibptr; - } else { - if (fibptr->hw_fib_va->header.XferState != 0) { - printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - (void*)fibptr, - le32_to_cpu(fibptr->hw_fib_va->header.XferState)); - } - fibptr->next = fibptr->dev->free_fib; - fibptr->dev->free_fib = fibptr; - } + if (fibptr->hw_fib_va->header.XferState != 0) { + printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", + (void*)fibptr, + le32_to_cpu(fibptr->hw_fib_va->header.XferState)); + } + fibptr->next = fibptr->dev->free_fib; + fibptr->dev->free_fib = fibptr; spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); } diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index 26f4d563d95..4e53f9db1b2 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -84,11 +84,13 @@ unsigned int aac_response_normal(struct aac_queue * q) * continue. The caller has already been notified that * the fib timed out. */ - if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) - dev->queues->queue[AdapNormCmdQueue].numpending--; - else { - printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); - printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); + dev->queues->queue[AdapNormCmdQueue].numpending--; + + if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + spin_unlock_irqrestore(q->lock, flags); + aac_fib_complete(fib); + aac_fib_free(fib); + spin_lock_irqsave(q->lock, flags); continue; } spin_unlock_irqrestore(q->lock, flags); @@ -281,14 +283,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) * continue. The caller has already been notified that * the fib timed out. */ - if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); - printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); + dev->queues->queue[AdapNormCmdQueue].numpending--; + + if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + aac_fib_complete(fib); + aac_fib_free(fib); return 0; } - dev->queues->queue[AdapNormCmdQueue].numpending--; - if (fast) { /* * Doctor the fib diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0f948c2fb60..3cf3f6472e9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -247,6 +247,19 @@ static struct aac_driver_ident aac_drivers[] = { static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { + struct Scsi_Host *host = cmd->device->host; + struct aac_dev *dev = (struct aac_dev *)host->hostdata; + u32 count = 0; + cmd->scsi_done = done; + for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &dev->fibs[count]; + struct scsi_cmnd * command; + if (fib->hw_fib_va->header.XferState && + ((command = fib->callback_data)) && + (command == cmd) && + (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) + return 0; /* Already owned by Adapter */ + } cmd->scsi_done = done; cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); @@ -446,6 +459,40 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) return aac_do_ioctl(dev, cmd, arg); } +static int aac_eh_abort(struct scsi_cmnd* cmd) +{ + struct Scsi_Host * host = cmd->device->host; + struct aac_dev * aac = (struct aac_dev *)host->hostdata; + int count; + int ret = FAILED; + + printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", + AAC_DRIVERNAME, + cmd->device->host->host_no, sdev_channel(cmd->device), + sdev_id(cmd->device), cmd->device->lun); + switch (cmd->cmnd[0]) { + case SERVICE_ACTION_IN: + if (!(aac->raw_io_interface) || + !(aac->raw_io_64) || + ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) + break; + case INQUIRY: + case READ_CAPACITY: + case TEST_UNIT_READY: + /* Mark associated FIB to not complete, eh handler does this */ + for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &aac->fibs[count]; + if (fib->hw_fib_va->header.XferState && + (fib->callback_data == cmd)) { + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; + cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; + ret = SUCCESS; + } + } + } + return ret; +} + /* * aac_eh_reset - Reset command handling * @scsi_cmd: SCSI command block causing the reset @@ -457,12 +504,20 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) struct Scsi_Host * host = dev->host; struct scsi_cmnd * command; int count; - struct aac_dev * aac; + struct aac_dev * aac = (struct aac_dev *)host->hostdata; unsigned long flags; + /* Mark the associated FIB to not complete, eh handler does this */ + for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &aac->fibs[count]; + if (fib->hw_fib_va->header.XferState && + (fib->callback_data == cmd)) { + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; + cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; + } + } printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); - aac = (struct aac_dev *)host->hostdata; if ((count = aac_check_health(aac))) return count; @@ -496,7 +551,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) ssleep(1); } printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); - return -ETIMEDOUT; + return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ } /** @@ -796,6 +851,7 @@ static struct scsi_host_template aac_driver_template = { .bios_param = aac_biosparm, .shost_attrs = aac_attrs, .slave_configure = aac_slave_configure, + .eh_abort_handler = aac_eh_abort, .eh_host_reset_handler = aac_eh_reset, .can_queue = AAC_NUM_IO_FIB, .this_id = MAXIMUM_NUM_CONTAINERS, -- cgit v1.2.3 From 6c5f8ce1fb7e8925d957f754a9513911399791b9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 16 Mar 2007 17:44:41 -0500 Subject: [SCSI] expose eh_timed_out to the host template It looks like megaraid_sas at least needs this to throttle its commands as they begin to time out. The code keeps the existing transport template use of eh_timed_out (and allows the transport to override the host if they both have this callback). Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 11 ++++++++++- include/scsi/scsi_host.h | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index b8edcf5b545..7a1a1bb1341 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -184,10 +184,19 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) **/ void scsi_times_out(struct scsi_cmnd *scmd) { + enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + scsi_log_completion(scmd, TIMEOUT_ERROR); if (scmd->device->host->transportt->eh_timed_out) - switch (scmd->device->host->transportt->eh_timed_out(scmd)) { + eh_timed_out = scmd->device->host->transportt->eh_timed_out; + else if (scmd->device->host->hostt->eh_timed_out) + eh_timed_out = scmd->device->host->hostt->eh_timed_out; + else + eh_timed_out = NULL; + + if (eh_timed_out) + switch (eh_timed_out(scmd)) { case EH_HANDLED: __scsi_done(scmd); return; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 965b6b8ffec..68f461b7a83 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -325,6 +325,19 @@ struct scsi_host_template { */ int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); + /* + * This is an optional routine that allows the transport to become + * involved when a scsi io timer fires. The return value tells the + * timer routine how to finish the io timeout handling: + * EH_HANDLED: I fixed the error, please complete the command + * EH_RESET_TIMER: I need more time, reset the timer and + * begin counting again + * EH_NOT_HANDLED Begin normal error recovery + * + * Status: OPTIONAL + */ + enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + /* * suspend support */ -- cgit v1.2.3 From 5f9279f23913045c810eeb4ab03c694c46231f75 Mon Sep 17 00:00:00 2001 From: Richard Knutsson Date: Sun, 18 Mar 2007 00:58:23 +0100 Subject: [SCSI] eata_pio: Remove FALSE/TRUE defines eata_generic.h is only included by eata_pio.c and it only uses FALSE/TRUE in comments. Signed-off-by: Richard Knutsson Signed-off-by: James Bottomley --- drivers/scsi/eata_generic.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h index 635c14861f8..5016af5cf86 100644 --- a/drivers/scsi/eata_generic.h +++ b/drivers/scsi/eata_generic.h @@ -18,13 +18,6 @@ * Misc. definitions * *********************************************/ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - #define R_LIMIT 0x20000 #define MAXISA 4 -- cgit v1.2.3 From a1f9ce056a1875b6c8633f370df4fb169b925b16 Mon Sep 17 00:00:00 2001 From: Horms Date: Fri, 16 Mar 2007 16:05:22 +0900 Subject: [SCSI] fusion: remove unnecessary code in mptscsih_resume() It seems that most of the code in mptscsih_resume() doesn't do anything. This patch removes that code. Signed-off-by: Simon Horman Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/mptscsih.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index eef00ed139b..10927e34c2b 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1188,19 +1188,7 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) int mptscsih_resume(struct pci_dev *pdev) { - MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - struct Scsi_Host *host = ioc->sh; - MPT_SCSI_HOST *hd; - mpt_resume(pdev); - - if(!host) - return 0; - - hd = (MPT_SCSI_HOST *)host->hostdata; - if(!hd) - return 0; - return 0; } -- cgit v1.2.3 From b364fd5081b02fa8a966a29eea2da628913fd4b8 Mon Sep 17 00:00:00 2001 From: Horms Date: Mon, 19 Mar 2007 15:06:44 +0900 Subject: [SCSI] fusion: honour return value of pci_enable_device() in mpt_resume() Honour the return value of pci_enable_device(), which seems to be a desirable thing to do: 2.6.20-rc4 gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) CC [M] drivers/message/fusion/mptbase.o drivers/message/fusion/mptbase.c: In function `mpt_resume': drivers/message/fusion/mptbase.c:1541: warning: ignoring return value of `pci_enable_device', declared with attribute warn_unused_result It also in turn has mptscsih_resume() honour the return value of mpt_resume() I'm not sure about the handling of the other potential error cases in mpt_resume(), of which there appear to be many. But this does seem to be a good start. Signed-off-by: Simon Horman Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 5 ++++- drivers/message/fusion/mptscsih.c | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 0a2d7db7b63..97471af4309 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1531,6 +1531,7 @@ mpt_resume(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); u32 device_state = pdev->current_state; int recovery_state; + int err; printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", @@ -1538,7 +1539,9 @@ mpt_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) + return err; /* enable interrupts */ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 10927e34c2b..537fcc221c9 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1188,8 +1188,7 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) int mptscsih_resume(struct pci_dev *pdev) { - mpt_resume(pdev); - return 0; + return mpt_resume(pdev); } #endif -- cgit v1.2.3 From ad8c31bb69d60c0c6bc6431bccdf67e5a96c0d31 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 19 Mar 2007 10:31:51 -0600 Subject: [SCSI] fusion: remove VMWare guest OS remounted as read only work around This address the issue of VMWare guest OS being remounted as read-only becuase the underlying device was held busy too long and at the same time address Engenio MPP driver concerns over infinite retries. This patch removes the code that snoops the SAM STATUS on busy, which would be returning DID_BUS_BUSY, instead we return the status as is. Retry hanlding seems to be properly handled in scsi_softirq_done, where a busy sam status would only occurr for the time specified by (cmd->allowed +1) * cmd->timeout_per_command. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptscsih.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 537fcc221c9..fa0f7761652 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -819,10 +819,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->resid=0; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - if (scsi_status == MPI_SCSI_STATUS_BUSY) - sc->result = (DID_BUS_BUSY << 16) | scsi_status; - else - sc->result = (DID_OK << 16) | scsi_status; + sc->result = (DID_OK << 16) | scsi_status; if (scsi_state == 0) { ; } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { -- cgit v1.2.3 From 3721050afc6cb6ddf6de0f782e2054ebcc225e9b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Mar 2007 00:07:18 +0900 Subject: [SCSI] sd: fix return value of sd_sync_cache() sd_sync_cache() should return -errno on error, fix it. Signed-off-by: Tejun Heo Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12e18bb5456..3dda77c31f5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -766,7 +766,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) sd_print_sense_hdr(sdkp, &sshdr); } - return res; + if (res) + return -EIO; + return 0; } static int sd_issue_flush(struct device *dev, sector_t *error_sector) -- cgit v1.2.3 From c3c94c5a2fb43a654e777f509d5032b0db8ed09f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Mar 2007 00:13:59 +0900 Subject: [SCSI] sd: implement START/STOP management Implement SBC START/STOP management. sdev->mange_start_stop is added. When it's set to one, sd STOPs the device on suspend and shutdown and STARTs it on resume. sdev->manage_start_stop defaults is in sdev instead of scsi_disk cdev to allow ->slave_config() override the default configuration but is exported under scsi_disk sysfs node as sdev->allow_restart is. When manage_start_stop is zero (the default value), this patch doesn't introduce any behavior change. Signed-off-by: Tejun Heo Rejections fixed and Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 31 ++++++++++++-- drivers/scsi/sd.c | 101 +++++++++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_device.h | 1 + include/scsi/sd.h | 2 + 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c275dcac3f1..96db51c40ef 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -278,6 +278,7 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) static int scsi_bus_suspend(struct device * dev, pm_message_t state) { + struct device_driver *drv = dev->driver; struct scsi_device *sdev = to_scsi_device(dev); struct scsi_host_template *sht = sdev->host->hostt; int err; @@ -286,23 +287,45 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) if (err) return err; - if (sht->suspend) + /* call HLD suspend first */ + if (drv && drv->suspend) { + err = drv->suspend(dev, state); + if (err) + return err; + } + + /* then, call host suspend */ + if (sht->suspend) { err = sht->suspend(sdev, state); + if (err) { + if (drv && drv->resume) + drv->resume(dev); + return err; + } + } - return err; + return 0; } static int scsi_bus_resume(struct device * dev) { + struct device_driver *drv = dev->driver; struct scsi_device *sdev = to_scsi_device(dev); struct scsi_host_template *sht = sdev->host->hostt; - int err = 0; + int err = 0, err2 = 0; + /* call host resume first */ if (sht->resume) err = sht->resume(sdev); + /* then, call HLD resume */ + if (drv && drv->resume) + err2 = drv->resume(dev); + scsi_device_resume(sdev); - return err; + + /* favor LLD failure */ + return err ? err : err2;; } struct bus_type scsi_bus_type = { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3dda77c31f5..49a94ae3225 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -147,6 +147,20 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, return count; } +static ssize_t sd_store_manage_start_stop(struct class_device *cdev, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + struct scsi_device *sdp = sdkp->device; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + sdp->manage_start_stop = simple_strtoul(buf, NULL, 10); + + return count; +} + static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf, size_t count) { @@ -179,6 +193,14 @@ static ssize_t sd_show_fua(struct class_device *cdev, char *buf) return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); } +static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + struct scsi_device *sdp = sdkp->device; + + return snprintf(buf, 20, "%u\n", sdp->manage_start_stop); +} + static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf) { struct scsi_disk *sdkp = to_scsi_disk(cdev); @@ -192,6 +214,8 @@ static struct class_device_attribute sd_disk_attrs[] = { __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart, sd_store_allow_restart), + __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop, + sd_store_manage_start_stop), __ATTR_NULL, }; @@ -208,6 +232,8 @@ static struct scsi_driver sd_template = { .name = "sd", .probe = sd_probe, .remove = sd_remove, + .suspend = sd_suspend, + .resume = sd_resume, .shutdown = sd_shutdown, }, .rescan = sd_rescan, @@ -1707,6 +1733,32 @@ static void scsi_disk_release(struct class_device *cdev) kfree(sdkp); } +static int sd_start_stop_device(struct scsi_device *sdp, int start) +{ + unsigned char cmd[6] = { START_STOP }; /* START_VALID */ + struct scsi_sense_hdr sshdr; + int res; + + if (start) + cmd[4] |= 1; /* START */ + + if (!scsi_device_online(sdp)) + return -ENODEV; + + res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); + if (res) { + printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + "host = %d, driver = %02x\n ", + status_byte(res), msg_byte(res), + host_byte(res), driver_byte(res)); + if (driver_byte(res) & DRIVER_SENSE) + scsi_print_sense_hdr("sd", &sshdr); + } + + return res; +} + /* * Send a SYNCHRONIZE CACHE instruction down to the device through * the normal SCSI command structure. Wait for the command to @@ -1714,6 +1766,7 @@ static void scsi_disk_release(struct class_device *cdev) */ static void sd_shutdown(struct device *dev) { + struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (!sdkp) @@ -1723,9 +1776,57 @@ static void sd_shutdown(struct device *dev) sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); sd_sync_cache(sdkp); } + + if (system_state != SYSTEM_RESTART && sdp->manage_start_stop) { + printk(KERN_NOTICE "Stopping disk %s: \n", + sdkp->disk->disk_name); + sd_start_stop_device(sdp, 0); + } + scsi_disk_put(sdkp); } +static int sd_suspend(struct device *dev, pm_message_t mesg) +{ + struct scsi_device *sdp = to_scsi_device(dev); + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + int ret; + + if (!sdkp) + return 0; /* this can happen */ + + if (sdkp->WCE) { + printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n", + sdkp->disk->disk_name); + ret = sd_sync_cache(sdkp); + if (ret) + return ret; + } + + if (mesg.event == PM_EVENT_SUSPEND && sdp->manage_start_stop) { + printk(KERN_NOTICE "Stopping disk %s: \n", + sdkp->disk->disk_name); + ret = sd_start_stop_device(sdp, 0); + if (ret) + return ret; + } + + return 0; +} + +static int sd_resume(struct device *dev) +{ + struct scsi_device *sdp = to_scsi_device(dev); + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + + if (!sdp->manage_start_stop) + return 0; + + printk(KERN_NOTICE "Starting disk %s: \n", sdkp->disk->disk_name); + + return sd_start_stop_device(sdp, 1); +} + /** * init_sd - entry point for this driver (both when built in or when * a module). diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index c86e6ce143d..b05cd3b09e6 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -120,6 +120,7 @@ struct scsi_device { unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ unsigned no_start_on_add:1; /* do not issue start on add */ unsigned allow_restart:1; /* issue START_UNIT in error handler */ + unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ unsigned select_no_atn:1; unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ diff --git a/include/scsi/sd.h b/include/scsi/sd.h index 82e6a84b77e..5261488e110 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h @@ -52,6 +52,8 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt); static int sd_probe(struct device *); static int sd_remove(struct device *); static void sd_shutdown(struct device *dev); +static int sd_suspend(struct device *dev, pm_message_t state); +static int sd_resume(struct device *dev); static void sd_rescan(struct device *); static int sd_init_command(struct scsi_cmnd *); static int sd_issue_flush(struct device *, sector_t *); -- cgit v1.2.3 From cc5d2c8c64804564617a7be71c73a075a426d1c6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 20 Mar 2007 12:26:03 -0500 Subject: [SCSI] sd: fix up start/stop messages for new sd_printk() API Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 49a94ae3225..b044dcf7342 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1733,10 +1733,11 @@ static void scsi_disk_release(struct class_device *cdev) kfree(sdkp); } -static int sd_start_stop_device(struct scsi_device *sdp, int start) +static int sd_start_stop_device(struct scsi_disk *sdkp, int start) { unsigned char cmd[6] = { START_STOP }; /* START_VALID */ struct scsi_sense_hdr sshdr; + struct scsi_device *sdp = sdkp->device; int res; if (start) @@ -1748,12 +1749,10 @@ static int sd_start_stop_device(struct scsi_device *sdp, int start) res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); if (res) { - printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " - "host = %d, driver = %02x\n ", - status_byte(res), msg_byte(res), - host_byte(res), driver_byte(res)); + sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n"); + sd_print_result(sdkp, res); if (driver_byte(res) & DRIVER_SENSE) - scsi_print_sense_hdr("sd", &sshdr); + sd_print_sense_hdr(sdkp, &sshdr); } return res; @@ -1766,7 +1765,6 @@ static int sd_start_stop_device(struct scsi_device *sdp, int start) */ static void sd_shutdown(struct device *dev) { - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (!sdkp) @@ -1777,10 +1775,9 @@ static void sd_shutdown(struct device *dev) sd_sync_cache(sdkp); } - if (system_state != SYSTEM_RESTART && sdp->manage_start_stop) { - printk(KERN_NOTICE "Stopping disk %s: \n", - sdkp->disk->disk_name); - sd_start_stop_device(sdp, 0); + if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) { + sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); + sd_start_stop_device(sdkp, 0); } scsi_disk_put(sdkp); @@ -1788,7 +1785,6 @@ static void sd_shutdown(struct device *dev) static int sd_suspend(struct device *dev, pm_message_t mesg) { - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); int ret; @@ -1796,17 +1792,16 @@ static int sd_suspend(struct device *dev, pm_message_t mesg) return 0; /* this can happen */ if (sdkp->WCE) { - printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n", - sdkp->disk->disk_name); + sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); ret = sd_sync_cache(sdkp); if (ret) return ret; } - if (mesg.event == PM_EVENT_SUSPEND && sdp->manage_start_stop) { - printk(KERN_NOTICE "Stopping disk %s: \n", - sdkp->disk->disk_name); - ret = sd_start_stop_device(sdp, 0); + if (mesg.event == PM_EVENT_SUSPEND && + sdkp->device->manage_start_stop) { + sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); + ret = sd_start_stop_device(sdkp, 0); if (ret) return ret; } @@ -1816,15 +1811,14 @@ static int sd_suspend(struct device *dev, pm_message_t mesg) static int sd_resume(struct device *dev) { - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); - if (!sdp->manage_start_stop) + if (!sdkp->device->manage_start_stop) return 0; - printk(KERN_NOTICE "Starting disk %s: \n", sdkp->disk->disk_name); + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - return sd_start_stop_device(sdp, 1); + return sd_start_stop_device(sdkp, 1); } /** -- cgit v1.2.3 From 0272bf7271eb6895b081c3df34c3ebe50cb769b7 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 20 Mar 2007 14:44:04 -0500 Subject: [SCSI] fix scsi_wait_scan build problem The #ifdef MODULE around the export of scsi_complete_async_scans() which is the API the scsi_wait_scan module uses is incorrect and causes the symbol to be undefined in certain circumstances leading to a build failure. Remove the defines. Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 0949145304e..a67f315244d 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -181,10 +181,8 @@ int scsi_complete_async_scans(void) return 0; } -#ifdef MODULE /* Only exported for the benefit of scsi_wait_scan */ EXPORT_SYMBOL_GPL(scsi_complete_async_scans); -#endif /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command -- cgit v1.2.3 From 20235f35221472f1a127a5d5414f11091eb0a845 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 21 Mar 2007 13:22:56 -0400 Subject: [SCSI] aacraid: check buffer address in aac_internal_transfer Captured a panic on an older kernel where an application issuing commands via sg was sending requests that lacked a request_buffer, thus the buffer pointer used in aac_internal_transer was NULL. The application was fixed closing the issue, but felt it was advised to immunize the driver against the eventuality. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0c4e27eb652..f9deab686dc 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -350,8 +350,9 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne buf = scsicmd->request_buffer; transfer_len = min(scsicmd->request_bufflen, len + offset); } - - memcpy(buf + offset, data, transfer_len - offset); + transfer_len -= offset; + if (buf && transfer_len) + memcpy(buf + offset, data, transfer_len); if (scsicmd->use_sg) kunmap_atomic(buf - sg->offset, KM_IRQ0); -- cgit v1.2.3 From 802ae2f05b646c1e5f9e33cfe4c80cfa1452a0e3 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 21 Mar 2007 13:49:47 -0400 Subject: [SCSI] aacraid: cleanup and version stamp driver There is some residual cleanup of the last series of patches and the need to bump the revision number to draw the line in the sand. The cmd->SCp.phase is set in the aac_valid_context routine, then set again to the same value following it's return. The cmd->scsi_done is set twice in the aac_queuecommand routine. Free up the scsidev FILO in aac_probe_container as it is not needed further down the function in any case. Improve the efficiency of the abort handler kernel print parameters. Bump revision number of driver to approximate the equivalent in the Adaptec supplied version. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 +----- drivers/scsi/aacraid/aacraid.h | 4 ++-- drivers/scsi/aacraid/linit.c | 7 +++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index f9deab686dc..fc16fe0dfa8 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -365,7 +365,6 @@ static void get_container_name_callback(void *context, struct fib * fibptr) struct scsi_cmnd * scsicmd; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; @@ -629,9 +628,9 @@ int aac_probe_container(struct aac_dev *dev, int cid) if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) while (scsicmd->device == scsidev) schedule(); + kfree(scsidev); status = scsicmd->SCp.Status; kfree(scsicmd); - kfree(scsidev); return status; } @@ -1321,7 +1320,6 @@ static void io_callback(void *context, struct fib * fibptr) u32 cid; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; @@ -1571,7 +1569,6 @@ static void synchronize_callback(void *context, struct fib *fibptr) struct scsi_cmnd *cmd; cmd = context; - cmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(cmd, fibptr)) return; @@ -2127,7 +2124,6 @@ static void aac_srb_callback(void *context, struct fib * fibptr) struct scsi_cmnd *scsicmd; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 2c0994b448d..1771851db6e 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,8 +12,8 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2423 -# define AAC_DRIVER_BRANCH "-mh3" +# define AAC_DRIVER_BUILD 2437 +# define AAC_DRIVER_BRANCH "-mh4" #endif #define MAXIMUM_NUM_CONTAINERS 32 diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 3cf3f6472e9..a5950c17d62 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -260,7 +260,6 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) return 0; /* Already owned by Adapter */ } - cmd->scsi_done = done; cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); } @@ -461,15 +460,15 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) static int aac_eh_abort(struct scsi_cmnd* cmd) { - struct Scsi_Host * host = cmd->device->host; + struct scsi_device * dev = cmd->device; + struct Scsi_Host * host = dev->host; struct aac_dev * aac = (struct aac_dev *)host->hostdata; int count; int ret = FAILED; printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", AAC_DRIVERNAME, - cmd->device->host->host_no, sdev_channel(cmd->device), - sdev_id(cmd->device), cmd->device->lun); + host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); switch (cmd->cmnd[0]) { case SERVICE_ACTION_IN: if (!(aac->raw_io_interface) || -- cgit v1.2.3 From 07da60c1f45a6a5f563429e88e8c94c82f9132eb Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 21 Mar 2007 08:41:47 -0500 Subject: [SCSI] lpfc: fix oops when parsing dodgy VPD We have seen two cases where VPD on an emulex card has been incorrect and we end up walking off the end of memory. It looks like someone made an update (increased the length of a string) without increasing the Length field. Then we do: Length -= (3+i); And since Length is unsigned it becomes very large and we loop forever in the encapsulating: while (Length > 0) { If we make Length signed then we fall out of the loop and proceed on. Its important to note we have only seen this in the lab and it may be the only two cases of this in existence, but since the rest of the code has been written to be resilient against bad VPD we may as well fix this too. Signed-off-by: Anton Blanchard Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9d014e5a81c..09a9c8ab2ea 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -671,7 +671,7 @@ static int lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len) { uint8_t lenlo, lenhi; - uint32_t Length; + int Length; int i, j; int finished = 0; int index = 0; -- cgit v1.2.3 From 1196ae025ba4a36eb9e6baab57ba903d36139ff2 Mon Sep 17 00:00:00 2001 From: Richard Lary Date: Thu, 22 Mar 2007 10:53:19 -0500 Subject: [SCSI] qla2xxx: fix for byteswap in fc_host fabric_name This patch fixes byte swap issue in qla2xxx driver to fix corrupted fabric_name passed to /sys/class/fc_host/host*/fabric_name. Signed-off-by: Richard Lary Acked-by: Seokmann Ju Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 83376f6ac3d..71e32a24852 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1280,14 +1280,14 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name, } else { if (name != NULL) { /* This function returns name in big endian. */ - name[0] = LSB(mcp->mb[2]); - name[1] = MSB(mcp->mb[2]); - name[2] = LSB(mcp->mb[3]); - name[3] = MSB(mcp->mb[3]); - name[4] = LSB(mcp->mb[6]); - name[5] = MSB(mcp->mb[6]); - name[6] = LSB(mcp->mb[7]); - name[7] = MSB(mcp->mb[7]); + name[0] = MSB(mcp->mb[2]); + name[1] = LSB(mcp->mb[2]); + name[2] = MSB(mcp->mb[3]); + name[3] = LSB(mcp->mb[3]); + name[4] = MSB(mcp->mb[6]); + name[5] = LSB(mcp->mb[6]); + name[6] = MSB(mcp->mb[7]); + name[7] = LSB(mcp->mb[7]); } DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n", -- cgit v1.2.3 From 912d4e8851389eee5c289ce0a7953e9067198232 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Mon, 26 Mar 2007 09:21:14 -0400 Subject: [SCSI] aacraid: Add likely() and unlikely() Add some likely() and unlikely() compiler hints in some of the aacraid hardware interface layers. There should be no operational side effects resulting from this patch and the changes should be mostly benign on x86 platforms. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commsup.c | 6 ++--- drivers/scsi/aacraid/rx.c | 50 +++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index a23d7e5de5b..5824a757a75 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -519,11 +519,9 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, spin_unlock_irqrestore(&fibptr->event_lock, flags); BUG_ON(fibptr->done == 0); - if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ + if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) return -ETIMEDOUT; - } else { - return 0; - } + return 0; } /* * If the user does not want a response than return success otherwise diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 6f8a19462e4..391d4751338 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,25 +57,25 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) * been enabled. * Check to see if this is our interrupt. If it isn't just return */ - if (intstat & ~(dev->OIMR)) { + if (likely(intstat & ~(dev->OIMR))) { bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { + if (unlikely(bellbits & DoorBellPrintfReady)) { aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - else if (bellbits & DoorBellAdapterNormCmdReady) { + else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); } - else if (bellbits & DoorBellAdapterNormRespReady) { + else if (likely(bellbits & DoorBellAdapterNormRespReady)) { rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); aac_response_normal(&dev->queues->queue[HostNormRespQueue]); } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { + else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); } - else if (bellbits & DoorBellAdapterNormRespNotFull) { + else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); } @@ -88,11 +88,11 @@ static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) { struct aac_dev *dev = dev_id; u32 Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index == 0xFFFFFFFFL) + if (unlikely(Index == 0xFFFFFFFFL)) Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index != 0xFFFFFFFFL) { + if (likely(Index != 0xFFFFFFFFL)) { do { - if (aac_intr_normal(dev, Index)) { + if (unlikely(aac_intr_normal(dev, Index))) { rx_writel(dev, MUnit.OutboundQueue, Index); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); } @@ -204,7 +204,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, */ msleep(1); } - if (ok != 1) { + if (unlikely(ok != 1)) { /* * Restore interrupt mask even though we timed out */ @@ -319,12 +319,12 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Check to see if the board failed any self tests. */ - if (status & SELF_TEST_FAILED) + if (unlikely(status & SELF_TEST_FAILED)) return -1; /* * Check to see if the board panic'd. */ - if (status & KERNEL_PANIC) { + if (unlikely(status & KERNEL_PANIC)) { char * buffer; struct POSTSTATUS { __le32 Post_Command; @@ -333,15 +333,15 @@ static int aac_rx_check_health(struct aac_dev *dev) dma_addr_t paddr, baddr; int ret; - if ((status & 0xFF000000L) == 0xBC000000L) + if (likely((status & 0xFF000000L) == 0xBC000000L)) return (status >> 16) & 0xFF; buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); ret = -2; - if (buffer == NULL) + if (unlikely(buffer == NULL)) return ret; post = pci_alloc_consistent(dev->pdev, sizeof(struct POSTSTATUS), &paddr); - if (post == NULL) { + if (unlikely(post == NULL)) { pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; } @@ -353,7 +353,7 @@ static int aac_rx_check_health(struct aac_dev *dev) NULL, NULL, NULL, NULL, NULL); pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); - if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) { + if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); ret <<= 4; ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); @@ -364,7 +364,7 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Wait for the adapter to be up and running. */ - if (!(status & KERNEL_UP_AND_RUNNING)) + if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) return -3; /* * Everything is OK @@ -419,9 +419,9 @@ static int aac_rx_deliver_message(struct fib * fib) spin_unlock_irqrestore(q->lock, qflags); for(;;) { Index = rx_readl(dev, MUnit.InboundQueue); - if (Index == 0xFFFFFFFFL) + if (unlikely(Index == 0xFFFFFFFFL)) Index = rx_readl(dev, MUnit.InboundQueue); - if (Index != 0xFFFFFFFFL) + if (likely(Index != 0xFFFFFFFFL)) break; if (--count == 0) { spin_lock_irqsave(q->lock, qflags); @@ -526,11 +526,8 @@ int _aac_rx_init(struct aac_dev *dev) { unsigned long start; unsigned long status; - int instance; - const char * name; - - instance = dev->id; - name = dev->name; + int instance = dev->id; + const char * name = dev->name; if (aac_adapter_ioremap(dev, dev->base_size)) { printk(KERN_WARNING "%s: unable to map adapter.\n", name); @@ -568,8 +565,7 @@ int _aac_rx_init(struct aac_dev *dev) */ while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+startup_timeout*HZ)) - { + if(time_after(jiffies, start+startup_timeout*HZ)) { printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; -- cgit v1.2.3 From 023ae6199938fc79a51d2616903b44b07fe338b6 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 26 Mar 2007 16:06:45 -0400 Subject: [SCSI] pcmcia: allow drivers to be built non-modular Remove the Kconfig requirement that the PCMCIA SCSI drivers be built only as modules, and allow them to be built into the kernel. Signed-off-by: Robert P. J. Day Acked-by: Dominik Brodowski Signed-off-by: James Bottomley --- drivers/scsi/pcmcia/Kconfig | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index eac8e179cff..7dd787f6ab2 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -3,11 +3,11 @@ # menu "PCMCIA SCSI adapter support" - depends on SCSI!=n && PCMCIA!=n && MODULES + depends on SCSI!=n && PCMCIA!=n config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" - depends on m && !64BIT + depends on !64BIT select SCSI_SPI_ATTRS help Say Y here if you intend to attach this type of PCMCIA SCSI host @@ -18,7 +18,6 @@ config PCMCIA_AHA152X config PCMCIA_FDOMAIN tristate "Future Domain PCMCIA support" - depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -28,7 +27,7 @@ config PCMCIA_FDOMAIN config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" - depends on m && !64BIT + depends on !64BIT help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read @@ -62,7 +61,6 @@ config PCMCIA_NINJA_SCSI config PCMCIA_QLOGIC tristate "Qlogic PCMCIA support" - depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -72,7 +70,6 @@ config PCMCIA_QLOGIC config PCMCIA_SYM53C500 tristate "Symbios 53c500 PCMCIA support" - depends on m help Say Y here if you have a New Media Bus Toaster or other PCMCIA SCSI adapter based on the Symbios 53c500 controller. -- cgit v1.2.3 From 0d06b281a1001ed40cace820d99eeb7d4453adb7 Mon Sep 17 00:00:00 2001 From: Henne Date: Mon, 26 Mar 2007 21:59:28 -0800 Subject: [SCSI] dpt: whitespace cleanup Remove some trailing whitespaces and some replace whitespaces with tabs. Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley --- drivers/scsi/dpt/dpti_i2o.h | 48 +++++++++++++++++++++---------------------- drivers/scsi/dpt/dpti_ioctl.h | 2 +- drivers/scsi/dpt/dptsig.h | 4 ++-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h index 5a49216fe4c..100b49baca7 100644 --- a/drivers/scsi/dpt/dpti_i2o.h +++ b/drivers/scsi/dpt/dpti_i2o.h @@ -31,7 +31,7 @@ * Tunable parameters first */ -/* How many different OSM's are we allowing */ +/* How many different OSM's are we allowing */ #define MAX_I2O_MODULES 64 #define I2O_EVT_CAPABILITY_OTHER 0x01 @@ -63,7 +63,7 @@ struct i2o_message u16 size; u32 target_tid:12; u32 init_tid:12; - u32 function:8; + u32 function:8; u32 initiator_context; /* List follows */ }; @@ -77,7 +77,7 @@ struct i2o_device char dev_name[8]; /* linux /dev name if available */ i2o_lct_entry lct_data;/* Device LCT information */ - u32 flags; + u32 flags; struct proc_dir_entry* proc_entry; /* /proc dir */ struct adpt_device *owner; struct _adpt_hba *controller; /* Controlling IOP */ @@ -86,7 +86,7 @@ struct i2o_device /* * Each I2O controller has one of these objects */ - + struct i2o_controller { char name[16]; @@ -111,9 +111,9 @@ struct i2o_sys_tbl_entry u32 iop_id:12; u32 reserved2:20; u16 seg_num:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; u16 frame_size; u16 reserved3; u32 last_changed; @@ -124,14 +124,14 @@ struct i2o_sys_tbl_entry struct i2o_sys_tbl { - u8 num_entries; - u8 version; - u16 reserved1; + u8 num_entries; + u8 version; + u16 reserved1; u32 change_ind; u32 reserved2; u32 reserved3; struct i2o_sys_tbl_entry iops[0]; -}; +}; /* * I2O classes / subclasses @@ -146,7 +146,7 @@ struct i2o_sys_tbl /* Class code names * (from v1.5 Table 6-1 Class Code Assignments.) */ - + #define I2O_CLASS_EXECUTIVE 0x000 #define I2O_CLASS_DDM 0x001 #define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 @@ -166,7 +166,7 @@ struct i2o_sys_tbl /* Rest of 0x092 - 0x09f reserved for peer-to-peer classes */ - + #define I2O_CLASS_MATCH_ANYCLASS 0xffffffff /* Subclasses @@ -175,7 +175,7 @@ struct i2o_sys_tbl #define I2O_SUBCLASS_i960 0x001 #define I2O_SUBCLASS_HDM 0x020 #define I2O_SUBCLASS_ISM 0x021 - + /* Operation functions */ #define I2O_PARAMS_FIELD_GET 0x0001 @@ -219,7 +219,7 @@ struct i2o_sys_tbl /* * Messaging API values */ - + #define I2O_CMD_ADAPTER_ASSIGN 0xB3 #define I2O_CMD_ADAPTER_READ 0xB2 #define I2O_CMD_ADAPTER_RELEASE 0xB5 @@ -284,16 +284,16 @@ struct i2o_sys_tbl #define I2O_PRIVATE_MSG 0xFF /* - * Init Outbound Q status + * Init Outbound Q status */ - + #define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01 #define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02 #define I2O_CMD_OUTBOUND_INIT_FAILED 0x03 #define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04 /* - * I2O Get Status State values + * I2O Get Status State values */ #define ADAPTER_STATE_INITIALIZING 0x01 @@ -303,7 +303,7 @@ struct i2o_sys_tbl #define ADAPTER_STATE_OPERATIONAL 0x08 #define ADAPTER_STATE_FAILED 0x10 #define ADAPTER_STATE_FAULTED 0x11 - + /* I2O API function return values */ #define I2O_RTN_NO_ERROR 0 @@ -321,9 +321,9 @@ struct i2o_sys_tbl /* Reply message status defines for all messages */ -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 #define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 #define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 #define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 @@ -338,7 +338,7 @@ struct i2o_sys_tbl #define I2O_PARAMS_STATUS_SUCCESS 0x00 #define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 -#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 #define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 #define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 #define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 @@ -390,7 +390,7 @@ struct i2o_sys_tbl #define I2O_CLAIM_MANAGEMENT 0x02000000 #define I2O_CLAIM_AUTHORIZED 0x03000000 #define I2O_CLAIM_SECONDARY 0x04000000 - + /* Message header defines for VersionOffset */ #define I2OVER15 0x0001 #define I2OVER20 0x0002 diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h index 82d24864be0..cc784e8f6e9 100644 --- a/drivers/scsi/dpt/dpti_ioctl.h +++ b/drivers/scsi/dpt/dpti_ioctl.h @@ -99,7 +99,7 @@ typedef struct { uCHAR eataVersion; /* EATA Version */ uLONG cpLength; /* EATA Command Packet Length */ uLONG spLength; /* EATA Status Packet Length */ - uCHAR drqNum; /* DRQ Index (0,5,6,7) */ + uCHAR drqNum; /* DRQ Index (0,5,6,7) */ uCHAR flag1; /* EATA Flags 1 (Byte 9) */ uCHAR flag2; /* EATA Flags 2 (Byte 30) */ } CtrlInfo; diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h index 4bf44779212..94bc894d120 100644 --- a/drivers/scsi/dpt/dptsig.h +++ b/drivers/scsi/dpt/dptsig.h @@ -145,8 +145,8 @@ typedef unsigned long sigLONG; #define FT_LOGGER 12 /* Event Logger */ #define FT_INSTALL 13 /* An Install Program */ #define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */ -#define FT_RESOURCE 15 /* Storage Manager Resource File */ -#define FT_MODEM_DB 16 /* Storage Manager Modem Database */ +#define FT_RESOURCE 15 /* Storage Manager Resource File */ +#define FT_MODEM_DB 16 /* Storage Manager Modem Database */ /* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */ /* ------------------------------------------------------------------ */ -- cgit v1.2.3 From b73c3d778647bffff6dbcbe41e8fc01215a22194 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 26 Mar 2007 21:59:33 -0800 Subject: [SCSI] Remove some unused SCSI-related kernel config variables. Remove the unused SCSI-related kernel config variables SCSI_NCR53C8XX_PROFILE_SUPPORT SCSI_NCR53C8XX_PROFILE 53C700_IO_MAPPED AIC79XX_ENABLE_RD_STRM AIC7XXX_PROBE_EISA_VL Signed-off-by: Robert P. J. Day Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- Documentation/scsi/ncr53c8xx.txt | 5 ----- drivers/scsi/Kconfig | 16 ---------------- drivers/scsi/aic7xxx/Kconfig.aic79xx | 12 ------------ drivers/scsi/aic7xxx/Kconfig.aic7xxx | 10 ---------- 4 files changed, 43 deletions(-) diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt index caf10b15518..88ef88b949f 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.txt @@ -562,11 +562,6 @@ if only one has a flaw for some SCSI feature, you can disable the support by the driver of this feature at linux start-up and enable this feature after boot-up only for devices that support it safely. -CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT (default answer: n) - This option must be set for profiling information to be gathered - and printed out through the proc file system. This features may - impact performances. - CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n) Answer "y" if you suspect your mother board to not allow memory mapped I/O. May slow down performance a little. This option is required by diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index f3bc0f459de..d243ae11520 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1200,17 +1200,6 @@ config SCSI_NCR53C8XX_SYNC There is no safe option other than using good cabling, right terminations and SCSI conformant devices. -config SCSI_NCR53C8XX_PROFILE - bool "enable profiling" - depends on SCSI_ZALON || SCSI_NCR_Q720 - help - This option allows you to enable profiling information gathering. - These statistics are not very accurate due to the low frequency - of the kernel clock (100 Hz on i386) and have performance impact - on systems that use very fast devices. - - The normal answer therefore is N. - config SCSI_NCR53C8XX_NO_DISCONNECT bool "not allow targets to disconnect" depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 @@ -1340,11 +1329,6 @@ config SCSI_SIM710 It currently supports Compaq EISA cards and NCR MCA cards -config 53C700_IO_MAPPED - bool - depends on SCSI_SIM710 - default y - config SCSI_SYM53C416 tristate "Symbios 53c416 SCSI support" depends on ISA && SCSI diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index 911ea1756e5..5e6620f8dab 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -57,18 +57,6 @@ config AIC79XX_BUILD_FIRMWARE or modify the assembler Makefile or the files it includes if your build environment is different than that of the author. -config AIC79XX_ENABLE_RD_STRM - bool "Enable Read Streaming for All Targets" - depends on SCSI_AIC79XX - default n - help - Read Streaming is a U320 protocol option that should enhance - performance. Early U320 drive firmware actually performs slower - with read streaming enabled so it is disabled by default. Read - Streaming can be configured in much the same way as tagged queueing - using the "rd_strm" command line option. See - drivers/scsi/aic7xxx/README.aic79xx for details. - config AIC79XX_DEBUG_ENABLE bool "Compile in Debugging Code" depends on SCSI_AIC79XX diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index cd93f9a8611..88da670a791 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -50,16 +50,6 @@ config AIC7XXX_RESET_DELAY_MS Default: 5000 (5 seconds) -config AIC7XXX_PROBE_EISA_VL - bool "Probe for EISA and VL AIC7XXX Adapters" - depends on SCSI_AIC7XXX && EISA - help - Probe for EISA and VLB Aic7xxx controllers. In many newer systems, - the invasive probes necessary to detect these controllers can cause - other devices to fail. For this reason, the non-PCI probe code is - disabled by default. The current value of this option can be "toggled" - via the no_probe kernel command line option. - config AIC7XXX_BUILD_FIRMWARE bool "Build Adapter Firmware with Kernel Build" depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD -- cgit v1.2.3 From 301b01aa621305e8d59a2eb948b4ad7bf26be86e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 26 Mar 2007 21:59:46 -0800 Subject: [SCSI] fusion: make mptspi_target_destroy() static Signed-off-by: Adrian Bunk Acked-by: Eric Moore Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/message/fusion/mptspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 755dec6b7ac..b08416f84ed 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -445,7 +445,7 @@ static int mptspi_target_alloc(struct scsi_target *starget) return 0; } -void +static void mptspi_target_destroy(struct scsi_target *starget) { if (starget->hostdata) -- cgit v1.2.3 From 3cfff0fc74bf5ac8213b5a2be583bf675ccd9511 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 26 Mar 2007 21:59:25 -0800 Subject: [SCSI] dpt_i2o: remove dead code The Coverity checker spotted this dead code introduced by commit a07f353701acae77e023f6270e8af353b37af7c4. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index cd36e81b2d9..f7b9dbd64a9 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -195,8 +195,6 @@ static int adpt_detect(struct scsi_host_template* sht) pci_dev_get(pDev); } } - if (pDev) - pci_dev_put(pDev); /* In INIT state, Activate IOPs */ for (pHba = hba_chain; pHba; pHba = pHba->next) { -- cgit v1.2.3 From 9695a25dbff788f26225966c43425e8bae7f06e8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 26 Mar 2007 21:59:35 -0800 Subject: [SCSI] aacraid: cleanups - proper prototypes for global code in aacraid.h - aac_rx_start_adapter() can now become static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 3 +++ drivers/scsi/aacraid/linit.c | 2 -- drivers/scsi/aacraid/nark.c | 3 --- drivers/scsi/aacraid/rkt.c | 3 --- drivers/scsi/aacraid/rx.c | 2 +- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 1771851db6e..249366f471c 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1843,8 +1843,11 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype); int aac_get_adapter_info(struct aac_dev* dev); int aac_send_shutdown(struct aac_dev *dev); int aac_probe_container(struct aac_dev *dev, int cid); +int _aac_rx_init(struct aac_dev *dev); +int aac_rx_select_comm(struct aac_dev *dev, int comm); extern int numacb; extern int acbsize; extern char aac_driver_version[]; extern int startup_timeout; extern int aif_timeout; +extern int expose_physicals; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index a5950c17d62..350ea7feb61 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -82,8 +82,6 @@ static LIST_HEAD(aac_devices); static int aac_cfg_major = -1; char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; -extern int expose_physicals; - /* * Because of the way Linux names scsi devices, the order in this table has * become important. Check for on-board Raid first, add-in cards second. diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index c76b611b6af..a8ace567781 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c @@ -74,9 +74,6 @@ static int aac_nark_ioremap(struct aac_dev * dev, u32 size) int aac_nark_init(struct aac_dev * dev) { - extern int _aac_rx_init(struct aac_dev *dev); - extern int aac_rx_select_comm(struct aac_dev *dev, int comm); - /* * Fill in the function dispatch table. */ diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index d953c3fe998..9c5fcfb398c 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -45,7 +45,6 @@ static int aac_rkt_select_comm(struct aac_dev *dev, int comm) { int retval; - extern int aac_rx_select_comm(struct aac_dev *dev, int comm); retval = aac_rx_select_comm(dev, comm); if (comm == AAC_COMM_MESSAGE) { /* @@ -97,8 +96,6 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size) int aac_rkt_init(struct aac_dev *dev) { - extern int _aac_rx_init(struct aac_dev *dev); - /* * Fill in the function dispatch table. */ diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 391d4751338..3e23aa6cac0 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -294,7 +294,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) * Start up processing on an i960 based AAC adapter */ -void aac_rx_start_adapter(struct aac_dev *dev) +static void aac_rx_start_adapter(struct aac_dev *dev) { struct aac_init *init; -- cgit v1.2.3 From e3e0ca5143d7a78522df30b75bd1acfcf80c2a38 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 26 Mar 2007 21:59:29 -0800 Subject: [SCSI] aic7xxx: make functions static Signed-off-by: Adrian Bunk Acked-by: Hannes Reinecke Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 6 ++++-- drivers/scsi/aic7xxx/aic79xx_osm.h | 2 -- drivers/scsi/aic7xxx/aic7xxx.h | 5 ----- drivers/scsi/aic7xxx/aic7xxx_core.c | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 2be03e975d9..6054881f21f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -363,6 +363,8 @@ static int ahd_linux_run_command(struct ahd_softc*, struct scsi_cmnd *); static void ahd_linux_setup_tag_info_global(char *p); static int aic79xx_setup(char *c); +static void ahd_freeze_simq(struct ahd_softc *ahd); +static void ahd_release_simq(struct ahd_softc *ahd); static int ahd_linux_unit; @@ -2016,13 +2018,13 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); } -void +static void ahd_freeze_simq(struct ahd_softc *ahd) { scsi_block_requests(ahd->platform_data->host); } -void +static void ahd_release_simq(struct ahd_softc *ahd) { scsi_unblock_requests(ahd->platform_data->host); diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 147c83c456a..9218f29314f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -837,8 +837,6 @@ int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg); void ahd_platform_free(struct ahd_softc *ahd); void ahd_platform_init(struct ahd_softc *ahd); void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -void ahd_freeze_simq(struct ahd_softc *ahd); -void ahd_release_simq(struct ahd_softc *ahd); static __inline void ahd_freeze_scb(struct scb *scb) diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 954c7c24501..e1bd57b9f23 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -1278,11 +1278,6 @@ typedef enum { AHC_QUEUE_TAGGED } ahc_queue_alg; -void ahc_set_tags(struct ahc_softc *ahc, - struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, - ahc_queue_alg alg); - /**************************** Target Mode *************************************/ #ifdef AHC_TARGET_MODE void ahc_send_lstate_events(struct ahc_softc *, diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 50ef785224d..75733b09f27 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -2073,7 +2073,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, /* * Update the current state of tagged queuing for a given target. */ -void +static void ahc_set_tags(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, ahc_queue_alg alg) { -- cgit v1.2.3 From 10c9a017f1bd84a7aedaea7029cd5224863197db Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Tue, 27 Mar 2007 11:51:34 -0400 Subject: [SCSI] aacraid: Add SMC and SUN products to README Add SMC and SUN products to aacraid documentation Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- Documentation/scsi/aacraid.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt index dc8e44fc650..bddc641dddb 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.txt @@ -37,7 +37,11 @@ Supported Cards/Chipsets 9005:0286:9005:029d Adaptec 2420SA (Intruder HP release) 9005:0286:9005:02ac Adaptec 1800 (Typhoon44) 9005:0285:9005:02b5 Adaptec 5445 (Voodoo44) + 9005:0285:15d9:02b5 SMC AOC-USAS-S4i + 9005:0285:15d9:02c9 SMC AOC-USAS-S4iB 9005:0285:9005:02b6 Adaptec 5805 (Voodoo80) + 9005:0285:15d9:02b6 SMC AOC-USAS-S8i + 9005:0285:15d9:02ca SMC AOC-USAS-S8iB 9005:0285:9005:02b7 Adaptec 5085 (Voodoo08) 9005:0285:9005:02bb Adaptec 3405 (Marauder40LP) 9005:0285:9005:02bc Adaptec 3805 (Marauder80LP) @@ -93,6 +97,9 @@ Supported Cards/Chipsets 9005:0286:9005:02ae (Aurora Lite ARK) 9005:0285:9005:02b0 (Sunrise Lake ARK) 9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external) + 9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote) + 9005:0285:108e:0286 SUN SG-XPCIESAS-R-IN (Cougar) + 9005:0285:108e:0287 SUN SG-XPCIESAS-R-EX (Prometheus) People ------------------------- -- cgit v1.2.3 From 4dfb7cbef856689caebd0f498dbd140d1b79954f Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Tue, 27 Mar 2007 15:07:28 -0400 Subject: [SCSI] aacraid: resolve compiler warnings using ptrdiff_t Unsigned long is not always the same size as a pointer, namely on 32 bit systems with 64 bit address space. Ptrdiff_t is the same size as a pointer in all configurations. By using ptrdiff_t we can mitigate the warning messages on these configurations. There should be no side effects of this patch. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commctrl.c | 4 +--- drivers/scsi/aacraid/comminit.c | 4 ++-- drivers/scsi/aacraid/dpcsup.c | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 987e35e4078..72b0393b459 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -391,10 +391,8 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg) /* * Extract the fibctx from the input parameters */ - if (fibctx->unique == (u32)(unsigned long)arg) { - /* We found a winner */ + if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */ break; - } entry = entry->next; fibctx = NULL; } diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index ae34768987a..33682ce96a5 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co /* * Align the beginning of Headers to commalign */ - align = (commalign - ((unsigned long)(base) & (commalign - 1))); + align = (commalign - ((ptrdiff_t)(base) & (commalign - 1))); base = base + align; phys = phys + align; /* diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index 4e53f9db1b2..fbf27f59a31 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -256,7 +256,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) return 1; } memset(hw_fib, 0, sizeof(struct hw_fib)); - memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib)); + memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) + + (index & ~0x00000002L)), sizeof(struct hw_fib)); memset(fib, 0, sizeof(struct fib)); INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; -- cgit v1.2.3 From 665db93b8a5fc6a11e2ace6b20569420a353d037 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Wed, 28 Mar 2007 00:49:49 +0200 Subject: [SCSI] qla2xxx: Remove duplicate pci_disable_device() call On the path qla2x00_probe_one() -> probe_failed -> qla2x00_free_device(), pci_disable_device() is executed twice, once in qla2x00_free_device() and once in qla2x00_probe_one(). This patch removes the unnecessary call. Signed-off-by: Bernhard Walle Acked-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b6c96a8e033..b78919a318e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1707,6 +1707,7 @@ qla2x00_remove_one(struct pci_dev *pdev) scsi_host_put(ha->host); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -1749,8 +1750,6 @@ qla2x00_free_device(scsi_qla_host_t *ha) if (ha->iobase) iounmap(ha->iobase); pci_release_regions(ha->pdev); - - pci_disable_device(ha->pdev); } static inline void -- cgit v1.2.3 From 9e3738f3c83f534d82f1d7d5191dcecb2425f7f9 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 28 Mar 2007 14:20:40 +0200 Subject: [SCSI] zfcp: fix initialization of FSF timer Correctly initialize the timer for FSF requests with jiffies + timeout. Cc: Swen Schillig Acked-by: Heiko Carstens Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 421da1e7c0e..c1f2d4b14c2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -186,7 +186,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) { fsf_req->timer.function = zfcp_fsf_request_timeout_handler; fsf_req->timer.data = (unsigned long) fsf_req->adapter; - fsf_req->timer.expires = timeout; + fsf_req->timer.expires = jiffies + timeout; add_timer(&fsf_req->timer); } -- cgit v1.2.3 From 74ee9d52cf8b524edf8ae6222c8bfcc6df6f5954 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 28 Mar 2007 09:22:39 -0400 Subject: [SCSI] aacraid: remove unused or deprecated firmware constants Just sweeping the floor clean in one spot. Some of these constants have never been used in the driver or in the firmware (and thus are meaningless). Triggered this patch because I discovered one of the unused constants was actually incorrect and figured it was better to clean them out than correct and update. There are no side effects at all regarding this patch, it is purely cosmetic. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 249366f471c..12cad1f3020 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -48,49 +48,13 @@ struct diskparm /* - * DON'T CHANGE THE ORDER, this is set by the firmware + * Firmware constants */ #define CT_NONE 0 -#define CT_VOLUME 1 -#define CT_MIRROR 2 -#define CT_STRIPE 3 -#define CT_RAID5 4 -#define CT_SSRW 5 -#define CT_SSRO 6 -#define CT_MORPH 7 -#define CT_PASSTHRU 8 -#define CT_RAID4 9 -#define CT_RAID10 10 /* stripe of mirror */ -#define CT_RAID00 11 /* stripe of stripe */ -#define CT_VOLUME_OF_MIRRORS 12 /* volume of mirror */ -#define CT_PSEUDO_RAID 13 /* really raid4 */ -#define CT_LAST_VOLUME_TYPE 14 #define CT_OK 218 - -/* - * Types of objects addressable in some fashion by the client. - * This is a superset of those objects handled just by the filesystem - * and includes "raw" objects that an administrator would use to - * configure containers and filesystems. - */ - -#define FT_REG 1 /* regular file */ -#define FT_DIR 2 /* directory */ -#define FT_BLK 3 /* "block" device - reserved */ -#define FT_CHR 4 /* "character special" device - reserved */ -#define FT_LNK 5 /* symbolic link */ -#define FT_SOCK 6 /* socket */ -#define FT_FIFO 7 /* fifo */ #define FT_FILESYS 8 /* ADAPTEC's "FSA"(tm) filesystem */ #define FT_DRIVE 9 /* physical disk - addressable in scsi by bus/id/lun */ -#define FT_SLICE 10 /* virtual disk - raw volume - slice */ -#define FT_PARTITION 11 /* FSA partition - carved out of a slice - building block for containers */ -#define FT_VOLUME 12 /* Container - Volume Set */ -#define FT_STRIPE 13 /* Container - Stripe Set */ -#define FT_MIRROR 14 /* Container - Mirror Set */ -#define FT_RAID5 15 /* Container - Raid 5 Set */ -#define FT_DATABASE 16 /* Storage object with "foreign" content manager */ /* * Host side memory scatter gather list @@ -1519,8 +1483,7 @@ struct aac_mntent { struct creation_info create_info; /* if applicable */ __le32 capacity; __le32 vol; /* substrate structure */ - __le32 obj; /* FT_FILESYS, - FT_DATABASE, etc. */ + __le32 obj; /* FT_FILESYS, etc. */ __le32 state; /* unready for mounting, readonly, etc. */ union aac_contentinfo fileinfo; /* Info specific to content -- cgit v1.2.3 From a45c863f02c808107172b4b2975e1130c7da66d6 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 28 Mar 2007 13:44:54 -0400 Subject: [SCSI] aacraid: fix print of Firmware Build Date and add TSID The Adapter build date that is to be printed on instantiation was not displayed as a result of the supplemental adapter information structure not being in sync with the Firmware; the driver took an early test cycle version that had a miss-sized padded region at the head and the structure was not re-checked at the end of qualification. The Build Date was not a priority and is merely a cosmetic enhancement, and the wrong location for the start of the structure member would not induce any side-effect problems. We updated the structure to match the actual format, and added the TSID (Tech Support Identification) value print, should it be present, to the adapter instantiation announcements during driver load. This later enhancement should improve the relationship between Service folk & Tech Support if the printed value of the TSID found it's way into the circular file labeled G... Neither of these values show in sysfs (yet). Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 ++++++ drivers/scsi/aacraid/aacraid.h | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index fc16fe0dfa8..31ac9f56cd1 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1194,6 +1194,12 @@ int aac_get_adapter_info(struct aac_dev* dev) printk(KERN_INFO "%s%d: serial %x\n", dev->name, dev->id, le32_to_cpu(dev->adapter_info.serial[0])); + if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) { + printk(KERN_INFO "%s%d: TSID %.*s\n", + dev->name, dev->id, + (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), + dev->supplement_adapter_info.VpdInfo.Tsid); + } } dev->nondasd_support = 0; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 12cad1f3020..45ca3e80161 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -843,10 +843,25 @@ struct aac_supplement_adapter_info __le32 Version; __le32 FeatureBits; u8 SlotNumber; - u8 ReservedPad0[0]; + u8 ReservedPad0[3]; u8 BuildDate[12]; __le32 CurrentNumberPorts; - __le32 ReservedGrowth[24]; + struct { + u8 AssemblyPn[8]; + u8 FruPn[8]; + u8 BatteryFruPn[8]; + u8 EcVersionString[8]; + u8 Tsid[12]; + } VpdInfo; + __le32 FlashFirmwareRevision; + __le32 FlashFirmwareBuild; + __le32 RaidTypeMorphOptions; + __le32 FlashFirmwareBootRevision; + __le32 FlashFirmwareBootBuild; + u8 MfgPcbaSerialNo[12]; + u8 MfgWWNName[8]; + __le32 MoreFeatureBits; + __le32 ReservedGrowth[1]; }; #define AAC_FEATURE_FALCON 0x00000010 #define AAC_SIS_VERSION_V3 3 -- cgit v1.2.3 From a897ff2a6386ac4368ba41db18b626afd903f9d8 Mon Sep 17 00:00:00 2001 From: Robert Jennings Date: Wed, 28 Mar 2007 12:45:46 -0500 Subject: [SCSI] ibmvscsi: allow for dynamic adjustment of server request_limit The request limit calculations used previously on the client failed to mirror the state of the server. Additionally, when a value < 3 was provided there could be problems setting can_queue and handling abort and reset commands. Signed-off-by: "Robert Jennings" Signed-off-by: Santiago Leon Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 58 ++++++++++++++++++++++++++-------------- drivers/scsi/ibmvscsi/ibmvscsi.h | 2 ++ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index fbc1d5c3b0a..383f5948ba0 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -85,7 +85,7 @@ static int max_id = 64; static int max_channel = 3; static int init_timeout = 5; -static int max_requests = 50; +static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; #define IBMVSCSI_VERSION "1.5.8" @@ -538,7 +538,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, int request_status; int rc; - /* If we have exhausted our request limit, just fail this request. + /* If we have exhausted our request limit, just fail this request, + * unless it is for a reset or abort. * Note that there are rare cases involving driver generated requests * (such as task management requests) that the mid layer may think we * can handle more requests (can_queue) when we actually can't @@ -551,9 +552,30 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, */ if (request_status < -1) goto send_error; - /* Otherwise, if we have run out of requests */ - else if (request_status < 0) - goto send_busy; + /* Otherwise, we may have run out of requests. */ + /* Abort and reset calls should make it through. + * Nothing except abort and reset should use the last two + * slots unless we had two or less to begin with. + */ + else if (request_status < 2 && + evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) { + /* In the case that we have less than two requests + * available, check the server limit as a combination + * of the request limit and the number of requests + * in-flight (the size of the send list). If the + * server limit is greater than 2, return busy so + * that the last two are reserved for reset and abort. + */ + int server_limit = request_status; + struct srp_event_struct *tmp_evt; + + list_for_each_entry(tmp_evt, &hostdata->sent, list) { + server_limit++; + } + + if (server_limit > 2) + goto send_busy; + } } /* Copy the IU into the transfer area */ @@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, printk(KERN_ERR "ibmvscsi: send error %d\n", rc); + atomic_inc(&hostdata->request_limit); goto send_error; } @@ -581,7 +604,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); free_event_struct(&hostdata->pool, evt_struct); - return SCSI_MLQUEUE_HOST_BUSY; + atomic_inc(&hostdata->request_limit); + return SCSI_MLQUEUE_HOST_BUSY; send_error: unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); @@ -831,23 +855,16 @@ static void login_rsp(struct srp_event_struct *evt_struct) printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n"); - if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta > - (max_requests - 2)) - evt_struct->xfer_iu->srp.login_rsp.req_lim_delta = - max_requests - 2; + if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0) + printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n"); - /* Now we know what the real request-limit is */ + /* Now we know what the real request-limit is. + * This value is set rather than added to request_limit because + * request_limit could have been set to -1 by this client. + */ atomic_set(&hostdata->request_limit, evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); - hostdata->host->can_queue = - evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2; - - if (hostdata->host->can_queue < 1) { - printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n"); - return; - } - /* If we had any pending I/Os, kick them */ scsi_unblock_requests(hostdata->host); @@ -1483,7 +1500,7 @@ static struct scsi_host_template driver_template = { .eh_abort_handler = ibmvscsi_eh_abort_handler, .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, .cmd_per_lun = 16, - .can_queue = 1, /* Updated after SRP_LOGIN */ + .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, .this_id = -1, .sg_tablesize = SG_ALL, .use_clustering = ENABLE_CLUSTERING, @@ -1503,6 +1520,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) vdev->dev.driver_data = NULL; + driver_template.can_queue = max_requests; host = scsi_host_alloc(&driver_template, sizeof(*hostdata)); if (!host) { printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n"); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 5c6d9358292..77cc1d40f5b 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -44,6 +44,8 @@ struct Scsi_Host; */ #define MAX_INDIRECT_BUFS 10 +#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100 + /* ------------------------------------------------------------ * Data Structures */ -- cgit v1.2.3 From 0979c84b4affaf924a894380dd0069638b64de03 Mon Sep 17 00:00:00 2001 From: Robert Jennings Date: Thu, 29 Mar 2007 12:30:40 -0500 Subject: [SCSI] ibmvscsi: add slave_configure to allow device restart Fixed the kernel-doc comment for ibmvscsi_slave_configure. Thanks to Randy Dunlap for pointing this out. Adding a slave_configure function for the driver. Now the disks can be restarted by the scsi mid-layer when the are disconnected and reconnected. Signed-off-by: "Robert Jennings" Signed-off-by: "Santiago Leon" Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 383f5948ba0..b10eefe735c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1354,6 +1354,27 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, return rc; } +/** + * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk. + * @sdev: struct scsi_device device to configure + * + * Enable allow_restart for a device if it is a disk. Adjust the + * queue_depth here also as is required by the documentation for + * struct scsi_host_template. + */ +static int ibmvscsi_slave_configure(struct scsi_device *sdev) +{ + struct Scsi_Host *shost = sdev->host; + unsigned long lock_flags = 0; + + spin_lock_irqsave(shost->host_lock, lock_flags); + if (sdev->type == TYPE_DISK) + sdev->allow_restart = 1; + scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); + spin_unlock_irqrestore(shost->host_lock, lock_flags); + return 0; +} + /* ------------------------------------------------------------ * sysfs attributes */ @@ -1499,6 +1520,7 @@ static struct scsi_host_template driver_template = { .queuecommand = ibmvscsi_queuecommand, .eh_abort_handler = ibmvscsi_eh_abort_handler, .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, + .slave_configure = ibmvscsi_slave_configure, .cmd_per_lun = 16, .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, .this_id = -1, -- cgit v1.2.3 From 5469cb5bdef76dbe18865fff30975f0694fff2c2 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:42:40 -0500 Subject: [SCSI] ipr: Make adapter operational timeout be per adapter type Some ipr adapters may take longer than others to come operational. This patch makes this timeout different for different adapters, while still preserving the module parameter which can be used to globally override the default. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 29 +++++++++++++++++++++-------- drivers/scsi/ipr.h | 5 +++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 95045e33710..ba17ac50127 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -89,7 +89,7 @@ static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL; static unsigned int ipr_max_speed = 1; static int ipr_testmode = 0; static unsigned int ipr_fastfail = 0; -static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT; +static unsigned int ipr_transop_timeout = 0; static unsigned int ipr_enable_cache = 1; static unsigned int ipr_debug = 0; static int ipr_auto_create = 1; @@ -6187,7 +6187,7 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n"); ipr_cmd->timer.data = (unsigned long) ipr_cmd; - ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ); + ipr_cmd->timer.expires = jiffies + (ioa_cfg->transop_timeout * HZ); ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout; ipr_cmd->done = ipr_reset_ioa_job; add_timer(&ipr_cmd->timer); @@ -7232,6 +7232,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto out_scsi_host_put; } + if (ipr_transop_timeout) + ioa_cfg->transop_timeout = ipr_transop_timeout; + else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT) + ioa_cfg->transop_timeout = IPR_LONG_OPERATIONAL_TIMEOUT; + else + ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT; + ipr_regs_pci = pci_resource_start(pdev, 0); rc = pci_request_regions(pdev, IPR_NAME); @@ -7539,29 +7546,35 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 88f285de97b..c83ccbb2498 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -104,6 +104,9 @@ #define IPR_IOASC_IOA_WAS_RESET 0x10000001 #define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002 +/* Driver data flags */ +#define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001 + #define IPR_DEFAULT_MAX_ERROR_DUMP 984 #define IPR_NUM_LOG_HCAMS 2 #define IPR_NUM_CFG_CHG_HCAMS 2 @@ -179,6 +182,7 @@ #define IPR_SET_SUP_DEVICE_TIMEOUT (2 * 60 * HZ) #define IPR_REQUEST_SENSE_TIMEOUT (10 * HZ) #define IPR_OPERATIONAL_TIMEOUT (5 * 60) +#define IPR_LONG_OPERATIONAL_TIMEOUT (12 * 60) #define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ) #define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10) #define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ) @@ -1119,6 +1123,7 @@ struct ipr_ioa_cfg { struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES]; + unsigned int transop_timeout; const struct ipr_chip_cfg_t *chip_cfg; void __iomem *hdw_dma_regs; /* iomapped PCI memory space */ -- cgit v1.2.3 From 7d2267bb9d94aabfa316a13d04b0bce2fb51ff83 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:42:47 -0500 Subject: [SCSI] ipr: Remove auto RAID create module parameter Remove the auto RAID 0 array creation module parameter, since support for this function has been removed from the firmware. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index ba17ac50127..6bd64d4edcd 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -92,7 +92,6 @@ static unsigned int ipr_fastfail = 0; static unsigned int ipr_transop_timeout = 0; static unsigned int ipr_enable_cache = 1; static unsigned int ipr_debug = 0; -static int ipr_auto_create = 1; static DEFINE_SPINLOCK(ipr_driver_lock); /* This table describes the differences between DMA controller chips */ @@ -159,8 +158,6 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0); MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); module_param_named(debug, ipr_debug, int, 0); MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); -module_param_named(auto_create, ipr_auto_create, int, 0); -MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when initialized (default: 1)"); MODULE_LICENSE("GPL"); MODULE_VERSION(IPR_DRIVER_VERSION); @@ -7116,8 +7113,6 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, ioa_cfg->pdev = pdev; ioa_cfg->log_level = ipr_log_level; ioa_cfg->doorbell = IPR_DOORBELL; - if (!ipr_auto_create) - ioa_cfg->doorbell |= IPR_RUNTIME_RESET; sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER); sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL); sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL); -- cgit v1.2.3 From 185eb31cc242f415800a1a06dca522d27c269279 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:42:53 -0500 Subject: [SCSI] ipr: Add new PCI-E IDs to device table Adds support for some new PCI-E ipr adapters. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 10 ++++++++++ drivers/scsi/ipr.h | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 6bd64d4edcd..4fd6a3d81ff 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7557,6 +7557,13 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, @@ -7570,6 +7577,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SCAMP_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index c83ccbb2498..4d068887608 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -55,6 +55,7 @@ #define IPR_NUM_BASE_CMD_BLKS 100 #define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339 +#define PCI_DEVICE_ID_IBM_SCAMP_E 0x034A #define IPR_SUBS_DEV_ID_2780 0x0264 #define IPR_SUBS_DEV_ID_5702 0x0266 @@ -69,8 +70,12 @@ #define IPR_SUBS_DEV_ID_572A 0x02C1 #define IPR_SUBS_DEV_ID_572B 0x02C2 #define IPR_SUBS_DEV_ID_572F 0x02C3 +#define IPR_SUBS_DEV_ID_574D 0x030B +#define IPR_SUBS_DEV_ID_574E 0x030A #define IPR_SUBS_DEV_ID_575B 0x030D #define IPR_SUBS_DEV_ID_575C 0x0338 +#define IPR_SUBS_DEV_ID_575D 0x033E +#define IPR_SUBS_DEV_ID_57B3 0x033A #define IPR_SUBS_DEV_ID_57B7 0x0360 #define IPR_SUBS_DEV_ID_57B8 0x02C2 -- cgit v1.2.3 From cc9bd5d4256ecc1b6e0448febb4be29db1a91256 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:01 -0500 Subject: [SCSI] ipr: Enable logging of debug error data for all devices The ipr driver has a sysfs attribute which can be used to adjust the logging level of the driver for error events. The error response data for commands can be dumped by increasing the logging level of the ipr driver. This currently only works for JBOD passthrough devices. This patch enables this function for all devices, including RAID devices, to aid in debugging problems. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 4fd6a3d81ff..5b6ffe18bc7 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4473,6 +4473,9 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, if (ioasa->ilid != 0) return; + if (!ipr_is_gscsi(res)) + return; + if (ipr_error_table[error_index].log_ioasa == 0) return; } @@ -4632,11 +4635,11 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, return; } - if (ipr_is_gscsi(res)) - ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); - else + if (!ipr_is_gscsi(res)) ipr_gen_sense(ipr_cmd); + ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); + switch (ioasc & IPR_IOASC_IOASC_MASK) { case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST: if (ipr_is_naca_model(res)) -- cgit v1.2.3 From b0692dd4d7e90ce5cf1241731c6e80118402e3b4 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:09 -0500 Subject: [SCSI] ipr: Log error for SAS dual path switch For ipr SAS adapters that support dual pathing, this patch modifies ipr to log an error when a path fails. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 5b6ffe18bc7..44ce9f5218a 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4453,12 +4453,13 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, { int i; u16 data_len; - u32 ioasc; + u32 ioasc, fd_ioasc; struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; __be32 *ioasa_data = (__be32 *)ioasa; int error_index; ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK; + fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK; if (0 == ioasc) return; @@ -4466,7 +4467,10 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL) return; - error_index = ipr_get_error(ioasc); + if (ioasc == IPR_IOASC_BUS_WAS_RESET && fd_ioasc) + error_index = ipr_get_error(fd_ioasc); + else + error_index = ipr_get_error(ioasc); if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) { /* Don't log an error if the IOA already logged one */ -- cgit v1.2.3 From 24d6f2b50bd34d0da540a9e6f71c4b6ab25f4b93 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:17 -0500 Subject: [SCSI] ipr: Fix for oops following SATA request sense This patch fixes a problem discovered on a system with some bad SATA devices attached. If a command to a SATAPI device times out and the device gets reset as part of error recovery, its possible that ipr will set err_mask to indicate a device error has occurred. If this happens, a request sense will get issued by libata. Since scsi core thinks this scsi command is now completed, because the device reset handler completed successfully, scsi core will free the associated scsi command, which may cause an oops when that request sense is completed later by ipr. This patch ensures that any commands that get aborted as a result of a device reset set err_mask appropriately so that the request sense does not get sent. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 44ce9f5218a..fc1171c7def 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3846,6 +3846,8 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { if (ipr_cmd->scsi_cmd) ipr_cmd->done = ipr_scsi_eh_done; + if (ipr_cmd->qc) + ipr_cmd->done = ipr_sata_eh_done; if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; -- cgit v1.2.3 From a9aedb098437655b7b78d66e0e28405830cbdbef Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:23 -0500 Subject: [SCSI] ipr: PCI unblock config access fix Fix to make sure user config accesses get re-enabled if the PCI config write to start BIST fails. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index fc1171c7def..b502c831cc5 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6390,6 +6390,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); if (rc != PCIBIOS_SUCCESSFUL) { + pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); rc = IPR_RC_JOB_CONTINUE; } else { -- cgit v1.2.3 From 933916f365f9ef1268c058bfaba2d4dcf26e4fd0 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:30 -0500 Subject: [SCSI] ipr: Improve async error logging level control Add the ability to control how much error data gets logged on a per error basis. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 192 ++++++++++++++++++++++++++--------------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b502c831cc5..e1d24ddd881 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -164,7 +164,7 @@ MODULE_VERSION(IPR_DRIVER_VERSION); /* A constant array of IOASCs/URCs/Error Messages */ static const struct ipr_error_table_t ipr_error_table[] = { - {0x00000000, 1, 1, + {0x00000000, 1, IPR_DEFAULT_LOG_LEVEL, "8155: An unknown error was received"}, {0x00330000, 0, 0, "Soft underlength error"}, @@ -172,37 +172,37 @@ struct ipr_error_table_t ipr_error_table[] = { "Command to be cancelled not found"}, {0x00808000, 0, 0, "Qualified success"}, - {0x01080000, 1, 1, + {0x01080000, 1, IPR_DEFAULT_LOG_LEVEL, "FFFE: Soft device bus error recovered by the IOA"}, - {0x01088100, 0, 1, + {0x01088100, 0, IPR_DEFAULT_LOG_LEVEL, "4101: Soft device bus fabric error"}, - {0x01170600, 0, 1, + {0x01170600, 0, IPR_DEFAULT_LOG_LEVEL, "FFF9: Device sector reassign successful"}, - {0x01170900, 0, 1, + {0x01170900, 0, IPR_DEFAULT_LOG_LEVEL, "FFF7: Media error recovered by device rewrite procedures"}, - {0x01180200, 0, 1, + {0x01180200, 0, IPR_DEFAULT_LOG_LEVEL, "7001: IOA sector reassignment successful"}, - {0x01180500, 0, 1, + {0x01180500, 0, IPR_DEFAULT_LOG_LEVEL, "FFF9: Soft media error. Sector reassignment recommended"}, - {0x01180600, 0, 1, + {0x01180600, 0, IPR_DEFAULT_LOG_LEVEL, "FFF7: Media error recovered by IOA rewrite procedures"}, - {0x01418000, 0, 1, + {0x01418000, 0, IPR_DEFAULT_LOG_LEVEL, "FF3D: Soft PCI bus error recovered by the IOA"}, - {0x01440000, 1, 1, + {0x01440000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device hardware error recovered by the IOA"}, - {0x01448100, 0, 1, + {0x01448100, 0, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device hardware error recovered by the device"}, - {0x01448200, 1, 1, + {0x01448200, 1, IPR_DEFAULT_LOG_LEVEL, "FF3D: Soft IOA error recovered by the IOA"}, - {0x01448300, 0, 1, + {0x01448300, 0, IPR_DEFAULT_LOG_LEVEL, "FFFA: Undefined device response recovered by the IOA"}, - {0x014A0000, 1, 1, + {0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device bus error, message or command phase"}, - {0x014A8000, 0, 1, + {0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFE: Task Management Function failed"}, - {0x015D0000, 0, 1, + {0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF6: Failure prediction threshold exceeded"}, - {0x015D9200, 0, 1, + {0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL, "8009: Impending cache battery pack failure"}, {0x02040400, 0, 0, "34FF: Disk device format in progress"}, @@ -212,85 +212,85 @@ struct ipr_error_table_t ipr_error_table[] = { "No ready, IOA shutdown"}, {0x025A0000, 0, 0, "Not ready, IOA has been shutdown"}, - {0x02670100, 0, 1, + {0x02670100, 0, IPR_DEFAULT_LOG_LEVEL, "3020: Storage subsystem configuration error"}, {0x03110B00, 0, 0, "FFF5: Medium error, data unreadable, recommend reassign"}, {0x03110C00, 0, 0, "7000: Medium error, data unreadable, do not reassign"}, - {0x03310000, 0, 1, + {0x03310000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF3: Disk media format bad"}, - {0x04050000, 0, 1, + {0x04050000, 0, IPR_DEFAULT_LOG_LEVEL, "3002: Addressed device failed to respond to selection"}, - {0x04080000, 1, 1, + {0x04080000, 1, IPR_DEFAULT_LOG_LEVEL, "3100: Device bus error"}, - {0x04080100, 0, 1, + {0x04080100, 0, IPR_DEFAULT_LOG_LEVEL, "3109: IOA timed out a device command"}, {0x04088000, 0, 0, "3120: SCSI bus is not operational"}, - {0x04088100, 0, 1, + {0x04088100, 0, IPR_DEFAULT_LOG_LEVEL, "4100: Hard device bus fabric error"}, - {0x04118000, 0, 1, + {0x04118000, 0, IPR_DEFAULT_LOG_LEVEL, "9000: IOA reserved area data check"}, - {0x04118100, 0, 1, + {0x04118100, 0, IPR_DEFAULT_LOG_LEVEL, "9001: IOA reserved area invalid data pattern"}, - {0x04118200, 0, 1, + {0x04118200, 0, IPR_DEFAULT_LOG_LEVEL, "9002: IOA reserved area LRC error"}, - {0x04320000, 0, 1, + {0x04320000, 0, IPR_DEFAULT_LOG_LEVEL, "102E: Out of alternate sectors for disk storage"}, - {0x04330000, 1, 1, + {0x04330000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Data transfer underlength error"}, - {0x04338000, 1, 1, + {0x04338000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Data transfer overlength error"}, - {0x043E0100, 0, 1, + {0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL, "3400: Logical unit failure"}, - {0x04408500, 0, 1, + {0x04408500, 0, IPR_DEFAULT_LOG_LEVEL, "FFF4: Device microcode is corrupt"}, - {0x04418000, 1, 1, + {0x04418000, 1, IPR_DEFAULT_LOG_LEVEL, "8150: PCI bus error"}, {0x04430000, 1, 0, "Unsupported device bus message received"}, - {0x04440000, 1, 1, + {0x04440000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Disk device problem"}, - {0x04448200, 1, 1, + {0x04448200, 1, IPR_DEFAULT_LOG_LEVEL, "8150: Permanent IOA failure"}, - {0x04448300, 0, 1, + {0x04448300, 0, IPR_DEFAULT_LOG_LEVEL, "3010: Disk device returned wrong response to IOA"}, - {0x04448400, 0, 1, + {0x04448400, 0, IPR_DEFAULT_LOG_LEVEL, "8151: IOA microcode error"}, {0x04448500, 0, 0, "Device bus status error"}, - {0x04448600, 0, 1, + {0x04448600, 0, IPR_DEFAULT_LOG_LEVEL, "8157: IOA error requiring IOA reset to recover"}, {0x04448700, 0, 0, "ATA device status error"}, {0x04490000, 0, 0, "Message reject received from the device"}, - {0x04449200, 0, 1, + {0x04449200, 0, IPR_DEFAULT_LOG_LEVEL, "8008: A permanent cache battery pack failure occurred"}, - {0x0444A000, 0, 1, + {0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL, "9090: Disk unit has been modified after the last known status"}, - {0x0444A200, 0, 1, + {0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL, "9081: IOA detected device error"}, - {0x0444A300, 0, 1, + {0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL, "9082: IOA detected device error"}, - {0x044A0000, 1, 1, + {0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL, "3110: Device bus error, message or command phase"}, - {0x044A8000, 1, 1, + {0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL, "3110: SAS Command / Task Management Function failed"}, - {0x04670400, 0, 1, + {0x04670400, 0, IPR_DEFAULT_LOG_LEVEL, "9091: Incorrect hardware configuration change has been detected"}, - {0x04678000, 0, 1, + {0x04678000, 0, IPR_DEFAULT_LOG_LEVEL, "9073: Invalid multi-adapter configuration"}, - {0x04678100, 0, 1, + {0x04678100, 0, IPR_DEFAULT_LOG_LEVEL, "4010: Incorrect connection between cascaded expanders"}, - {0x04678200, 0, 1, + {0x04678200, 0, IPR_DEFAULT_LOG_LEVEL, "4020: Connections exceed IOA design limits"}, - {0x04678300, 0, 1, + {0x04678300, 0, IPR_DEFAULT_LOG_LEVEL, "4030: Incorrect multipath connection"}, - {0x04679000, 0, 1, + {0x04679000, 0, IPR_DEFAULT_LOG_LEVEL, "4110: Unsupported enclosure function"}, - {0x046E0000, 0, 1, + {0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF4: Command to logical unit failed"}, {0x05240000, 1, 0, "Illegal request, invalid request type or request packet"}, @@ -310,101 +310,101 @@ struct ipr_error_table_t ipr_error_table[] = { "Illegal request, command sequence error"}, {0x052C8000, 1, 0, "Illegal request, dual adapter support not enabled"}, - {0x06040500, 0, 1, + {0x06040500, 0, IPR_DEFAULT_LOG_LEVEL, "9031: Array protection temporarily suspended, protection resuming"}, - {0x06040600, 0, 1, + {0x06040600, 0, IPR_DEFAULT_LOG_LEVEL, "9040: Array protection temporarily suspended, protection resuming"}, - {0x06288000, 0, 1, + {0x06288000, 0, IPR_DEFAULT_LOG_LEVEL, "3140: Device bus not ready to ready transition"}, - {0x06290000, 0, 1, + {0x06290000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFB: SCSI bus was reset"}, {0x06290500, 0, 0, "FFFE: SCSI bus transition to single ended"}, {0x06290600, 0, 0, "FFFE: SCSI bus transition to LVD"}, - {0x06298000, 0, 1, + {0x06298000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFB: SCSI bus was reset by another initiator"}, - {0x063F0300, 0, 1, + {0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL, "3029: A device replacement has occurred"}, - {0x064C8000, 0, 1, + {0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL, "9051: IOA cache data exists for a missing or failed device"}, - {0x064C8100, 0, 1, + {0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL, "9055: Auxiliary cache IOA contains cache data needed by the primary IOA"}, - {0x06670100, 0, 1, + {0x06670100, 0, IPR_DEFAULT_LOG_LEVEL, "9025: Disk unit is not supported at its physical location"}, - {0x06670600, 0, 1, + {0x06670600, 0, IPR_DEFAULT_LOG_LEVEL, "3020: IOA detected a SCSI bus configuration error"}, - {0x06678000, 0, 1, + {0x06678000, 0, IPR_DEFAULT_LOG_LEVEL, "3150: SCSI bus configuration error"}, - {0x06678100, 0, 1, + {0x06678100, 0, IPR_DEFAULT_LOG_LEVEL, "9074: Asymmetric advanced function disk configuration"}, - {0x06678300, 0, 1, + {0x06678300, 0, IPR_DEFAULT_LOG_LEVEL, "4040: Incomplete multipath connection between IOA and enclosure"}, - {0x06678400, 0, 1, + {0x06678400, 0, IPR_DEFAULT_LOG_LEVEL, "4041: Incomplete multipath connection between enclosure and device"}, - {0x06678500, 0, 1, + {0x06678500, 0, IPR_DEFAULT_LOG_LEVEL, "9075: Incomplete multipath connection between IOA and remote IOA"}, - {0x06678600, 0, 1, + {0x06678600, 0, IPR_DEFAULT_LOG_LEVEL, "9076: Configuration error, missing remote IOA"}, - {0x06679100, 0, 1, + {0x06679100, 0, IPR_DEFAULT_LOG_LEVEL, "4050: Enclosure does not support a required multipath function"}, - {0x06690200, 0, 1, + {0x06690200, 0, IPR_DEFAULT_LOG_LEVEL, "9041: Array protection temporarily suspended"}, - {0x06698200, 0, 1, + {0x06698200, 0, IPR_DEFAULT_LOG_LEVEL, "9042: Corrupt array parity detected on specified device"}, - {0x066B0200, 0, 1, + {0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL, "9030: Array no longer protected due to missing or failed disk unit"}, - {0x066B8000, 0, 1, + {0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL, "9071: Link operational transition"}, - {0x066B8100, 0, 1, + {0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL, "9072: Link not operational transition"}, - {0x066B8200, 0, 1, + {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, "9032: Array exposed but still protected"}, - {0x066B9100, 0, 1, + {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, "4061: Multipath redundancy level got better"}, - {0x066B9200, 0, 1, + {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, "4060: Multipath redundancy level got worse"}, {0x07270000, 0, 0, "Failure due to other device"}, - {0x07278000, 0, 1, + {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL, "9008: IOA does not support functions expected by devices"}, - {0x07278100, 0, 1, + {0x07278100, 0, IPR_DEFAULT_LOG_LEVEL, "9010: Cache data associated with attached devices cannot be found"}, - {0x07278200, 0, 1, + {0x07278200, 0, IPR_DEFAULT_LOG_LEVEL, "9011: Cache data belongs to devices other than those attached"}, - {0x07278400, 0, 1, + {0x07278400, 0, IPR_DEFAULT_LOG_LEVEL, "9020: Array missing 2 or more devices with only 1 device present"}, - {0x07278500, 0, 1, + {0x07278500, 0, IPR_DEFAULT_LOG_LEVEL, "9021: Array missing 2 or more devices with 2 or more devices present"}, - {0x07278600, 0, 1, + {0x07278600, 0, IPR_DEFAULT_LOG_LEVEL, "9022: Exposed array is missing a required device"}, - {0x07278700, 0, 1, + {0x07278700, 0, IPR_DEFAULT_LOG_LEVEL, "9023: Array member(s) not at required physical locations"}, - {0x07278800, 0, 1, + {0x07278800, 0, IPR_DEFAULT_LOG_LEVEL, "9024: Array not functional due to present hardware configuration"}, - {0x07278900, 0, 1, + {0x07278900, 0, IPR_DEFAULT_LOG_LEVEL, "9026: Array not functional due to present hardware configuration"}, - {0x07278A00, 0, 1, + {0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL, "9027: Array is missing a device and parity is out of sync"}, - {0x07278B00, 0, 1, + {0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL, "9028: Maximum number of arrays already exist"}, - {0x07278C00, 0, 1, + {0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL, "9050: Required cache data cannot be located for a disk unit"}, - {0x07278D00, 0, 1, + {0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL, "9052: Cache data exists for a device that has been modified"}, - {0x07278F00, 0, 1, + {0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL, "9054: IOA resources not available due to previous problems"}, - {0x07279100, 0, 1, + {0x07279100, 0, IPR_DEFAULT_LOG_LEVEL, "9092: Disk unit requires initialization before use"}, - {0x07279200, 0, 1, + {0x07279200, 0, IPR_DEFAULT_LOG_LEVEL, "9029: Incorrect hardware configuration change has been detected"}, - {0x07279600, 0, 1, + {0x07279600, 0, IPR_DEFAULT_LOG_LEVEL, "9060: One or more disk pairs are missing from an array"}, - {0x07279700, 0, 1, + {0x07279700, 0, IPR_DEFAULT_LOG_LEVEL, "9061: One or more disks are missing from an array"}, - {0x07279800, 0, 1, + {0x07279800, 0, IPR_DEFAULT_LOG_LEVEL, "9062: One or more disks are missing from an array"}, - {0x07279900, 0, 1, + {0x07279900, 0, IPR_DEFAULT_LOG_LEVEL, "9063: Maximum number of functional arrays has been exceeded"}, {0x0B260000, 0, 0, "Aborted command, invalid descriptor"}, @@ -1607,7 +1607,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, /* Set indication we have logged an error */ ioa_cfg->errors_logged++; - if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL) + if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam) return; if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw)) hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw)); -- cgit v1.2.3 From e435340c4b583b4472dad1178029b8e3e7dafd0b Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:37 -0500 Subject: [SCSI] ipr: Disrupt device error Add entry in ipr error translation table for an error received when a device is forced into the failed state by the user. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e1d24ddd881..0251fd7272e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -360,6 +360,8 @@ struct ipr_error_table_t ipr_error_table[] = { "9072: Link not operational transition"}, {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, "9032: Array exposed but still protected"}, + {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1, + "70DD: Device forced failed by disrupt device command"}, {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, "4061: Multipath redundancy level got better"}, {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, -- cgit v1.2.3 From 0feeed823af05ca556087a89fdcf644f156f73b8 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:43 -0500 Subject: [SCSI] ipr: Return better qc_issue errors If qc_issue fails for some reason, return a better error to libata. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 0251fd7272e..aa1fb72ca23 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5128,7 +5128,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) struct ipr_ioarcb_ata_regs *regs; if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead)) - return -EIO; + return AC_ERR_SYSTEM; ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); ioarcb = &ipr_cmd->ioarcb; @@ -5173,7 +5173,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) default: WARN_ON(1); - return -1; + return AC_ERR_INVALID; } mb(); -- cgit v1.2.3 From 51b1c7e19e18e84a44277951dd5c4c4617330baa Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:50 -0500 Subject: [SCSI] ipr: Faster sg list fetch Improve overall command performance by embedding the scatterlist in the command block used by the adapter. This decreases the overall number of DMAs required for a single command. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 28 +++++++++++++++++++++++----- drivers/scsi/ipr.h | 31 ++++++++++++++++--------------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index aa1fb72ca23..5cf1002283b 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -480,12 +480,16 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) { struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr); memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); ioarcb->write_data_transfer_length = 0; ioarcb->read_data_transfer_length = 0; ioarcb->write_ioadl_len = 0; ioarcb->read_ioadl_len = 0; + ioarcb->write_ioadl_addr = + cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl)); + ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; ioasa->ioasc = 0; ioasa->residual_data_len = 0; ioasa->u.gata.status = 0; @@ -4230,6 +4234,14 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg, sglist = scsi_cmd->request_buffer; + if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) { + ioadl = ioarcb->add_data.u.ioadl; + ioarcb->write_ioadl_addr = + cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) + + offsetof(struct ipr_ioarcb, add_data)); + ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; + } + for (i = 0; i < ipr_cmd->dma_use_sg; i++) { ioadl[i].flags_and_data_len = cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i])); @@ -4260,6 +4272,11 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg, scsi_cmd->sc_data_direction); if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) { + ioadl = ioarcb->add_data.u.ioadl; + ioarcb->write_ioadl_addr = + cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) + + offsetof(struct ipr_ioarcb, add_data)); + ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; ipr_cmd->dma_use_sg = 1; ioadl[0].flags_and_data_len = cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST); @@ -4346,11 +4363,9 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) **/ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) { - struct ipr_ioarcb *ioarcb; - struct ipr_ioasa *ioasa; - - ioarcb = &ipr_cmd->ioarcb; - ioasa = &ipr_cmd->ioasa; + struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; + struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr); memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); ioarcb->write_data_transfer_length = 0; @@ -4359,6 +4374,9 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) ioarcb->read_ioadl_len = 0; ioasa->ioasc = 0; ioasa->residual_data_len = 0; + ioarcb->write_ioadl_addr = + cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl)); + ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; } /** diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 4d068887608..50e14f59f2f 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -422,9 +422,25 @@ struct ipr_ioarcb_ata_regs { u8 ctl; }__attribute__ ((packed, aligned(4))); +struct ipr_ioadl_desc { + __be32 flags_and_data_len; +#define IPR_IOADL_FLAGS_MASK 0xff000000 +#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK) +#define IPR_IOADL_DATA_LEN_MASK 0x00ffffff +#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK) +#define IPR_IOADL_FLAGS_READ 0x48000000 +#define IPR_IOADL_FLAGS_READ_LAST 0x49000000 +#define IPR_IOADL_FLAGS_WRITE 0x68000000 +#define IPR_IOADL_FLAGS_WRITE_LAST 0x69000000 +#define IPR_IOADL_FLAGS_LAST 0x01000000 + + __be32 address; +}__attribute__((packed, aligned (8))); + struct ipr_ioarcb_add_data { union { struct ipr_ioarcb_ata_regs regs; + struct ipr_ioadl_desc ioadl[5]; __be32 add_cmd_parms[10]; }u; }__attribute__ ((packed, aligned(4))); @@ -456,21 +472,6 @@ struct ipr_ioarcb { struct ipr_ioarcb_add_data add_data; }__attribute__((packed, aligned (4))); -struct ipr_ioadl_desc { - __be32 flags_and_data_len; -#define IPR_IOADL_FLAGS_MASK 0xff000000 -#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK) -#define IPR_IOADL_DATA_LEN_MASK 0x00ffffff -#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK) -#define IPR_IOADL_FLAGS_READ 0x48000000 -#define IPR_IOADL_FLAGS_READ_LAST 0x49000000 -#define IPR_IOADL_FLAGS_WRITE 0x68000000 -#define IPR_IOADL_FLAGS_WRITE_LAST 0x69000000 -#define IPR_IOADL_FLAGS_LAST 0x01000000 - - __be32 address; -}__attribute__((packed, aligned (8))); - struct ipr_ioasa_vset { __be32 failing_lba_hi; __be32 failing_lba_lo; -- cgit v1.2.3 From aa2e07b4c2addaa4ad4bd7a6ee205565e83c2a14 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 12:43:57 -0500 Subject: [SCSI] ipr: Driver version to 2.3.2 Bump driver version. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 50e14f59f2f..bc53d7cebe0 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.3.1" -#define IPR_DRIVER_DATE "(January 23, 2007)" +#define IPR_DRIVER_VERSION "2.3.2" +#define IPR_DRIVER_DATE "(March 23, 2007)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding -- cgit v1.2.3 From 18a6598f2d3bb7275dadba77df5f06bc996a77d4 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Fri, 30 Mar 2007 10:30:48 -0400 Subject: [SCSI] aacraid: [Fastboot] Panics for AACRAID driver during 'insmod' for kexec test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attached is the patch I feel will address this issue. As an added 'perk' I have also added the code to detect if the controller was previously initialized for interrupted operations by ANY operating system should the reset_devices kernel parameter not be set and we are dealing with a naïve kexec without the addition of this kernel parameter. The reset handler is also improved. Related to reset operations, but not pertinent specifically to this issue, I have also altered the handling somewhat so that we reset the adapter if we feel it is taking too long (three minutes) to start up. We have not unit tested the reset_devices flag propagation to this driver code, nor have we unit tested the check for the interrupted operations under the conditions of a naively issued kexec. We are submitting this modified driver to our Q/A department for integration testing in our current programs. I would appreciate an ACK to this patch should it resolve the issue described in this thread... Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/rx.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 3e23aa6cac0..0c71315cbf1 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -467,16 +467,19 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) if (bled) printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", dev->name, dev->id, bled); - else + else { bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (bled) + if (!bled && (var != 0x00000001)) + bled = -EINVAL; + } + if (bled && (bled != -ETIMEDOUT)) bled = aac_adapter_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (bled) + if (bled && (bled != -ETIMEDOUT)) return -EINVAL; - if (var == 0x3803000F) { /* USE_OTHER_METHOD */ + if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ rx_writel(dev, MUnit.reserved2, 3); msleep(5000); /* Delay 5 seconds */ var = 0x00000001; @@ -526,6 +529,7 @@ int _aac_rx_init(struct aac_dev *dev) { unsigned long start; unsigned long status; + int restart = 0; int instance = dev->id; const char * name = dev->name; @@ -534,15 +538,19 @@ int _aac_rx_init(struct aac_dev *dev) goto error_iounmap; } + /* Failure to reset here is an option ... */ + dev->OIMR = status = rx_readb (dev, MUnit.OIMR); + if ((((status & 0xff) != 0xff) || reset_devices) && + !aac_rx_restart_adapter(dev, 0)) + ++restart; /* * Check to see if the board panic'd while booting. */ status = rx_readl(dev, MUnit.OMRx[0]); if (status & KERNEL_PANIC) { - if ((status = aac_rx_check_health(dev)) <= 0) - goto error_iounmap; - if (aac_rx_restart_adapter(dev, status)) + if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev))) goto error_iounmap; + ++restart; } /* * Check to see if the board failed any self tests. @@ -565,11 +573,23 @@ int _aac_rx_init(struct aac_dev *dev) */ while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+startup_timeout*HZ)) { + if ((restart && + (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || + time_after(jiffies, start+HZ*startup_timeout)) { printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } + if (!restart && + ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || + time_after(jiffies, start + HZ * + ((startup_timeout > 60) + ? (startup_timeout - 60) + : (startup_timeout / 2))))) { + if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))) + start = jiffies; + ++restart; + } msleep(1); } /* -- cgit v1.2.3 From ed773e66480fdcd06732eb2aa39362599dcd67fa Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 29 Mar 2007 15:25:52 -0500 Subject: [SCSI] scsi_error.c: Add EH Start Unit retry Currently, the scsi error handler will issue a START_UNIT command if the drive indicates it needs its motor started and the allow_restart flag is set in the scsi_device. If, after the scsi error handler invokes a host adapter reset due to error recovery, a device is in a unit attention state AND also needs a START_UNIT, that device will be placed offline. The disk array devices on an ipr RAID adapter will do exactly this when in a dual initiator configuration. This patch adds a single retry to the EH initiated START_UNIT. Signed-off-by: Brian King Patch modified and Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 7a1a1bb1341..28a266c804b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -932,10 +932,12 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd) static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0}; if (scmd->device->allow_restart) { - int rtn; + int i, rtn = NEEDS_RETRY; + + for (i = 0; rtn == NEEDS_RETRY && i < 2; i++) + rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, + START_UNIT_TIMEOUT, 0); - rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, - START_UNIT_TIMEOUT, 0); if (rtn == SUCCESS) return 0; } -- cgit v1.2.3 From 144ff8bf0d84a81806bfb5979b0a6b176b1fcace Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 4 Apr 2007 15:49:54 -0400 Subject: [SCSI] aacraid: Correct SMC products in aacraid.txt Correct a spelling mistake for the SMC product names (replace 'B' with 'R') in the Documentation/scsi/aacraid.txt file. This is a follow-up to a documentation patch '[PATCH] aacraid: Add SMC and SUN products to README' submitted and accepted to scsi-misc-2.6 on March 27 2007. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- Documentation/scsi/aacraid.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt index bddc641dddb..2368e7e4a8c 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.txt @@ -38,10 +38,10 @@ Supported Cards/Chipsets 9005:0286:9005:02ac Adaptec 1800 (Typhoon44) 9005:0285:9005:02b5 Adaptec 5445 (Voodoo44) 9005:0285:15d9:02b5 SMC AOC-USAS-S4i - 9005:0285:15d9:02c9 SMC AOC-USAS-S4iB + 9005:0285:15d9:02c9 SMC AOC-USAS-S4iR 9005:0285:9005:02b6 Adaptec 5805 (Voodoo80) 9005:0285:15d9:02b6 SMC AOC-USAS-S8i - 9005:0285:15d9:02ca SMC AOC-USAS-S8iB + 9005:0285:15d9:02ca SMC AOC-USAS-S8iR 9005:0285:9005:02b7 Adaptec 5085 (Voodoo08) 9005:0285:9005:02bb Adaptec 3405 (Marauder40LP) 9005:0285:9005:02bc Adaptec 3805 (Marauder80LP) -- cgit v1.2.3 From 4def7fa11208f779f22e6ba7344370b0220d3350 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Fri, 13 Apr 2007 08:35:25 -0400 Subject: [SCSI] aacraid: fix aacraid not finding device Thanks for the help from Steve Fox and Duane Cox investigating this issue, I'd like to report that we found the problem. The issue is with the patch Steve Fox isolated below, by not accommodating older adapters properly and issuing a command they do not support when retrieving storage parameters about the arrays. This simple patch resolves the problem (and more accurately mimics the logic of the original code before the patch). Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 31ac9f56cd1..1e82c69b36b 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -503,8 +503,7 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) dresp = (struct aac_mount *) fib_data(fibptr); dresp->mnt[0].capacityhigh = 0; if ((le32_to_cpu(dresp->status) != ST_OK) || - ((le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) == FSCS_HIDDEN))) + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) return _aac_probe_container2(context, fibptr); scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; -- cgit v1.2.3 From ad1331a792f9f253bef362de9b6872c6b8f88c0c Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Sat, 7 Apr 2007 18:10:00 +0900 Subject: [SCSI] tgt: fix rdma transfer bugs - ibmstgt hits the max rdma transfer size (128k). - libsrp returns a rdma transfer error properly. Signed-off-by: Bastian Blank Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvstgt.c | 18 +++++++++--------- drivers/scsi/libsrp.c | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index a7fbd10817a..84363c18162 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -35,7 +35,7 @@ #include "ibmvscsi.h" #define INITIAL_SRP_LIMIT 16 -#define DEFAULT_MAX_SECTORS 512 +#define DEFAULT_MAX_SECTORS 256 #define TGT_NAME "ibmvstgt" @@ -248,8 +248,8 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, md[i].va + mdone); if (err != H_SUCCESS) { - eprintk("rdma error %d %d\n", dir, slen); - goto out; + eprintk("rdma error %d %d %ld\n", dir, slen, err); + return -EIO; } mlen -= slen; @@ -265,14 +265,13 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, if (sidx > nsg) { eprintk("out of sg %p %d %d\n", iue, sidx, nsg); - goto out; + return -EIO; } } }; rest -= mlen; } -out: return 0; } @@ -282,18 +281,19 @@ static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, unsigned long flags; struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; struct srp_target *target = iue->target; + int err = 0; dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], cmd->usg_sg); if (sc->use_sg) - srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); + err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); spin_lock_irqsave(&target->lock, flags); list_del(&iue->ilist); spin_unlock_irqrestore(&target->lock, flags); - if (sc->result != SAM_STAT_GOOD) { + if (err|| sc->result != SAM_STAT_GOOD) { eprintk("operation failed %p %d %x\n", iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); send_rsp(iue, sc, HARDWARE_ERROR, 0x00); @@ -493,7 +493,8 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target) { struct vio_port *vport = target_to_port(target); struct iu_entry *iue; - long err, done; + long err; + int done = 1; iue = srp_iu_get(target); if (!iue) { @@ -508,7 +509,6 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target) if (err != H_SUCCESS) { eprintk("%ld transferring data error %p\n", err, iue); - done = 1; goto out; } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 89403b00e04..37a0f4dd618 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -225,8 +225,7 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, struct srp_direct_buf *md = NULL; struct scatterlist dummy, *sg = NULL; dma_addr_t token = 0; - long err; - unsigned int done = 0; + int err = 0; int nmd, nsg = 0, len; if (dma_map || ext_desc) { @@ -258,8 +257,8 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, sg_dma_address(&dummy) = token; err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE, id->table_desc.len); - if (err < 0) { - eprintk("Error copying indirect table %ld\n", err); + if (err) { + eprintk("Error copying indirect table %d\n", err); goto free_mem; } } else { @@ -272,6 +271,7 @@ rdma: nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL); if (!nsg) { eprintk("fail to map %p %d\n", iue, sc->use_sg); + err = -EIO; goto free_mem; } len = min(sc->request_bufflen, id->len); @@ -287,7 +287,7 @@ free_mem: if (token && dma_map) dma_free_coherent(iue->target->dev, id->table_desc.len, md, token); - return done; + return err; } static int data_out_desc_size(struct srp_cmd *cmd) @@ -352,7 +352,7 @@ int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, break; default: eprintk("Unknown format %d %x\n", dir, format); - break; + err = -EINVAL; } return err; -- cgit v1.2.3 From 1079a2d251f24a7d9e7576217f5f738bc4218337 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Tue, 10 Apr 2007 08:53:08 -0500 Subject: [SCSI] BusLogic: stop using check_region I got so sick of seing the check_region warnings from BusLogic.c I actually fixed it properly. Never use check region, reserve it before the probe with request region instead and check the error result; free region if setup fails. Should be functionally identical to the original except for fixing the potential race. Signed-off-by: Zachary Amsden Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/BusLogic.c | 73 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index e874b894487..96f4cab0761 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -579,17 +579,17 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt /* Append the list of standard BusLogic MultiMaster ISA I/O Addresses. */ - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330) BusLogic_AppendProbeAddressISA(0x330); - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334) BusLogic_AppendProbeAddressISA(0x334); - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230) BusLogic_AppendProbeAddressISA(0x230); - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234) BusLogic_AppendProbeAddressISA(0x234); - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130) BusLogic_AppendProbeAddressISA(0x130); - if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) + if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134) BusLogic_AppendProbeAddressISA(0x134); } @@ -795,7 +795,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd host adapters are probed. */ if (!BusLogic_ProbeOptions.NoProbeISA) - if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) { + if (PrimaryProbeInfo->IO_Address == 0 && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe330)) { PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; PrimaryProbeInfo->IO_Address = 0x330; @@ -805,15 +807,25 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd omitting the Primary I/O Address which has already been handled. */ if (!BusLogic_ProbeOptions.NoProbeISA) { - if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)) + if (!StandardAddressSeen[1] && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe334)) BusLogic_AppendProbeAddressISA(0x334); - if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)) + if (!StandardAddressSeen[2] && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe230)) BusLogic_AppendProbeAddressISA(0x230); - if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)) + if (!StandardAddressSeen[3] && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe234)) BusLogic_AppendProbeAddressISA(0x234); - if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)) + if (!StandardAddressSeen[4] && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe130)) BusLogic_AppendProbeAddressISA(0x130); - if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)) + if (!StandardAddressSeen[5] && + (!BusLogic_ProbeOptions.LimitedProbeISA || + BusLogic_ProbeOptions.Probe134)) BusLogic_AppendProbeAddressISA(0x134); } /* @@ -2220,22 +2232,35 @@ static int __init BusLogic_init(void) HostAdapter->PCI_Device = ProbeInfo->PCI_Device; HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; + + /* + Make sure region is free prior to probing. + */ + if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, + "BusLogic")) + continue; /* Probe the Host Adapter. If unsuccessful, abort further initialization. */ - if (!BusLogic_ProbeHostAdapter(HostAdapter)) + if (!BusLogic_ProbeHostAdapter(HostAdapter)) { + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); continue; + } /* Hard Reset the Host Adapter. If unsuccessful, abort further initialization. */ - if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) + if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) { + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); continue; + } /* Check the Host Adapter. If unsuccessful, abort further initialization. */ - if (!BusLogic_CheckHostAdapter(HostAdapter)) + if (!BusLogic_CheckHostAdapter(HostAdapter)) { + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); continue; + } /* Initialize the Driver Options field if provided. */ @@ -2246,16 +2271,6 @@ static int __init BusLogic_init(void) and Electronic Mail Address. */ BusLogic_AnnounceDriver(HostAdapter); - /* - Register usage of the I/O Address range. From this point onward, any - failure will be assumed to be due to a problem with the Host Adapter, - rather than due to having mistakenly identified this port as belonging - to a BusLogic Host Adapter. The I/O Address range will not be - released, thereby preventing it from being incorrectly identified as - any other type of Host Adapter. - */ - if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic")) - continue; /* Register the SCSI Host structure. */ @@ -2280,6 +2295,12 @@ static int __init BusLogic_init(void) Acquire the System Resources necessary to use the Host Adapter, then Create the Initial CCBs, Initialize the Host Adapter, and finally perform Target Device Inquiry. + + From this point onward, any failure will be assumed to be due to a + problem with the Host Adapter, rather than due to having mistakenly + identified this port as belonging to a BusLogic Host Adapter. The + I/O Address range will not be released, thereby preventing it from + being incorrectly identified as any other type of Host Adapter. */ if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && BusLogic_ReportHostAdapterConfiguration(HostAdapter) && @@ -3598,6 +3619,7 @@ static void __exit BusLogic_exit(void) __setup("BusLogic=", BusLogic_Setup); +#ifdef MODULE static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -3607,6 +3629,7 @@ static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { } }; +#endif MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl); module_init(BusLogic_init); -- cgit v1.2.3 From 44ec95425c1d9dce6e4638c29e4362cfb44814e7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 Feb 2007 11:01:57 -0500 Subject: [SCSI] sg: cap reserved_size values at max_sectors This patch (as857) modifies the SG_GET_RESERVED_SIZE and SG_SET_RESERVED_SIZE ioctls in the sg driver, capping the values at the device's request_queue's max_sectors value. This will permit cdrecord to obtain a legal value for the maximum transfer length, fixing Bugzilla #7026. The patch also caps the initial reserved_size value. There's no reason to have a reserved buffer larger than max_sectors, since it would be impossible to use the extra space. The corresponding ioctls in the block layer are modified similarly, and the initial value for the reserved_size is set as large as possible. This will effectively make it default to max_sectors. Note that the actual value is meaningless anyway, since block devices don't have a reserved buffer. Finally, the BLKSECTGET ioctl is added to sg, so that there will be a uniform way for users to determine the actual max_sectors value for any raw SCSI transport. Signed-off-by: Alan Stern Acked-by: Jens Axboe Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- block/ll_rw_blk.c | 2 ++ block/scsi_ioctl.c | 4 +++- drivers/scsi/sg.c | 13 +++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 38c293b987b..cf8752abd61 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1925,6 +1925,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); + q->sg_reserved_size = INT_MAX; + /* * all done */ diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 65c6a3cba6d..e83f1dbf7c2 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -78,7 +78,9 @@ static int sg_set_timeout(request_queue_t *q, int __user *p) static int sg_get_reserved_size(request_queue_t *q, int __user *p) { - return put_user(q->sg_reserved_size, p); + unsigned val = min(q->sg_reserved_size, q->max_sectors << 9); + + return put_user(val, p); } static int sg_set_reserved_size(request_queue_t *q, int __user *p) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 81e3bc7b02a..570977cf9ef 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -917,6 +917,8 @@ sg_ioctl(struct inode *inode, struct file *filp, return result; if (val < 0) return -EINVAL; + val = min_t(int, val, + sdp->device->request_queue->max_sectors * 512); if (val != sfp->reserve.bufflen) { if (sg_res_in_use(sfp) || sfp->mmap_called) return -EBUSY; @@ -925,7 +927,8 @@ sg_ioctl(struct inode *inode, struct file *filp, } return 0; case SG_GET_RESERVED_SIZE: - val = (int) sfp->reserve.bufflen; + val = min_t(int, sfp->reserve.bufflen, + sdp->device->request_queue->max_sectors * 512); return put_user(val, ip); case SG_SET_COMMAND_Q: result = get_user(val, ip); @@ -1061,6 +1064,9 @@ sg_ioctl(struct inode *inode, struct file *filp, if (sdp->detached) return -ENODEV; return scsi_ioctl(sdp->device, cmd_in, p); + case BLKSECTGET: + return put_user(sdp->device->request_queue->max_sectors * 512, + ip); default: if (read_only) return -EPERM; /* don't know so take safe approach */ @@ -2339,6 +2345,7 @@ sg_add_sfp(Sg_device * sdp, int dev) { Sg_fd *sfp; unsigned long iflags; + int bufflen; sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN); if (!sfp) @@ -2369,7 +2376,9 @@ sg_add_sfp(Sg_device * sdp, int dev) if (unlikely(sg_big_buff != def_reserved_size)) sg_big_buff = def_reserved_size; - sg_build_reserve(sfp, sg_big_buff); + bufflen = min_t(int, sg_big_buff, + sdp->device->request_queue->max_sectors * 512); + sg_build_reserve(sfp, bufflen); SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", sfp->reserve.bufflen, sfp->reserve.k_use_sg)); return sfp; -- cgit v1.2.3 From d7b8bcb0a0819315a51cae620ff7ae0c1704c069 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Fri, 27 Oct 2006 16:02:37 +0400 Subject: [SCSI] modalias for scsi devices The following patch adds support for sysfs/uevent modalias attribute for scsi devices (like disks, tapes, cdroms etc), based on whatever current sd.c, sr.c, st.c and osst.c drivers supports. The modalias format is like this: scsi:type-0x04 (for TYPE_WORM, handled by sr.c now). Several comments. o This hexadecimal type value is because all TYPE_XXX constants in include/scsi/scsi.h are given in hex, but __stringify() will not convert them to decimal (so it will NOT be scsi:type-4). Since it does not really matter in which format it is, while both modalias in module and modalias attribute match each other, I descided to go for that 0x%02x format (and added a comment in include/scsi/scsi.h to keep them that way), instead of changing them all to decimal. o There was no .uevent routine for SCSI bus. It might be a good idea to add some more ueven environment variables in there. o osst.c driver handles tapes too, like st.c, but only SOME tapes. With this setup, hotplug scripts (or whatever is used by the user) will try to load both st and osst modules for all SCSI tapes found, because both modules have scsi:type-0x01 alias). It is not harmful, but one extra module is no good either. It is possible to solve this, by exporting more info in modalias attribute, including vendor and device identification strings, so that modalias becomes something like scsi:type-0x12:vendor-Adaptec LTD:device-OnStream Tape Drive and having that, match for all 3 attributes, not only device type. But oh well, vendor and device strings may be large, and they do contain spaces and whatnot. So I left them for now, awaiting for comments first. Signed-off-by: Michael Tokarev Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 1 + drivers/scsi/scsi_sysfs.c | 23 +++++++++++++++++++++++ drivers/scsi/sd.c | 3 +++ drivers/scsi/sr.c | 2 ++ drivers/scsi/st.c | 1 + include/scsi/scsi.h | 1 + include/scsi/scsi_device.h | 5 +++++ 7 files changed, 36 insertions(+) diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index a967fadb743..08060fb478b 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -87,6 +87,7 @@ MODULE_AUTHOR("Willem Riede"); MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE); module_param(max_dev, int, 0444); MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)"); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 96db51c40ef..5326f5cbeae 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -276,6 +276,19 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } +static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct scsi_device *sdev = to_scsi_device(dev); + int i = 0; + int length = 0; + + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); + envp[i] = NULL; + return 0; +} + static int scsi_bus_suspend(struct device * dev, pm_message_t state) { struct device_driver *drv = dev->driver; @@ -331,6 +344,7 @@ static int scsi_bus_resume(struct device * dev) struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, + .uevent = scsi_bus_uevent, .suspend = scsi_bus_suspend, .resume = scsi_bus_resume, }; @@ -558,6 +572,14 @@ show_sdev_iostat(iorequest_cnt); show_sdev_iostat(iodone_cnt); show_sdev_iostat(ioerr_cnt); +static ssize_t +sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev; + sdev = to_scsi_device(dev); + return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type); +} +static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); /* Default template for device attributes. May NOT be modified */ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { @@ -577,6 +599,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { &dev_attr_iorequest_cnt, &dev_attr_iodone_cnt, &dev_attr_ioerr_cnt, + &dev_attr_modalias, NULL }; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b044dcf7342..00e46662296 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -82,6 +82,9 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); +MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); +MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); static DEFINE_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 1857d68e719..f9a52af7f5b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -62,6 +62,8 @@ MODULE_DESCRIPTION("SCSI cdrom (sr) driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_ROM); +MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); #define SR_DISKS 256 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 98d8411bbcc..55bfeccf68a 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -89,6 +89,7 @@ MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI tape (st) driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE); /* Set 'perm' (4th argument) to 0 to disable module_param's definition * of sysfs parameters (which module_param doesn't yet support). diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 5c0e9791441..9f8f80ab0c8 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -203,6 +203,7 @@ static inline int scsi_status_is_good(int status) /* * DEVICE TYPES + * Please keep them in 0x%02x format for $MODALIAS to work */ #define TYPE_DISK 0x00 diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index b05cd3b09e6..2f3c5b8b1d6 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -358,4 +358,9 @@ static inline int scsi_device_qas(struct scsi_device *sdev) return 0; return sdev->inquiry[56] & 0x02; } + +#define MODULE_ALIAS_SCSI_DEVICE(type) \ + MODULE_ALIAS("scsi:t-" __stringify(type) "*") +#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x" + #endif /* _SCSI_SCSI_DEVICE_H */ -- cgit v1.2.3 From 4e08df3f91837656c36712f559d5ce8d80852760 Mon Sep 17 00:00:00 2001 From: David Miller Date: Mon, 16 Apr 2007 12:37:43 -0700 Subject: [SCSI] qla2xxx: fix regression on sparc64 Some sparc64 boxes don't have a valid NVRAM (from which the driver takes its WWPN) try to extract this from open firmware instead and if that fails, fall back to a default, which would be invalid if more than one machine on the same SAN does this, since two machines with the same WWPN would be illegal, so warn when taking this potentially invalid default. Tested on SunBlade-1000: Acked-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 177 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 98c01cd5e1a..3e296ab845b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -11,6 +11,11 @@ #include "qla_devtbl.h" +#ifdef CONFIG_SPARC +#include +#include +#endif + /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */ #ifndef EXT_IS_LUN_BIT_SET #define EXT_IS_LUN_BIT_SET(P,L) \ @@ -88,12 +93,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); - rval = ha->isp_ops.nvram_config(ha); - if (rval) { - DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n", - ha->host_no)); - return rval; - } + ha->isp_ops.nvram_config(ha); if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ @@ -1393,6 +1393,28 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de } } +/* On sparc systems, obtain port and node WWN from firmware + * properties. + */ +static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv) +{ +#ifdef CONFIG_SPARC + struct pci_dev *pdev = ha->pdev; + struct pcidev_cookie *pcp = pdev->sysdata; + struct device_node *dp = pcp->prom_node; + u8 *val; + int len; + + val = of_get_property(dp, "port-wwn", &len); + if (val && len >= WWN_SIZE) + memcpy(nv->port_name, val, WWN_SIZE); + + val = of_get_property(dp, "node-wwn", &len); + if (val && len >= WWN_SIZE) + memcpy(nv->node_name, val, WWN_SIZE); +#endif +} + /* * NVRAM configuration for ISP 2xxx * @@ -1409,6 +1431,7 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de int qla2x00_nvram_config(scsi_qla_host_t *ha) { + int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; @@ -1417,6 +1440,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) uint8_t *ptr = (uint8_t *)ha->request_ring; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + rval = QLA_SUCCESS; + /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(nvram_t); ha->nvram_base = 0; @@ -1440,7 +1465,57 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); - return QLA_FUNCTION_FAILED; + qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " + "invalid -- WWPN) defaults.\n"); + + /* + * Set default initialization control block. + */ + memset(nv, 0, ha->nvram_size); + nv->parameter_block_version = ICB_VERSION; + + if (IS_QLA23XX(ha)) { + nv->firmware_options[0] = BIT_2 | BIT_1; + nv->firmware_options[1] = BIT_7 | BIT_5; + nv->add_firmware_options[0] = BIT_5; + nv->add_firmware_options[1] = BIT_5 | BIT_4; + nv->frame_payload_size = __constant_cpu_to_le16(2048); + nv->special_options[1] = BIT_7; + } else if (IS_QLA2200(ha)) { + nv->firmware_options[0] = BIT_2 | BIT_1; + nv->firmware_options[1] = BIT_7 | BIT_5; + nv->add_firmware_options[0] = BIT_5; + nv->add_firmware_options[1] = BIT_5 | BIT_4; + nv->frame_payload_size = __constant_cpu_to_le16(1024); + } else if (IS_QLA2100(ha)) { + nv->firmware_options[0] = BIT_3 | BIT_1; + nv->firmware_options[1] = BIT_5; + nv->frame_payload_size = __constant_cpu_to_le16(1024); + } + + nv->max_iocb_allocation = __constant_cpu_to_le16(256); + nv->execution_throttle = __constant_cpu_to_le16(16); + nv->retry_count = 8; + nv->retry_delay = 1; + + nv->port_name[0] = 33; + nv->port_name[3] = 224; + nv->port_name[4] = 139; + + qla2xxx_nvram_wwn_from_ofw(ha, nv); + + nv->login_timeout = 4; + + /* + * Set default host adapter parameters + */ + nv->host_p[1] = BIT_2; + nv->reset_delay = 5; + nv->port_down_retry_count = 8; + nv->max_luns_per_target = __constant_cpu_to_le16(8); + nv->link_down_timeout = 60; + + rval = 1; } #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) @@ -1653,7 +1728,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) } } - return QLA_SUCCESS; + if (rval) { + DEBUG2_3(printk(KERN_WARNING + "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); + } + return (rval); } static void @@ -3071,9 +3150,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_ops.get_flash_version(ha, ha->request_ring); - rval = ha->isp_ops.nvram_config(ha); - if (rval) - goto isp_abort_retry; + ha->isp_ops.nvram_config(ha); if (!qla2x00_restart_isp(ha)) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -3103,7 +3180,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } } } else { /* failed the ISP abort */ -isp_abort_retry: ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { if (ha->isp_abort_cnt == 0) { @@ -3290,9 +3366,32 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); } +/* On sparc systems, obtain port and node WWN from firmware + * properties. + */ +static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv) +{ +#ifdef CONFIG_SPARC + struct pci_dev *pdev = ha->pdev; + struct pcidev_cookie *pcp = pdev->sysdata; + struct device_node *dp = pcp->prom_node; + u8 *val; + int len; + + val = of_get_property(dp, "port-wwn", &len); + if (val && len >= WWN_SIZE) + memcpy(nv->port_name, val, WWN_SIZE); + + val = of_get_property(dp, "node-wwn", &len); + if (val && len >= WWN_SIZE) + memcpy(nv->node_name, val, WWN_SIZE); +#endif +} + int qla24xx_nvram_config(scsi_qla_host_t *ha) { + int rval; struct init_cb_24xx *icb; struct nvram_24xx *nv; uint32_t *dptr; @@ -3300,6 +3399,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) uint32_t chksum; uint16_t cnt; + rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; nv = (struct nvram_24xx *)ha->request_ring; @@ -3332,7 +3432,52 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], le16_to_cpu(nv->nvram_version)); - return QLA_FUNCTION_FAILED; + qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " + "invalid -- WWPN) defaults.\n"); + + /* + * Set default initialization control block. + */ + memset(nv, 0, ha->nvram_size); + nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); + nv->version = __constant_cpu_to_le16(ICB_VERSION); + nv->frame_payload_size = __constant_cpu_to_le16(2048); + nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); + nv->exchange_count = __constant_cpu_to_le16(0); + nv->hard_address = __constant_cpu_to_le16(124); + nv->port_name[0] = 0x21; + nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); + nv->port_name[2] = 0x00; + nv->port_name[3] = 0xe0; + nv->port_name[4] = 0x8b; + nv->port_name[5] = 0x1c; + nv->port_name[6] = 0x55; + nv->port_name[7] = 0x86; + nv->node_name[0] = 0x20; + nv->node_name[1] = 0x00; + nv->node_name[2] = 0x00; + nv->node_name[3] = 0xe0; + nv->node_name[4] = 0x8b; + nv->node_name[5] = 0x1c; + nv->node_name[6] = 0x55; + nv->node_name[7] = 0x86; + qla24xx_nvram_wwn_from_ofw(ha, nv); + nv->login_retry_count = __constant_cpu_to_le16(8); + nv->interrupt_delay_timer = __constant_cpu_to_le16(0); + nv->login_timeout = __constant_cpu_to_le16(0); + nv->firmware_options_1 = + __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); + nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); + nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); + nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); + nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); + nv->efi_parameters = __constant_cpu_to_le32(0); + nv->reset_delay = 5; + nv->max_luns_per_target = __constant_cpu_to_le16(128); + nv->port_down_retry_count = __constant_cpu_to_le16(30); + nv->link_down_timeout = __constant_cpu_to_le16(30); + + rval = 1; } /* Reset Initialization control block */ @@ -3479,7 +3624,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->flags.process_response_queue = 1; } - return QLA_SUCCESS; + if (rval) { + DEBUG2_3(printk(KERN_WARNING + "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); + } + return (rval); } static int -- cgit v1.2.3 From 7297824581755593535fc97d2c8b6c47e2dc2db6 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Wed, 7 Feb 2007 16:51:40 -0700 Subject: [SCSI] fusion: fix domain validation loops After host reset, the device are programmed to default asyn narrow nego. We need to reprogram the parameter back to previous values. If the host reset is called as a result of spi_dv_device() commands timing out, its possible to get into an infinite loop of dv to host reset. This will prevent that case, as we merely program old values. If host reset is called outside context of domain validation, then we can call spi_dv_device. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptspi.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e3a39272aad..d25d3be8fcd 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -994,6 +994,7 @@ typedef struct _MPT_SCSI_HOST { int scandv_wait_done; long last_queue_full; u16 tm_iocstatus; + u16 spi_pending; struct list_head target_reset_list; } MPT_SCSI_HOST; diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index b08416f84ed..d75f7ffbb02 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -676,7 +676,9 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, return; } + hd->spi_pending |= (1 << sdev->id); spi_dv_device(sdev); + hd->spi_pending &= ~(1 << sdev->id); if (sdev->channel == 1 && mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0) @@ -1202,11 +1204,27 @@ mptspi_dv_renegotiate_work(struct work_struct *work) container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct scsi_device *sdev; + struct scsi_target *starget; + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; kfree(wqw); - shost_for_each_device(sdev, hd->ioc->sh) - mptspi_dv_device(hd, sdev); + if (hd->spi_pending) { + shost_for_each_device(sdev, hd->ioc->sh) { + if (hd->spi_pending & (1 << sdev->id)) + continue; + starget = scsi_target(sdev); + nego = mptspi_getRP(starget); + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + mptspi_write_spi_device_pg1(starget, &pg1); + } + } else { + shost_for_each_device(sdev, hd->ioc->sh) + mptspi_dv_device(hd, sdev); + } } static void @@ -1452,6 +1470,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) init_waitqueue_head(&hd->scandv_waitq); hd->scandv_wait_done = 0; hd->last_queue_full = 0; + hd->spi_pending = 0; /* Some versions of the firmware don't support page 0; without * that we can't get the parameters */ -- cgit v1.2.3