void scsi_print_driverbyte(int scsiresult) { int dr = (driver_byte(scsiresult) & DRIVER_MASK); int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4); printk("Driverbyte=0x%02x ", driver_byte(scsiresult)); printk("(%s,%s) ", (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"), (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid")); }
void scsi_show_result(int result) { int hb = host_byte(result); int db = (driver_byte(result) & DRIVER_MASK); int su = ((driver_byte(result) & SUGGEST_MASK) >> 4); 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")); }
static int do_ioctl( void ) { int retries = IOCTL_RETRIES; retry: the_result = -1; scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id, (void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done, IOCTL_TIMEOUT, (void *) sense_buffer, 0); while (the_result < 0) sleep_on(&sr_cmd_wait); if(driver_byte(the_result) != 0 && (sense_buffer[2] & 0xf) == UNIT_ATTENTION) { scsi_CDs[target].changed = 1; printk("Disc change detected.\n"); }; if (the_result && retries) { retries--; goto retry; } /* Minimal error checking. Ignore cases we know about, and report the rest. */ if(driver_byte(the_result) != 0) switch(sense_buffer[2] & 0xf) { case UNIT_ATTENTION: scsi_CDs[target].changed = 1; printk("Disc change detected.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ printk("CDROM not ready. Make sure there is a disc in the drive.\n"); break; case ILLEGAL_REQUEST: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); break; default: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", scsi_CDs[target].device->host_no, scsi_CDs[target].device->id, scsi_CDs[target].device->lun, the_result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(sense_buffer[0]), sense_error(sense_buffer[0]), sense_buffer[2] & 0xf); }; return the_result; }
static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { int r, ret = 0; /* * fill in all the output members */ hdr->status = rq->errors & 0xff; hdr->masked_status = status_byte(rq->errors); hdr->msg_status = msg_byte(rq->errors); hdr->host_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->resid = rq->resid_len; hdr->sb_len_wr = 0; if (rq->sense_len && hdr->sbp) { int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); if (!copy_to_user(hdr->sbp, rq->sense, len)) hdr->sb_len_wr = len; else ret = -EFAULT; } r = blk_rq_unmap_user(bio); if (!ret) ret = r; blk_put_request(rq); return ret; }
void scsi_show_result(int result) { int hb = host_byte(result); int db = driver_byte(result); // printk("Result: hostbyte=%s driverbyte=%s\n", // (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), ; }
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { struct scsi_request *sreq; int result; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { printk("SCSI internal ioctl failed, no memory\n"); return -ENOMEM; } sreq->sr_data_direction = DMA_NONE; scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); if (driver_byte(sreq->sr_result)) { switch (sreq->sr_sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; sreq->sr_result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", sdev->host->host_no, sdev->id, sdev->lun, sreq->sr_result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(sreq->sr_sense_buffer[0]), sense_error(sreq->sr_sense_buffer[0]), sreq->sr_sense_buffer[2] & 0xf); } } result = sreq->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); scsi_release_request(sreq); return result; }
void scsi_show_result(int result) { int hb = host_byte(result); int db = driver_byte(result); printk("Result: hostbyte=%s driverbyte=%s\n", (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid")); }
static int ioctl_internal_command(Scsi_Device *dev, char * cmd, int timeout, int retries) { int result; Scsi_Cmnd * SCpnt; SCpnt = allocate_device(NULL, dev, 1); { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries); down(&sem); } if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable){ printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; }; case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ printk(KERN_INFO "Disc change detected.\n"); break; }; default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", dev->host->host_no, dev->id, dev->lun, SCpnt->result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.rq_status = RQ_INACTIVE; if (!SCpnt->device->was_reset && SCpnt->device->scsi_request_fn) (*SCpnt->device->scsi_request_fn)(); wake_up(&SCpnt->device->device_wait); return result; }
static int ioctl_internal_command(Scsi_Device *dev, char * cmd) { int host, result; Scsi_Cmnd * SCpnt; host = dev->host_no; SCpnt = allocate_device(NULL, dev->index, 1); scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, MAX_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev != 0xfffe){ SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable){ printk("Device not ready. Make sure there is a disc in the drive.\n"); break; }; case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ printk("Disc change detected.\n"); break; }; default: /* Fall through for non-removable media */ printk("SCSI CD error: host %d id %d lun %d return code = %x\n", dev->host_no, dev->id, dev->lun, SCpnt->result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.dev = -1; /* Mark as not busy */ wake_up(&scsi_devices[SCpnt->index].device_wait); return result; }
static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength) { Scsi_Cmnd * SCpnt; int result; SCpnt = allocate_device(NULL, scsi_CDs[target].device->index, 1); scsi_do_cmd(SCpnt, (void *) sr_cmd, buffer, buflength, sr_ioctl_done, IOCTL_TIMEOUT, IOCTL_RETRIES); if (SCpnt->request.dev != 0xfffe) { SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; result = SCpnt->result; /* Minimal error checking. Ignore cases we know about, and report the rest. */ if(driver_byte(result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case UNIT_ATTENTION: scsi_CDs[target].device->changed = 1; printk("Disc change detected.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ printk("CDROM not ready. Make sure there is a disc in the drive.\n"); break; case ILLEGAL_REQUEST: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); break; default: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", scsi_CDs[target].device->host_no, scsi_CDs[target].device->id, scsi_CDs[target].device->lun, result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.dev = -1; /* Deallocate */ wake_up(&scsi_devices[SCpnt->index].device_wait); /* Wake up a process waiting for device*/ return result; }
static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr) { struct bsg_job *job = blk_mq_rq_to_pdu(rq); int ret = 0; /* * The assignments below don't make much sense, but are kept for * bug by bug backwards compatibility: */ hdr->device_status = job->result & 0xff; hdr->transport_status = host_byte(job->result); hdr->driver_status = driver_byte(job->result); hdr->info = 0; if (hdr->device_status || hdr->transport_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->response_len = 0; if (job->result < 0) { /* we're only returning the result field in the reply */ job->reply_len = sizeof(u32); ret = job->result; } if (job->reply_len && hdr->response) { int len = min(hdr->max_response_len, job->reply_len); if (copy_to_user(uptr64(hdr->response), job->reply, len)) ret = -EFAULT; else hdr->response_len = len; } /* we assume all request payload was transferred, residual == 0 */ hdr->dout_resid = 0; if (job->bidi_rq) { unsigned int rsp_len = job->reply_payload.payload_len; if (WARN_ON(job->reply_payload_rcv_len > rsp_len)) hdr->din_resid = 0; else hdr->din_resid = rsp_len - job->reply_payload_rcv_len; } else { hdr->din_resid = 0; } return ret; }
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { int result; struct scsi_sense_hdr sshdr; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); if ((driver_byte(result) & DRIVER_SENSE) && (scsi_sense_valid(&sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else printk(KERN_INFO "ioctl_internal_command: " "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n", sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { printk(KERN_INFO "Device not ready. Make sure" " there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ sdev_printk(KERN_INFO, sdev, "ioctl_internal_command return code = %x\n", result); scsi_print_sense_hdr(" ", &sshdr); break; } } SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); return result; }
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { int result; struct scsi_sense_hdr sshdr; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, retries, NULL); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); if ((driver_byte(result) & DRIVER_SENSE) && (scsi_sense_valid(&sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else printk(KERN_INFO "ioctl_internal_command: " "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n", sshdr.asc, sshdr.ascq); break; case NOT_READY: if (sdev->removable) break; case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; result = 0; break; } default: sdev_printk(KERN_INFO, sdev, "ioctl_internal_command return code = %x\n", result); scsi_print_sense_hdr(" ", &sshdr); break; } } SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); return result; }
/** * Issue a REPORT ZONES scsi command. */ static int sd_zbc_report_zones(struct scsi_disk *sdkp, unsigned char *buf, unsigned int buflen, sector_t lba) { struct scsi_device *sdp = sdkp->device; const int timeout = sdp->request_queue->rq_timeout; struct scsi_sense_hdr sshdr; unsigned char cmd[16]; unsigned int rep_len; int result; memset(cmd, 0, 16); cmd[0] = ZBC_IN; cmd[1] = ZI_REPORT_ZONES; put_unaligned_be64(lba, &cmd[2]); put_unaligned_be32(buflen, &cmd[10]); memset(buf, 0, buflen); result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, buf, buflen, &sshdr, timeout, SD_MAX_RETRIES, NULL); if (result) { sd_printk(KERN_ERR, sdkp, "REPORT ZONES lba %llu failed with %d/%d\n", (unsigned long long)lba, host_byte(result), driver_byte(result)); return -EIO; } rep_len = get_unaligned_be32(&buf[0]); if (rep_len < 64) { sd_printk(KERN_ERR, sdkp, "REPORT ZONES report invalid length %u\n", rep_len); return -EIO; } return 0; }
void scsi_print_driverbyte(int scsiresult) { printk("Driverbyte=0x%02x ", driver_byte(scsiresult)); }
int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) { struct scsi_device *SDev; struct scsi_sense_hdr sshdr; int result, err = 0, retries = 0; struct request_sense *sense = cgc->sense; SDev = cd->device; if (!sense) { sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); if (!sense) { err = -ENOMEM; goto out; } } retry: if (!scsi_block_when_processing_errors(SDev)) { err = -ENODEV; goto out; } memset(sense, 0, sizeof(*sense)); result = scsi_execute(SDev, cgc->cmd, cgc->data_direction, cgc->buffer, cgc->buflen, (char *)sense, cgc->timeout, IOCTL_RETRIES, 0, NULL); scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr); /* Minimal error checking. Ignore cases we know about, and report the rest. */ if (driver_byte(result) != 0) { switch (sshdr.sense_key) { case UNIT_ATTENTION: SDev->changed = 1; if (!cgc->quiet) sr_printk(KERN_INFO, cd, "disc change detected.\n"); if (retries++ < 10) goto retry; err = -ENOMEDIUM; break; case NOT_READY: /* This happens if there is no disc in drive */ if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!cgc->quiet) sr_printk(KERN_INFO, cd, "CDROM not ready yet.\n"); if (retries++ < 10) { /* sleep 2 sec and try again */ ssleep(2); goto retry; } else { /* 20 secs are enough? */ err = -ENOMEDIUM; break; } } if (!cgc->quiet) sr_printk(KERN_INFO, cd, "CDROM not ready. Make sure there " "is a disc in the drive.\n"); err = -ENOMEDIUM; break; case ILLEGAL_REQUEST: err = -EIO; if (sshdr.asc == 0x20 && sshdr.ascq == 0x00) /* sense: Invalid command operation code */ err = -EDRIVE_CANT_DO_THIS; break; default: err = -EIO; } } /* Wake up a process waiting for device */ out: if (!cgc->sense) kfree(sense); cgc->stat = err; return err; }
/* * alua_rtpg - Evaluate REPORT TARGET GROUP STATES * @sdev: the device to be evaluated. * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state * * Evaluate the Target Port Group State. * Returns SCSI_DH_DEV_OFFLINED if the path is * found to be unusable. */ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition) { struct scsi_sense_hdr sense_hdr; int len, k, off, valid_states = 0; unsigned char *ucp; unsigned err, retval; unsigned long expiry, interval = 0; unsigned int tpg_desc_tbl_off; unsigned char orig_transition_tmo; if (!h->transition_tmo) expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT * HZ); else expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ); retry: retval = submit_rtpg(sdev, h); if (retval) { if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr)) { sdev_printk(KERN_INFO, sdev, "%s: rtpg failed, result %d\n", ALUA_DH_NAME, retval); if (driver_byte(retval) == DRIVER_BUSY) return SCSI_DH_DEV_TEMP_BUSY; return SCSI_DH_IO; } /* * submit_rtpg() has failed on existing arrays * when requesting extended header info, and * the array doesn't support extended headers, * even though it shouldn't according to T10. * The retry without rtpg_ext_hdr_req set * handles this. */ if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP) && sense_hdr.sense_key == ILLEGAL_REQUEST && sense_hdr.asc == 0x24 && sense_hdr.ascq == 0) { h->flags |= ALUA_RTPG_EXT_HDR_UNSUPP; goto retry; } /* * Retry on ALUA state transition or if any * UNIT ATTENTION occurred. */ if (sense_hdr.sense_key == NOT_READY && sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) err = SCSI_DH_RETRY; else if (sense_hdr.sense_key == UNIT_ATTENTION) err = SCSI_DH_RETRY; if (err == SCSI_DH_RETRY && time_before(jiffies, expiry)) { sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n", ALUA_DH_NAME); scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); goto retry; } sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n", ALUA_DH_NAME); scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); return SCSI_DH_IO; } len = get_unaligned_be32(&h->buff[0]) + 4; if (len > h->bufflen) { /* Resubmit with the correct length */ if (realloc_buffer(h, len)) { sdev_printk(KERN_WARNING, sdev, "%s: kmalloc buffer failed\n",__func__); /* Temporary failure, bypass */ return SCSI_DH_DEV_TEMP_BUSY; } goto retry; } orig_transition_tmo = h->transition_tmo; if ((h->buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR && h->buff[5] != 0) h->transition_tmo = h->buff[5]; else h->transition_tmo = ALUA_FAILOVER_TIMEOUT; if (wait_for_transition && (orig_transition_tmo != h->transition_tmo)) { sdev_printk(KERN_INFO, sdev, "%s: transition timeout set to %d seconds\n", ALUA_DH_NAME, h->transition_tmo); expiry = jiffies + h->transition_tmo * HZ; } if ((h->buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR) tpg_desc_tbl_off = 8; else tpg_desc_tbl_off = 4; for (k = tpg_desc_tbl_off, ucp = h->buff + tpg_desc_tbl_off; k < len; k += off, ucp += off) { if (h->group_id == get_unaligned_be16(&ucp[2])) { h->state = ucp[0] & 0x0f; h->pref = ucp[0] >> 7; valid_states = ucp[1]; } off = 8 + (ucp[7] * 4); }
static int ioctl_internal_command(Scsi_Device * dev, char *cmd, int timeout, int retries) { int result; Scsi_Request *SRpnt; Scsi_Device *SDpnt; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0])); if (NULL == (SRpnt = scsi_allocate_request(dev))) { printk("SCSI internal ioctl failed, no memory\n"); return -ENOMEM; } SRpnt->sr_data_direction = SCSI_DATA_NONE; scsi_wait_req(SRpnt, cmd, NULL, 0, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", SRpnt->sr_result)); if (driver_byte(SRpnt->sr_result) != 0) switch (SRpnt->sr_sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if (dev->removable && (cmd[0] != TEST_UNIT_READY)) { printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: if (dev->removable) { dev->changed = 1; SRpnt->sr_result = 0; /* This is no longer considered an error */ /* gag this error, VFS will log it anyway /axboe */ /* printk(KERN_INFO "Disc change detected.\n"); */ break; }; default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", dev->host->host_no, dev->id, dev->lun, SRpnt->sr_result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SRpnt->sr_sense_buffer[0]), sense_error(SRpnt->sr_sense_buffer[0]), SRpnt->sr_sense_buffer[2] & 0xf); }; result = SRpnt->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); SDpnt = SRpnt->sr_device; scsi_release_request(SRpnt); SRpnt = NULL; return result; }
void scsi_show_result(int result) { printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n", host_byte(result), driver_byte(result)); }
/* Convert the result to success code */ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt) { char *name = tape_name(STp); int result = SRpnt->result; u8 * sense = SRpnt->sense, scode; #if DEBUG const char *stp; #endif struct st_cmdstatus *cmdstatp; if (!result) return 0; cmdstatp = &STp->buffer->cmdstat; osst_analyze_sense(SRpnt, cmdstatp); if (cmdstatp->have_sense) scode = STp->buffer->cmdstat.sense_hdr.sense_key; else scode = 0; #if DEBUG if (debugging) { printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n", name, result, SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n", name, scode, sense[12], sense[13]); if (cmdstatp->have_sense) __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } else #endif if (cmdstatp->have_sense && ( scode != NO_SENSE && scode != RECOVERED_ERROR && /* scode != UNIT_ATTENTION && */ scode != BLANK_CHECK && scode != VOLUME_OVERFLOW && SRpnt->cmd[0] != MODE_SENSE && SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ if (cmdstatp->have_sense) { printk(KERN_WARNING "%s:W: Command with sense data:\n", name); __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } else { static int notyetprinted = 1; printk(KERN_WARNING "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n", name, result, driver_byte(result), host_byte(result)); if (notyetprinted) { notyetprinted = 0; printk(KERN_INFO "%s:I: This warning may be caused by your scsi controller,\n", name); printk(KERN_INFO "%s:I: it has been reported with some Buslogic cards.\n", name); } } } STp->pos_unknown |= STp->device->was_reset; if (cmdstatp->have_sense && scode == RECOVERED_ERROR) { STp->recover_count++; STp->recover_erreg++; #if DEBUG if (debugging) { if (SRpnt->cmd[0] == READ_6) stp = "read"; else if (SRpnt->cmd[0] == WRITE_6) stp = "write"; else stp = "ioctl"; printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp, STp->recover_count); } #endif if ((sense[2] & 0xe0) == 0) return 0; } return (-EIO); }
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { struct scsi_request *sreq; int result; struct scsi_sense_hdr sshdr; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n"); return -ENOMEM; } sreq->sr_data_direction = DMA_NONE; scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && (scsi_request_normalize_sense(sreq, &sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else printk(KERN_INFO "ioctl_internal_command: " "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n", sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { printk(KERN_INFO "Device not ready. Make sure" " there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; sreq->sr_result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ printk(KERN_INFO "ioctl_internal_command: <%d %d %d " "%d> return code = %x\n", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun, sreq->sr_result); scsi_print_req_sense(" ", sreq); break; } } result = sreq->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); scsi_release_request(sreq); return result; }
static void rw_intr (Scsi_Cmnd *SCpnt) { int result = SCpnt->result; int this_count = SCpnt->bufflen >> 9; #ifdef DEBUG printk("sd%d : rw_intr(%d, %x)\n", MINOR(SCpnt->request.dev), SCpnt->host, result); #endif /* First case : we assume that the command succeeded. One of two things will happen here. Either we will be finished, or there will be more sectors that we were unable to read last time. */ if (!result) { #ifdef DEBUG printk("sd%d : %d sectors remain.\n", MINOR(SCpnt->request.dev), SCpnt->request.nr_sectors); printk("use_sg is %d\n ",SCpnt->use_sg); #endif if (SCpnt->use_sg) { struct scatterlist * sgpnt; int i; sgpnt = (struct scatterlist *) SCpnt->buffer; for(i=0; i<SCpnt->use_sg; i++) { #ifdef DEBUG printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); #endif if (sgpnt[i].alt_address) { if (SCpnt->request.cmd == READ) memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); scsi_free(sgpnt[i].address, sgpnt[i].length); }; }; scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */ } else { if (SCpnt->buffer != SCpnt->request.buffer) { #ifdef DEBUG printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, SCpnt->bufflen); #endif if (SCpnt->request.cmd == READ) memcpy(SCpnt->request.buffer, SCpnt->buffer, SCpnt->bufflen); scsi_free(SCpnt->buffer, SCpnt->bufflen); }; }; /* * If multiple sectors are requested in one buffer, then * they will have been finished off by the first command. If * not, then we have a multi-buffer command. */ if (SCpnt->request.nr_sectors > this_count) { SCpnt->request.errors = 0; if (!SCpnt->request.bh) { #ifdef DEBUG printk("sd%d : handling page request, no buffer\n", MINOR(SCpnt->request.dev)); #endif /* The SCpnt->request.nr_sectors field is always done in 512 byte sectors, even if this really isn't the case. */ printk("sd.c: linked page request. (%x %x)", SCpnt->request.sector, this_count); panic("Aiiiiiiiiiiiieeeeeeeee"); } } end_scsi_request(SCpnt, 1, this_count); requeue_sd_request(SCpnt); return; } /* Free up any indirection buffers we allocated for DMA purposes. */ if (SCpnt->use_sg) { struct scatterlist * sgpnt; int i; sgpnt = (struct scatterlist *) SCpnt->buffer; for(i=0; i<SCpnt->use_sg; i++) { #ifdef DEBUG printk("err: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, SCpnt->bufflen); #endif if (sgpnt[i].alt_address) { scsi_free(sgpnt[i].address, sgpnt[i].length); }; }; scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */ } else { #ifdef DEBUG printk("nosgerr: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, SCpnt->bufflen); #endif if (SCpnt->buffer != SCpnt->request.buffer) scsi_free(SCpnt->buffer, SCpnt->bufflen); }; /* Now, if we were good little boys and girls, Santa left us a request sense buffer. We can extract information from this, so we can choose a block to remap, etc. */ if (driver_byte(result) != 0) { { int i; printk("Dumping sense buffer: "); for(i=0;i<10;i++) printk(" %d",SCpnt->sense_buffer[i]); };
static int sg_io(struct file *file, request_queue_t *q, struct gendisk *bd_disk, struct sg_io_hdr *hdr) { unsigned long start_time, timeout; int writing = 0, ret = 0; struct request *rq; char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char cmd[BLK_MAX_CDB]; struct bio *bio; if (hdr->interface_id != 'S') return -EINVAL; if (hdr->cmd_len > BLK_MAX_CDB) return -EINVAL; if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; if (verify_command(file, cmd)) return -EPERM; if (hdr->dxfer_len > (q->max_hw_sectors << 9)) return -EIO; if (hdr->dxfer_len) switch (hdr->dxfer_direction) { default: return -EINVAL; case SG_DXFER_TO_DEV: writing = 1; break; case SG_DXFER_TO_FROM_DEV: case SG_DXFER_FROM_DEV: break; } rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); if (!rq) return -ENOMEM; /* * fill in request structure */ rq->cmd_len = hdr->cmd_len; memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memcpy(rq->cmd, cmd, hdr->cmd_len); memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; rq->cmd_type = REQ_TYPE_BLOCK_PC; timeout = msecs_to_jiffies(hdr->timeout); rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX; if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; struct sg_iovec *iov; iov = kmalloc(size, GFP_KERNEL); if (!iov) { ret = -ENOMEM; goto out; } if (copy_from_user(iov, hdr->dxferp, size)) { kfree(iov); ret = -EFAULT; goto out; } ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, hdr->dxfer_len); kfree(iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); if (ret) goto out; bio = rq->bio; rq->retries = 0; start_time = jiffies; /* ignore return value. All information is passed back to caller * (if he doesn't check that is his problem). * N.B. a non-zero SCSI status is _not_ necessarily an error. */ blk_execute_rq(q, bd_disk, rq, 0); /* write to all output members */ hdr->status = 0xff & rq->errors; hdr->masked_status = status_byte(rq->errors); hdr->msg_status = msg_byte(rq->errors); hdr->host_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->resid = rq->data_len; hdr->duration = ((jiffies - start_time) * 1000) / HZ; hdr->sb_len_wr = 0; if (rq->sense_len && hdr->sbp) { int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); if (!copy_to_user(hdr->sbp, rq->sense, len)) hdr->sb_len_wr = len; } if (blk_rq_unmap_user(bio)) ret = -EFAULT; /* may not have succeeded, but output values written to control * structure (struct sg_io_hdr). */ out: blk_put_request(rq); return ret; }
int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) { struct scsi_request *SRpnt; struct scsi_device *SDev; struct request *req; int result, err = 0, retries = 0; SDev = cd->device; SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); if (!SRpnt) { printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); err = -ENOMEM; goto out; } SRpnt->sr_data_direction = cgc->data_direction; retry: if (!scsi_block_when_processing_errors(SDev)) { err = -ENODEV; goto out_free; } scsi_wait_req(SRpnt, cgc->cmd, cgc->buffer, cgc->buflen, cgc->timeout, IOCTL_RETRIES); req = SRpnt->sr_request; if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) { memcpy(req->buffer, SRpnt->sr_buffer, SRpnt->sr_bufflen); kfree(SRpnt->sr_buffer); SRpnt->sr_buffer = req->buffer; } result = SRpnt->sr_result; /* Minimal error checking. Ignore cases we know about, and report the rest. */ if (driver_byte(result) != 0) { switch (SRpnt->sr_sense_buffer[2] & 0xf) { case UNIT_ATTENTION: SDev->changed = 1; if (!cgc->quiet) printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name); if (retries++ < 10) goto retry; err = -ENOMEDIUM; break; case NOT_READY: /* This happens if there is no disc in drive */ if (SRpnt->sr_sense_buffer[12] == 0x04 && SRpnt->sr_sense_buffer[13] == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!cgc->quiet) printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); if (retries++ < 10) { /* sleep 2 sec and try again */ ssleep(2); goto retry; } else { /* 20 secs are enough? */ err = -ENOMEDIUM; break; } } if (!cgc->quiet) printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); #ifdef DEBUG scsi_print_req_sense("sr", SRpnt); #endif err = -ENOMEDIUM; break; case ILLEGAL_REQUEST: err = -EIO; if (SRpnt->sr_sense_buffer[12] == 0x20 && SRpnt->sr_sense_buffer[13] == 0x00) /* sense: Invalid command operation code */ err = -EDRIVE_CANT_DO_THIS; #ifdef DEBUG __scsi_print_command(cgc->cmd); scsi_print_req_sense("sr", SRpnt); #endif break; default: printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); __scsi_print_command(cgc->cmd); scsi_print_req_sense("sr", SRpnt); err = -EIO; } } if (cgc->sense) memcpy(cgc->sense, SRpnt->sr_sense_buffer, sizeof(*cgc->sense)); /* Wake up a process waiting for device */ out_free: scsi_release_request(SRpnt); SRpnt = NULL; out: cgc->stat = err; return err; }
static int ioctl_internal_command(Scsi_Device *dev, char * cmd, int timeout, int retries) { unsigned long flags; int result; Scsi_Cmnd * SCpnt; Scsi_Device * SDpnt; spin_lock_irqsave(&io_request_lock, flags); SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0])); SCpnt = scsi_allocate_device(NULL, dev, 1); { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries); spin_unlock_irqrestore(&io_request_lock, flags); down(&sem); spin_lock_irqsave(&io_request_lock, flags); SCpnt->request.sem = NULL; } SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", SCpnt->result)); if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable && (cmd[0] != TEST_UNIT_READY)){ printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; } case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ /* gag this error, VFS will log it anyway /axboe */ /* printk(KERN_INFO "Disc change detected.\n"); */ break; }; default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", dev->host->host_no, dev->id, dev->lun, SCpnt->result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); SDpnt = SCpnt->device; scsi_release_command(SCpnt); SCpnt = NULL; if (!SDpnt->was_reset && SDpnt->scsi_request_fn) (*SDpnt->scsi_request_fn)(); wake_up(&SDpnt->device_wait); spin_unlock_irqrestore(&io_request_lock, flags); return result; }