From b095518ef51c37658c58367bd19240b8a113f25c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 12 May 2005 15:45:22 -0400 Subject: [libata] ATA passthru (arbitrary ATA command execution) Authors: Brett Russ John W. Linville Andy Warner --- drivers/scsi/libata-scsi.c | 651 +++++++++++++++++++++++++++++++++++++-------- drivers/scsi/libata.h | 3 +- 2 files changed, 549 insertions(+), 105 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 4c96df060c3b..22c77a113536 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -29,10 +29,13 @@ #include "scsi.h" #include #include +#include #include #include "libata.h" +#define SECTOR_SIZE 512 + typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev); @@ -67,6 +70,148 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, return 0; } +/** + * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl + * @dev: Device to whom we are issuing command + * @arg: User provided data for issuing command + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ + +int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) +{ + int rc = 0; + u8 scsi_cmd[MAX_COMMAND_SIZE]; + u8 args[4], *argbuf = NULL; + int argsize = 0; + struct scsi_request *sreq; + + if (NULL == (void *)arg) + return -EINVAL; + + if (copy_from_user(args, arg, sizeof(args))) + return -EFAULT; + + sreq = scsi_allocate_request(scsidev, GFP_KERNEL); + if (!sreq) + return -EINTR; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + + if (args[3]) { + argsize = SECTOR_SIZE * args[3]; + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + + scsi_cmd[1] = (4 << 1); /* PIO Data-in */ + scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev, + block count in sector count field */ + sreq->sr_data_direction = DMA_FROM_DEVICE; + } else { + scsi_cmd[1] = (3 << 1); /* Non-data */ + /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + sreq->sr_data_direction = DMA_NONE; + } + + scsi_cmd[0] = ATA_16; + + scsi_cmd[4] = args[2]; + if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */ + scsi_cmd[6] = args[3]; + scsi_cmd[8] = args[1]; + scsi_cmd[10] = 0x4f; + scsi_cmd[12] = 0xc2; + } else { + scsi_cmd[6] = args[1]; + } + scsi_cmd[14] = args[0]; + + /* Good values for timeout and retries? Values below + from scsi_ioctl_send_command() for default case... */ + scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5); + + if (sreq->sr_result) { + rc = -EIO; + goto error; + } + + /* Need code to retrieve data from check condition? */ + + if ((argbuf) + && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) + rc = -EFAULT; +error: + scsi_release_request(sreq); + + if (argbuf) + kfree(argbuf); + + return rc; +} + +/** + * ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl + * @dev: Device to whom we are issuing command + * @arg: User provided data for issuing command + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ +int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) +{ + int rc = 0; + u8 scsi_cmd[MAX_COMMAND_SIZE]; + u8 args[7]; + struct scsi_request *sreq; + + if (NULL == (void *)arg) + return -EINVAL; + + if (copy_from_user(args, arg, sizeof(args))) + return -EFAULT; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + scsi_cmd[0] = ATA_16; + scsi_cmd[1] = (3 << 1); /* Non-data */ + /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + scsi_cmd[4] = args[1]; + scsi_cmd[6] = args[2]; + scsi_cmd[8] = args[3]; + scsi_cmd[10] = args[4]; + scsi_cmd[12] = args[5]; + scsi_cmd[14] = args[0]; + + sreq = scsi_allocate_request(scsidev, GFP_KERNEL); + if (!sreq) { + rc = -EINTR; + goto error; + } + + sreq->sr_data_direction = DMA_NONE; + /* Good values for timeout and retries? Values below + from scsi_ioctl_send_command() for default case... */ + scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5); + + if (sreq->sr_result) { + rc = -EIO; + goto error; + } + + /* Need code to retrieve data from check condition? */ + +error: + scsi_release_request(sreq); + return rc; +} + int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) { struct ata_port *ap; @@ -96,6 +241,16 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) return -EINVAL; return 0; + case HDIO_DRIVE_CMD: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ata_cmd_ioctl(scsidev, arg); + + case HDIO_DRIVE_TASK: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ata_task_ioctl(scsidev, arg); + default: rc = -ENOTTY; break; @@ -153,25 +308,70 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, return qc; } +/** + * ata_dump_status - user friendly display of error info + * @id: id of the port in question + * @tf: ptr to filled out taskfile + * + * Decode and dump the ATA error/status registers for the user so + * that they have some idea what really happened at the non + * make-believe layer. + * + * LOCKING: + * inherited from caller + */ +void ata_dump_status(unsigned id, struct ata_taskfile *tf) +{ + u8 stat = tf->command, err = tf->feature; + + printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat); + if (stat & ATA_BUSY) { + printk("Busy }\n"); /* Data is not valid in this case */ + } else { + if (stat & 0x40) printk("DriveReady "); + if (stat & 0x20) printk("DeviceFault "); + if (stat & 0x10) printk("SeekComplete "); + if (stat & 0x08) printk("DataRequest "); + if (stat & 0x04) printk("CorrectedError "); + if (stat & 0x02) printk("Index "); + if (stat & 0x01) printk("Error "); + printk("}\n"); + + if (err) { + printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err); + if (err & 0x04) printk("DriveStatusError "); + if (err & 0x80) { + if (err & 0x04) printk("BadCRC "); + else printk("Sector "); + } + if (err & 0x40) printk("UncorrectableError "); + if (err & 0x10) printk("SectorIdNotFound "); + if (err & 0x02) printk("TrackZeroNotFound "); + if (err & 0x01) printk("AddrMarkNotFound "); + printk("}\n"); + } + } +} + /** * ata_to_sense_error - convert ATA error to SCSI error - * @qc: Command that we are erroring out * @drv_stat: value contained in ATA status register + * @drv_err: value contained in ATA error register + * @sk: the sense key we'll fill out + * @asc: the additional sense code we'll fill out + * @ascq: the additional sense code qualifier we'll fill out * - * Converts an ATA error into a SCSI error. While we are at it - * we decode and dump the ATA error for the user so that they - * have some idea what really happened at the non make-believe - * layer. + * Converts an ATA error into a SCSI error. Fill out pointers to + * SK, ASC, and ASCQ bytes for later use in fixed or descriptor + * format sense blocks. * * LOCKING: * spin_lock_irqsave(host_set lock) */ - -void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) +void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, + u8 *ascq) { - struct scsi_cmnd *cmd = qc->scsicmd; - u8 err = 0; - unsigned char *sb = cmd->sense_buffer; + int i; /* Based on the 3ware driver translation table */ static unsigned char sense_table[][4] = { /* BBD|ECC|ID|MAR */ @@ -212,105 +412,183 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; - int i = 0; - - cmd->result = SAM_STAT_CHECK_CONDITION; /* * Is this an error we can process/parse */ - - if(drv_stat & ATA_ERR) - /* Read the err bits */ - err = ata_chk_err(qc->ap); - - /* Display the ATA level error info */ - - printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat); - if(drv_stat & 0x80) - { - printk("Busy "); - err = 0; /* Data is not valid in this case */ + if (drv_stat & ATA_BUSY) { + drv_err = 0; /* Ignore the err bits, they're invalid */ } - else { - if(drv_stat & 0x40) printk("DriveReady "); - if(drv_stat & 0x20) printk("DeviceFault "); - if(drv_stat & 0x10) printk("SeekComplete "); - if(drv_stat & 0x08) printk("DataRequest "); - if(drv_stat & 0x04) printk("CorrectedError "); - if(drv_stat & 0x02) printk("Index "); - if(drv_stat & 0x01) printk("Error "); + + if (drv_err) { + /* Look for drv_err */ + for (i = 0; sense_table[i][0] != 0xFF; i++) { + /* Look for best matches first */ + if ((sense_table[i][0] & drv_err) == + sense_table[i][0]) { + *sk = sense_table[i][1]; + *asc = sense_table[i][2]; + *ascq = sense_table[i][3]; + goto translate_done; + } + } + /* No immediate match */ + printk(KERN_WARNING "ata%u: no sense translation for " + "error 0x%02x\n", id, drv_err); } - printk("}\n"); - - if(err) - { - printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err); - if(err & 0x04) printk("DriveStatusError "); - if(err & 0x80) - { - if(err & 0x04) - printk("BadCRC "); - else - printk("Sector "); + + /* Fall back to interpreting status bits */ + for (i = 0; stat_table[i][0] != 0xFF; i++) { + if (stat_table[i][0] & drv_stat) { + *sk = stat_table[i][1]; + *asc = stat_table[i][2]; + *ascq = stat_table[i][3]; + goto translate_done; } - if(err & 0x40) printk("UncorrectableError "); - if(err & 0x10) printk("SectorIdNotFound "); - if(err & 0x02) printk("TrackZeroNotFound "); - if(err & 0x01) printk("AddrMarkNotFound "); - printk("}\n"); + } + /* No error? Undecoded? */ + printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", + id, drv_stat); + + /* For our last chance pick, use medium read error because + * it's much more common than an ATA drive telling you a write + * has failed. + */ + *sk = MEDIUM_ERROR; + *asc = 0x11; /* "unrecovered read error" */ + *ascq = 0x04; /* "auto-reallocation failed" */ + + translate_done: + printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " + "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, + *sk, *asc, *ascq); + return; +} + +/* + * ata_gen_ata_desc_sense - Generate check condition sense block. + * @qc: Command that completed. + * + * This function is specific to the ATA descriptor format sense + * block specified for the ATA pass through commands. Regardless + * of whether the command errored or not, return a sense + * block. Copy all controller registers into the sense + * block. Clear sense key, ASC & ASCQ if there is no error. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_taskfile *tf = &qc->tf; + unsigned char *sb = cmd->sense_buffer; + unsigned char *desc = sb + 8; + + memset(sb, 0, SCSI_SENSE_BUFFERSIZE); + + cmd->result = SAM_STAT_CHECK_CONDITION; + + /* + * Read the controller registers. + */ + assert(NULL != qc->ap->ops->tf_read); + qc->ap->ops->tf_read(qc->ap, tf); - /* Should we dump sector info here too ?? */ + /* + * Use ata_to_sense_error() to map status register bits + * onto sense key, asc & ascq. + */ + if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + &sb[1], &sb[2], &sb[3]); + sb[1] &= 0x0f; } + /* + * Sense data is current and format is descriptor. + */ + sb[0] = 0x72; - /* Look for err */ - while(sense_table[i][0] != 0xFF) - { - /* Look for best matches first */ - if((sense_table[i][0] & err) == sense_table[i][0]) - { - sb[0] = 0x70; - sb[2] = sense_table[i][1]; - sb[7] = 0x0a; - sb[12] = sense_table[i][2]; - sb[13] = sense_table[i][3]; - return; - } - i++; + desc[0] = 0x09; + + /* + * Set length of additional sense data. + * Since we only populate descriptor 0, the total + * length is the same (fixed) length as descriptor 0. + */ + desc[1] = sb[7] = 14; + + /* + * Copy registers into sense buffer. + */ + desc[2] = 0x00; + desc[3] = tf->feature; /* == error reg */ + desc[5] = tf->nsect; + desc[7] = tf->lbal; + desc[9] = tf->lbam; + desc[11] = tf->lbah; + desc[12] = tf->device; + desc[13] = tf->command; /* == status reg */ + + /* + * Fill in Extend bit, and the high order bytes + * if applicable. + */ + if (tf->flags & ATA_TFLAG_LBA48) { + desc[2] |= 0x01; + desc[4] = tf->hob_nsect; + desc[6] = tf->hob_lbal; + desc[8] = tf->hob_lbam; + desc[10] = tf->hob_lbah; } - /* No immediate match */ - if(err) - printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err); +} - i = 0; - /* Fall back to interpreting status bits */ - while(stat_table[i][0] != 0xFF) - { - if(stat_table[i][0] & drv_stat) - { - sb[0] = 0x70; - sb[2] = stat_table[i][1]; - sb[7] = 0x0a; - sb[12] = stat_table[i][2]; - sb[13] = stat_table[i][3]; - return; - } - i++; +/** + * ata_gen_fixed_sense - generate a SCSI fixed sense block + * @qc: Command that we are erroring out + * + * Leverage ata_to_sense_error() to give us the codes. Fit our + * LBA in here if there's room. + * + * LOCKING: + * inherited from caller + */ +void ata_gen_fixed_sense(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_taskfile *tf = &qc->tf; + unsigned char *sb = cmd->sense_buffer; + + memset(sb, 0, SCSI_SENSE_BUFFERSIZE); + + cmd->result = SAM_STAT_CHECK_CONDITION; + + /* + * Read the controller registers. + */ + assert(NULL != qc->ap->ops->tf_read); + qc->ap->ops->tf_read(qc->ap, tf); + + /* + * Use ata_to_sense_error() to map status register bits + * onto sense key, asc & ascq. + */ + if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + &sb[2], &sb[12], &sb[13]); + sb[2] &= 0x0f; } - /* No error ?? */ - printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); - /* additional-sense-code[-qualifier] */ sb[0] = 0x70; - sb[2] = MEDIUM_ERROR; - sb[7] = 0x0A; - if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - sb[12] = 0x11; /* "unrecovered read error" */ - sb[13] = 0x04; - } else { - sb[12] = 0x0C; /* "write error - */ - sb[13] = 0x02; /* auto-reallocation failed" */ + sb[7] = 0x0a; + if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) { + /* A small (28b) LBA will fit in the 32b info field */ + sb[0] |= 0x80; /* set valid bit */ + sb[3] = tf->device & 0x0f; + sb[4] = tf->lbah; + sb[5] = tf->lbam; + sb[6] = tf->lbal; } } @@ -626,11 +904,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) { struct scsi_cmnd *cmd = qc->scsicmd; + int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ); + + /* For ATA pass thru (SAT) commands, generate a sense block if + * user mandated it or if there's an error. Note that if we + * generate because the user forced us to, a check condition + * is generated and the ATA register values are returned + * whether the command completed successfully or not. If there + * was no error, SK, ASC and ASCQ will all be zero. + */ + if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) && + ((cmd->cmnd[2] & 0x20) || need_sense)) { + ata_gen_ata_desc_sense(qc); + } else { + if (!need_sense) { + cmd->result = SAM_STAT_GOOD; + } else { + /* TODO: decide which descriptor format to use + * for 48b LBA devices and call that here + * instead of the fixed desc, which is only + * good for smaller LBA (and maybe CHS?) + * devices. + */ + ata_gen_fixed_sense(qc); + } + } - if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) - ata_to_sense_error(qc, drv_stat); - else - cmd->result = SAM_STAT_GOOD; + if (need_sense) { + /* The ata_gen_..._sense routines fill in tf */ + ata_dump_status(qc->ap->id, &qc->tf); + } qc->scsidone(cmd); @@ -671,8 +974,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, return; /* data is present; dma-map it */ - if (cmd->sc_data_direction == DMA_FROM_DEVICE || - cmd->sc_data_direction == DMA_TO_DEVICE) { + if (cmd->sc_data_direction == SCSI_DATA_READ || + cmd->sc_data_direction == SCSI_DATA_WRITE) { if (unlikely(cmd->request_bufflen < 1)) { printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", ap->id, dev->devno); @@ -692,7 +995,6 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, if (xlat_func(qc, scsicmd)) goto err_out; - /* select device, send command to hardware */ if (ata_qc_issue(qc)) goto err_out; @@ -1304,7 +1606,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; int using_pio = (dev->flags & ATA_DFLAG_PIO); - int nodata = (cmd->sc_data_direction == DMA_NONE); + int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); if (!using_pio) /* Check whether ATAPI DMA is safe */ @@ -1316,7 +1618,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) qc->complete_fn = atapi_qc_complete; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - if (cmd->sc_data_direction == DMA_TO_DEVICE) { + if (cmd->sc_data_direction == SCSI_DATA_WRITE) { qc->tf.flags |= ATA_TFLAG_WRITE; DPRINTK("direction: write\n"); } @@ -1340,7 +1642,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) #ifdef ATAPI_ENABLE_DMADIR /* some SATA bridges need us to indicate data xfer direction */ - if (cmd->sc_data_direction != DMA_TO_DEVICE) + if (cmd->sc_data_direction != SCSI_DATA_WRITE) qc->tf.feature |= ATAPI_DMADIR; #endif } @@ -1393,6 +1695,143 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev) return dev; } +/* + * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value. + * @byte1: Byte 1 from pass-thru CDB. + * + * RETURNS: + * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise. + */ +static u8 +ata_scsi_map_proto(u8 byte1) +{ + switch((byte1 & 0x1e) >> 1) { + case 3: /* Non-data */ + return ATA_PROT_NODATA; + + case 6: /* DMA */ + return ATA_PROT_DMA; + + case 4: /* PIO Data-in */ + case 5: /* PIO Data-out */ + if (byte1 & 0xe0) { + return ATA_PROT_PIO_MULT; + } + return ATA_PROT_PIO; + + case 10: /* Device Reset */ + case 0: /* Hard Reset */ + case 1: /* SRST */ + case 2: /* Bus Idle */ + case 7: /* Packet */ + case 8: /* DMA Queued */ + case 9: /* Device Diagnostic */ + case 11: /* UDMA Data-in */ + case 12: /* UDMA Data-Out */ + case 13: /* FPDMA */ + default: /* Reserved */ + break; + } + + return ATA_PROT_UNKNOWN; +} + +/** + * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile + * @qc: command structure to be initialized + * @cmd: SCSI command to convert + * + * Handles either 12 or 16-byte versions of the CDB. + * + * RETURNS: + * Zero on success, non-zero on failure. + */ +static unsigned int +ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &(qc->tf); + struct scsi_cmnd *cmd = qc->scsicmd; + + if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) + return 1; + + /* + * 12 and 16 byte CDBs use different offsets to + * provide the various register values. + */ + if (scsicmd[0] == ATA_16) { + /* + * 16-byte CDB - may contain extended commands. + * + * If that is the case, copy the upper byte register values. + */ + if (scsicmd[1] & 0x01) { + tf->hob_feature = scsicmd[3]; + tf->hob_nsect = scsicmd[5]; + tf->hob_lbal = scsicmd[7]; + tf->hob_lbam = scsicmd[9]; + tf->hob_lbah = scsicmd[11]; + tf->flags |= ATA_TFLAG_LBA48; + } else + tf->flags &= ~ATA_TFLAG_LBA48; + + /* + * Always copy low byte, device and command registers. + */ + tf->feature = scsicmd[4]; + tf->nsect = scsicmd[6]; + tf->lbal = scsicmd[8]; + tf->lbam = scsicmd[10]; + tf->lbah = scsicmd[12]; + tf->device = scsicmd[13]; + tf->command = scsicmd[14]; + } else { + /* + * 12-byte CDB - incapable of extended commands. + */ + tf->flags &= ~ATA_TFLAG_LBA48; + + tf->feature = scsicmd[3]; + tf->nsect = scsicmd[4]; + tf->lbal = scsicmd[5]; + tf->lbam = scsicmd[6]; + tf->lbah = scsicmd[7]; + tf->device = scsicmd[8]; + tf->command = scsicmd[9]; + } + + /* + * Filter SET_FEATURES - XFER MODE command -- otherwise, + * SET_FEATURES - XFER MODE must be preceded/succeeded + * by an update to hardware-specific registers for each + * controller (i.e. the reason for ->set_piomode(), + * ->set_dmamode(), and ->post_set_mode() hooks). + */ + if ((tf->command == ATA_CMD_SET_FEATURES) + && (tf->feature == SETFEATURES_XFER)) + return 1; + + /* + * Set flags so that all registers will be written, + * and pass on write indication (used for PIO/DMA + * setup.) + */ + tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE); + + if (cmd->sc_data_direction == SCSI_DATA_WRITE) + tf->flags |= ATA_TFLAG_WRITE; + + /* + * Set transfer length. + * + * TODO: find out if we need to do more here to + * cover scatter/gather case. + */ + qc->nsect = cmd->bufflen / ATA_SECT_SIZE; + + return 0; +} + /** * ata_get_xlat_func - check if SCSI to ATA translation is possible * @dev: ATA device @@ -1425,6 +1864,10 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) case VERIFY: case VERIFY_16: return ata_scsi_verify_xlat; + + case ATA_12: + case ATA_16: + return ata_scsi_pass_thru; } return NULL; @@ -1581,7 +2024,7 @@ void ata_scsi_simulate(u16 *id, ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns); break; - /* mandantory commands we haven't implemented yet */ + /* mandatory commands we haven't implemented yet */ case REQUEST_SENSE: /* all other commands */ diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 6518226b8f87..c595f5f58c16 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -44,10 +44,11 @@ extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); +extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); +extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); /* libata-scsi.c */ -extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat); extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); -- cgit From 0274aa2506fd2fe89a58dd6cd64d3b3f7b976af8 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 22 Jun 2005 13:50:56 -0400 Subject: libata: Update 'passthru' branch for latest libata --- drivers/scsi/libata-scsi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index cdc0a10a606c..c1cf5e038967 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -582,7 +582,11 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) sb[0] = 0x70; sb[7] = 0x0a; + +#if 0 /* when C/H/S support is merged */ if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) { +#endif + if (!(tf->flags & ATA_TFLAG_LBA48)) { /* A small (28b) LBA will fit in the 32b info field */ sb[0] |= 0x80; /* set valid bit */ sb[3] = tf->device & 0x0f; @@ -977,8 +981,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, return; /* data is present; dma-map it */ - if (cmd->sc_data_direction == SCSI_DATA_READ || - cmd->sc_data_direction == SCSI_DATA_WRITE) { + if (cmd->sc_data_direction == DMA_FROM_DEVICE || + cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", ap->id, dev->devno); @@ -1609,7 +1613,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; int using_pio = (dev->flags & ATA_DFLAG_PIO); - int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); + int nodata = (cmd->sc_data_direction == DMA_NONE); if (!using_pio) /* Check whether ATAPI DMA is safe */ @@ -1621,7 +1625,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) qc->complete_fn = atapi_qc_complete; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - if (cmd->sc_data_direction == SCSI_DATA_WRITE) { + if (cmd->sc_data_direction == DMA_TO_DEVICE) { qc->tf.flags |= ATA_TFLAG_WRITE; DPRINTK("direction: write\n"); } @@ -1645,7 +1649,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) #ifdef ATAPI_ENABLE_DMADIR /* some SATA bridges need us to indicate data xfer direction */ - if (cmd->sc_data_direction != SCSI_DATA_WRITE) + if (cmd->sc_data_direction != DMA_TO_DEVICE) qc->tf.feature |= ATAPI_DMADIR; #endif } @@ -1821,7 +1825,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd) */ tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE); - if (cmd->sc_data_direction == SCSI_DATA_WRITE) + if (cmd->sc_data_direction == DMA_TO_DEVICE) tf->flags |= ATA_TFLAG_WRITE; /* -- cgit From 54dac83c426a1a03bd139c5ac7e938890bd2693e Mon Sep 17 00:00:00 2001 From: Jeff Raubitschek Date: Tue, 4 Oct 2005 10:21:19 -0400 Subject: [libata passthru] fix leak on error --- drivers/scsi/libata-scsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 98057563a3cc..75cb685e320b 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -116,8 +116,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) if (args[3]) { argsize = SECTOR_SIZE * args[3]; argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; + if (argbuf == NULL) { + rc = -ENOMEM; + goto error; + } scsi_cmd[1] = (4 << 1); /* PIO Data-in */ scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev, -- cgit From 0e5dec478cfff2c29e68d1108ff828fa321adc59 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 6 Oct 2005 09:40:20 -0400 Subject: [libata passthru] add (DRIVER_SENSE << 24) to all check-conditions --- drivers/scsi/libata-scsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 75cb685e320b..1b00bc618e15 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -500,7 +500,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) memset(sb, 0, SCSI_SENSE_BUFFERSIZE); - cmd->result = SAM_STAT_CHECK_CONDITION; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* * Read the controller registers. @@ -575,7 +575,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) memset(sb, 0, SCSI_SENSE_BUFFERSIZE); - cmd->result = SAM_STAT_CHECK_CONDITION; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* * Read the controller registers. @@ -1638,7 +1638,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq) { DPRINTK("ENTER\n"); - cmd->result = SAM_STAT_CHECK_CONDITION; + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; cmd->sense_buffer[0] = 0x70; cmd->sense_buffer[2] = ILLEGAL_REQUEST; -- cgit From 422fa08e538b649a9b80258950d2f8a202f45f19 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 9 Oct 2005 10:49:34 -0400 Subject: [libata passthru] update ATAPI completion for new error handling --- drivers/scsi/libata-scsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 698203bf4f69..617534b7a25e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1933,7 +1933,12 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat); if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ))) - ata_to_sense_error(qc, drv_stat); + /* FIXME: not quite right; we don't want the + * translation of taskfile registers into + * a sense descriptors, since that's only + * correct for ATA, not ATAPI + */ + ata_gen_ata_desc_sense(qc); else if (unlikely(drv_stat & ATA_ERR)) { DPRINTK("request check condition\n"); -- cgit From bdad1f836ab1ca2b18a625222f63f630cfd14e41 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 21 Oct 2005 22:36:23 -0400 Subject: [PARISC] Change the driver names so /sys/bus/parisc/drivers/ looks better Make /sys/bus/parisc/drivers look better by cleaning up parisc_driver names. Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4cbb6187cc44..123f4933d8f5 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -168,7 +168,7 @@ lasi700_driver_remove(struct parisc_device *dev) } static struct parisc_driver lasi700_driver = { - .name = "Lasi SCSI", + .name = "lasi_scsi", .id_table = lasi700_ids, .probe = lasi700_probe, .remove = __devexit_p(lasi700_driver_remove), -- cgit From 53f01bba49938f115237fe43a261c31ac13ae5c6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 21 Oct 2005 22:36:40 -0400 Subject: [PARISC] Convert parisc_device to use struct resource for hpa Convert pa_dev->hpa from an unsigned long to a struct resource. Signed-off-by: Matthew Wilcox Fix up users of ->hpa to use ->hpa.start instead. Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 123f4933d8f5..8028418b3ad6 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(parisc, lasi700_ids); static int __init lasi700_probe(struct parisc_device *dev) { - unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET; + unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET; struct NCR_700_Host_Parameters *hostdata; struct Scsi_Host *host; diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 5a51051e31f0..b131432c677d 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev) struct gsc_irq gsc_irq; u32 zalon_vers; int error = -ENODEV; - void __iomem *zalon = ioremap(dev->hpa, 4096); + void __iomem *zalon = ioremap(dev->hpa.start, 4096); void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; struct Scsi_Host *host; @@ -127,7 +127,7 @@ zalon_probe(struct parisc_device *dev) device.chip = zalon720_chip; device.host_id = 7; device.dev = &dev->dev; - device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET; + device.slot.base = dev->hpa.start + GSC_SCSI_ZALON_OFFSET; device.slot.base_v = io_port; device.slot.irq = dev->irq; device.differential = 2; -- cgit From 27ee073cd2f72aa794299ef1ead31072f5176533 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 21 Oct 2005 22:57:43 -0400 Subject: [PARISC] Update scsi drivers from parisc tree Fix lasi700 for James's ioread*be() changes Signed-off-by: Matthew Wilcox Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 8028418b3ad6..459a4daebece 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -125,8 +125,6 @@ lasi700_probe(struct parisc_device *dev) hostdata->dmode_extra = DMODE_FC2; } - NCR_700_set_mem_mapped(hostdata); - host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev); if (!host) goto out_kfree; -- cgit From d8539d81aeee4dbdc0624a798321e822fb2df7ae Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 15 Sep 2005 02:01:36 -0500 Subject: [PATCH] Driver core: pass interface to class interface methods Driver core: pass interface to class intreface methods Pass interface as argument to add() and remove() class interface methods. This way a subsystem can implement generic add/remove handlers and then call interface-specific ones. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ad94367df430..f0d8b4eda5ad 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -104,8 +104,8 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF; #define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ -static int sg_add(struct class_device *); -static void sg_remove(struct class_device *); +static int sg_add(struct class_device *, struct class_interface *); +static void sg_remove(struct class_device *, struct class_interface *); static Scsi_Request *dummy_cmdp; /* only used for sizeof */ @@ -1506,7 +1506,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) } static int -sg_add(struct class_device *cl_dev) +sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); struct gendisk *disk; @@ -1582,7 +1582,7 @@ out: } static void -sg_remove(struct class_device *cl_dev) +sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); Sg_device *sdp = NULL; -- cgit From 53f4654272df7c51064825024340554b39c9efba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Oct 2005 22:25:43 -0700 Subject: [PATCH] Driver Core: fix up all callers of class_device_create() The previous patch adding the ability to nest struct class_device changed the paramaters to the call class_device_create(). This patch fixes up all in-kernel users of the function. Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/ch.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/sg.c | 2 +- drivers/scsi/st.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index da6e51c7fe69..540147cb51ce 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -936,7 +936,7 @@ static int ch_probe(struct device *dev) if (init) ch_init_elem(ch); - class_device_create(ch_sysfs_class, + class_device_create(ch_sysfs_class, NULL, MKDEV(SCSI_CHANGER_MAJOR,ch->minor), dev, "s%s", ch->name); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 3f2f2464fa63..0bb60de0bded 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5627,7 +5627,7 @@ static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * if (!osst_sysfs_valid) return; - osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name); + osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name); if (IS_ERR(osst_class_member)) { printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name); return; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index f0d8b4eda5ad..40886e1c9616 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1550,7 +1550,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) if (sg_sysfs_valid) { struct class_device * sg_class_member; - sg_class_member = class_device_create(sg_sysfs_class, + sg_class_member = class_device_create(sg_sysfs_class, NULL, MKDEV(SCSI_GENERIC_MAJOR, k), cl_dev->dev, "%s", disk->disk_name); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index d001c046551b..d45ba4832162 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4375,7 +4375,7 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) snprintf(name, 10, "%s%s%s", rew ? "n" : "", STp->disk->disk_name, st_formats[i]); st_class_member = - class_device_create(st_sysfs_class, + class_device_create(st_sysfs_class, NULL, MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew)), &STp->device->sdev_gendev, "%s", name); -- cgit From a21a84a375ea3783cf9a53730d643c4db24371bc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 28 Oct 2005 15:43:16 -0400 Subject: [libata pdc_adma] minor fixes and cleanups Changes mostly from Mark Lord. - fix bugs in probe-time error handling - only complete qc if not NULL - check port-level polling flags --- drivers/scsi/pdc_adma.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 9820f272f889..7999817915c3 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -46,7 +46,7 @@ #include #define DRV_NAME "pdc_adma" -#define DRV_VERSION "0.01" +#define DRV_VERSION "0.03" /* macro to calculate base address for ATA regs */ #define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) @@ -79,7 +79,6 @@ enum { aNIEN = (1 << 8), /* irq mask: 1==masked */ aGO = (1 << 7), /* packet trigger ("Go!") */ aRSTADM = (1 << 5), /* ADMA logic reset */ - aRSTA = (1 << 2), /* ATA hard reset */ aPIOMD4 = 0x0003, /* PIO mode 4 */ /* ADMA_STATUS register bits */ @@ -452,24 +451,25 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) struct adma_port_priv *pp; struct ata_queued_cmd *qc; void __iomem *chan = ADMA_REGS(mmio_base, port_no); - u8 drv_stat, status = readb(chan + ADMA_STATUS); + u8 drv_stat = 0, status = readb(chan + ADMA_STATUS); if (status == 0) continue; handled = 1; adma_enter_reg_mode(ap); - if ((ap->flags & ATA_FLAG_PORT_DISABLED)) + if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - drv_stat = 0; - if ((status & (aPERR | aPSD | aUIRQ))) - drv_stat = ATA_ERR; - else if (pp->pkt[0] != cDONE) - drv_stat = ATA_ERR; - ata_qc_complete(qc, drv_stat); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if ((status & (aPERR | aPSD | aUIRQ))) + drv_stat = ATA_ERR; + else if (pp->pkt[0] != cDONE) + drv_stat = ATA_ERR; + ata_qc_complete(qc, drv_stat); + } } return handled; } @@ -561,15 +561,15 @@ static int adma_port_start(struct ata_port *ap) if ((pp->pkt_dma & 7) != 0) { printk("bad alignment for pp->pkt_dma: %08x\n", (u32)pp->pkt_dma); - goto err_out_kfree2; + dma_free_coherent(dev, ADMA_PKT_BYTES, + pp->pkt, pp->pkt_dma); + goto err_out_kfree; } memset(pp->pkt, 0, ADMA_PKT_BYTES); ap->private_data = pp; adma_reinit_engine(ap); return 0; -err_out_kfree2: - kfree(pp); err_out_kfree: kfree(pp); err_out: -- cgit From 00ac37f508689da281586c7ef304f26b5138d8a6 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 28 Oct 2005 15:58:28 -0400 Subject: [libata scsi] MODE SELECT, strengthen mode sense - move default mode pages to the front of libata-scsi.c so various functions can access them - partial annotation of these pages, point out divergence from sat-r06 - replace various mode page magic numbers with defines - strengthen MODE SENSE command decoding: handle DBD bit in cdb, yield block descriptor (per sat-r06) and handle mode sub pages Signed-off-by: Douglas Gilbert Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 144 ++++++++++++++++++++++++++++++++------------- 1 file changed, 103 insertions(+), 41 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b761bd1b9717..89a04b1a5a0e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -51,6 +51,45 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scs static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +#define RW_RECOVERY_MPAGE 0x1 +#define RW_RECOVERY_MPAGE_LEN 12 +#define CACHE_MPAGE 0x8 +#define CACHE_MPAGE_LEN 20 +#define CONTROL_MPAGE 0xa +#define CONTROL_MPAGE_LEN 12 +#define ALL_MPAGES 0x3f +#define ALL_SUB_MPAGES 0xff + + +static const u8 def_rw_recovery_mpage[] = { + RW_RECOVERY_MPAGE, + RW_RECOVERY_MPAGE_LEN - 2, + (1 << 7) | /* AWRE, sat-r06 say it shall be 0 */ + (1 << 6), /* ARRE (auto read reallocation) */ + 0, /* read retry count */ + 0, 0, 0, 0, + 0, /* write retry count */ + 0, 0, 0 +}; + +static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = { + CACHE_MPAGE, + CACHE_MPAGE_LEN - 2, + 0, /* contains WCE, needs to be 0 for logic */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* contains DRA, needs to be 0 for logic */ + 0, 0, 0, 0, 0, 0, 0 +}; + +static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { + CONTROL_MPAGE, + CONTROL_MPAGE_LEN - 2, + 2, /* DSENSE=0, GLTSD=1 */ + 0, /* [QAM+QERR may be 1, see 05-359r1] */ + 0, 0, 0, 0, 0xff, 0xff, + 0, 30 /* extended self test time, see 05-359r1 */ +}; + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) @@ -1583,13 +1622,9 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last, static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, const u8 *last) { - u8 page[] = { - 0x8, /* page code */ - 0x12, /* page length */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 zeroes */ - 0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */ - }; + u8 page[CACHE_MPAGE_LEN]; + memcpy(page, def_cache_mpage, sizeof(page)); if (ata_id_wcache_enabled(id)) page[2] |= (1 << 2); /* write cache enable */ if (!ata_id_rahead_enabled(id)) @@ -1613,15 +1648,9 @@ static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) { - const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30}; - - /* byte 2: set the descriptor format sense data bit (bit 2) - * since we need to support returning this format for SAT - * commands and any SCSI commands against a 48b LBA device. - */ - - ata_msense_push(ptr_io, last, page, sizeof(page)); - return sizeof(page); + ata_msense_push(ptr_io, last, def_control_mpage, + sizeof(def_control_mpage)); + return sizeof(def_control_mpage); } /** @@ -1638,15 +1667,10 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) { - const u8 page[] = { - 0x1, /* page code */ - 0xa, /* page length */ - (1 << 7) | (1 << 6), /* note auto r/w reallocation */ - 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */ - }; - ata_msense_push(ptr_io, last, page, sizeof(page)); - return sizeof(page); + ata_msense_push(ptr_io, last, def_rw_recovery_mpage, + sizeof(def_rw_recovery_mpage)); + return sizeof(def_rw_recovery_mpage); } /** @@ -1655,7 +1679,9 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Simulate MODE SENSE commands. + * Simulate MODE SENSE commands. Assume this is invoked for direct + * access devices (e.g. disks) only. There should be no block + * descriptor for other device types. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1665,15 +1691,22 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { u8 *scsicmd = args->cmd->cmnd, *p, *last; - unsigned int page_control, six_byte, output_len; + const u8 sat_blk_desc[] = { + 0, 0, 0, 0, /* number of blocks: sat unspecified */ + 0, + 0, 0x2, 0x0 /* block length: 512 bytes */ + }; + u8 pg, spg; + unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; VPRINTK("ENTER\n"); six_byte = (scsicmd[0] == MODE_SENSE); - - /* we only support saved and current values (which we treat - * in the same manner) + ebd = !(scsicmd[1] & 0x8); /* dbd bit inverted == edb */ + /* + * LLBA bit in msense(10) ignored (compliant) */ + page_control = scsicmd[2] >> 6; switch (page_control) { case 0: /* current */ @@ -1686,29 +1719,42 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, goto invalid_fld; } - if (six_byte) - output_len = 4; - else - output_len = 8; + if (six_byte) { + output_len = 4 + (ebd ? 8 : 0); + alloc_len = scsicmd[4]; + } else { + output_len = 8 + (ebd ? 8 : 0); + alloc_len = (scsicmd[7] << 8) + scsicmd[8]; + } + minlen = (alloc_len < buflen) ? alloc_len : buflen; p = rbuf + output_len; - last = rbuf + buflen - 1; + last = rbuf + minlen - 1; - switch(scsicmd[2] & 0x3f) { - case 0x01: /* r/w error recovery */ + pg = scsicmd[2] & 0x3f; + spg = scsicmd[3]; + /* + * No mode subpages supported (yet) but asking for _all_ + * subpages may be valid + */ + if (spg && (spg != ALL_SUB_MPAGES)) + goto invalid_fld; + + switch(pg) { + case RW_RECOVERY_MPAGE: output_len += ata_msense_rw_recovery(&p, last); break; - case 0x08: /* caching */ + case CACHE_MPAGE: output_len += ata_msense_caching(args->id, &p, last); break; - case 0x0a: { /* control mode */ + case CONTROL_MPAGE: { output_len += ata_msense_ctl_mode(&p, last); break; } - case 0x3f: /* all pages */ + case ALL_MPAGES: output_len += ata_msense_rw_recovery(&p, last); output_len += ata_msense_caching(args->id, &p, last); output_len += ata_msense_ctl_mode(&p, last); @@ -1718,15 +1764,31 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, goto invalid_fld; } + if (minlen < 1) + return 0; if (six_byte) { output_len--; rbuf[0] = output_len; + if (ebd) { + if (minlen > 3) + rbuf[3] = sizeof(sat_blk_desc); + if (minlen > 11) + memcpy(rbuf + 4, sat_blk_desc, + sizeof(sat_blk_desc)); + } } else { output_len -= 2; rbuf[0] = output_len >> 8; - rbuf[1] = output_len; + if (minlen > 1) + rbuf[1] = output_len; + if (ebd) { + if (minlen > 7) + rbuf[7] = sizeof(sat_blk_desc); + if (minlen > 15) + memcpy(rbuf + 8, sat_blk_desc, + sizeof(sat_blk_desc)); + } } - return 0; invalid_fld: @@ -2156,7 +2218,7 @@ ata_scsi_map_proto(u8 byte1) * Zero on success, non-zero on failure. */ static unsigned int -ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd) +ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) { struct ata_taskfile *tf = &(qc->tf); struct scsi_cmnd *cmd = qc->scsicmd; -- cgit From 07c1da2396632a4ad2cab41c6cd939b159f54968 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 28 Oct 2005 17:00:31 -0400 Subject: [libata sata_promise] add pci id Contributed by Daniel Mueller @ Siemens AG. --- drivers/scsi/sata_promise.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index eee93b0016df..50495569f409 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -195,6 +195,8 @@ static struct ata_port_info pdc_port_info[] = { static struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- cgit From c45154a3b1fecdbb51b5462c9f730b44e62b83a5 Mon Sep 17 00:00:00 2001 From: Ed Kear Date: Sat, 16 Jul 2005 23:32:19 -0400 Subject: [PATCH] libata: add support for Promise SATA 300 TX2plus PDC40775 I'm using this card in a RAID1 with 2 new SATA drives with no problems. Card - SATA 300 TX2plus PDC40775 (3d73) Signed-off-by: Ed Kear Signed-off-by: Jeff Garzik --- drivers/scsi/sata_promise.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 50495569f409..63911f16b6ec 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -209,6 +209,8 @@ static struct pci_device_id pdc_ata_pci_tbl[] = { board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, -- cgit From b30197d2c07b396907b81673354a015a9d2b216c Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 27 Sep 2005 01:21:56 -0700 Subject: [PATCH] PCI: ipr: Block config access during BIST IPR scsi adapter have an exposure today in that they issue BIST to the adapter to reset the card. If, during the time it takes to complete BIST, userspace attempts to access PCI config space, the host bus bridge will master abort the access since the ipr adapter does not respond on the PCI bus for a brief period of time when running BIST. On PPC64 hardware, this master abort results in the host PCI bridge isolating that PCI device from the rest of the system, making the device unusable until Linux is rebooted. This patch makes use of some newly added PCI layer APIs that allow for protection from userspace accessing config space of a device in scenarios such as this. Signed-off-by: Brian King Cc: Benjamin Herrenschmidt Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) --- drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index babd48363402..e0039dfae8e5 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4944,6 +4944,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; + pci_unblock_user_cfg_access(ioa_cfg->pdev); rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { @@ -4998,6 +4999,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) int rc; ENTER; + pci_block_user_cfg_access(ioa_cfg->pdev); rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); if (rc != PCIBIOS_SUCCESSFUL) { -- cgit From 5457b6a6013516a73b8f48ec1adb9984b577a5c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Oct 2005 21:32:46 +0100 Subject: [PATCH] PCI: Convert megaraid to use pci_driver shutdown method Convert megaraid to use pci_driver's shutdown method rather than the generic device_driver shutdown method. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_mbox.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index d47be8e0ea3a..c9e743ba09ec 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -76,7 +76,7 @@ static void megaraid_exit(void); static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *); static void megaraid_detach_one(struct pci_dev *); -static void megaraid_mbox_shutdown(struct device *); +static void megaraid_mbox_shutdown(struct pci_dev *); static int megaraid_io_attach(adapter_t *); static void megaraid_io_detach(adapter_t *); @@ -369,9 +369,7 @@ static struct pci_driver megaraid_pci_driver_g = { .id_table = pci_id_table_g, .probe = megaraid_probe_one, .remove = __devexit_p(megaraid_detach_one), - .driver = { - .shutdown = megaraid_mbox_shutdown, - } + .shutdown = megaraid_mbox_shutdown, }; @@ -673,9 +671,9 @@ megaraid_detach_one(struct pci_dev *pdev) * Shutdown notification, perform flush cache */ static void -megaraid_mbox_shutdown(struct device *device) +megaraid_mbox_shutdown(struct pci_dev *pdev) { - adapter_t *adapter = pci_get_drvdata(to_pci_dev(device)); + adapter_t *adapter = pci_get_drvdata(pdev); static int counter; if (!adapter) { -- cgit From 4b4a5eaedfc098d825d4c34cad1f1115802512b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 29 Oct 2005 06:38:44 +0100 Subject: [PATCH] sata_sil24 iomem annotations and fixes trivial iomem annotations + missing memcpy_fromio() caught by those Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/scsi/sata_sil24.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 32d730bd5bb6..51855d3bac64 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -220,8 +220,8 @@ struct sil24_port_priv { /* ap->host_set->private_data */ struct sil24_host_priv { - void *host_base; /* global controller control (128 bytes @BAR0) */ - void *port_base; /* port registers (4 * 8192 bytes @BAR2) */ + void __iomem *host_base; /* global controller control (128 bytes @BAR0) */ + void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */ }; static u8 sil24_check_status(struct ata_port *ap); @@ -349,10 +349,12 @@ static struct ata_port_info sil24_port_info[] = { static inline void sil24_update_tf(struct ata_port *ap) { struct sil24_port_priv *pp = ap->private_data; - void *port = (void *)ap->ioaddr.cmd_addr; - struct sil24_prb *prb = port; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + struct sil24_prb __iomem *prb = port; + u8 fis[6 * 4]; - ata_tf_from_fis(prb->fis, &pp->tf); + memcpy_fromio(fis, prb->fis, 6 * 4); + ata_tf_from_fis(fis, &pp->tf); } static u8 sil24_check_status(struct ata_port *ap) @@ -376,9 +378,9 @@ static int sil24_scr_map[] = { static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg) { - void *scr_addr = (void *)ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { - void *addr; + void __iomem *addr; addr = scr_addr + sil24_scr_map[sc_reg] * 4; return readl(scr_addr + sil24_scr_map[sc_reg] * 4); } @@ -387,9 +389,9 @@ static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg) static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) { - void *scr_addr = (void *)ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { - void *addr; + void __iomem *addr; addr = scr_addr + sil24_scr_map[sc_reg] * 4; writel(val, scr_addr + sil24_scr_map[sc_reg] * 4); } @@ -454,7 +456,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) static int sil24_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); @@ -467,7 +469,7 @@ static void sil24_irq_clear(struct ata_port *ap) /* unused */ } -static int __sil24_reset_controller(void *port) +static int __sil24_reset_controller(void __iomem *port) { int cnt; u32 tmp; @@ -493,7 +495,7 @@ static void sil24_reset_controller(struct ata_port *ap) { printk(KERN_NOTICE DRV_NAME " ata%u: resetting controller...\n", ap->id); - if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr)) + if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr)) printk(KERN_ERR DRV_NAME " ata%u: failed to reset controller\n", ap->id); } @@ -527,7 +529,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) { struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct sil24_port_priv *pp = ap->private_data; - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 irq_stat, cmd_err, sstatus, serror; irq_stat = readl(port + PORT_IRQ_STAT); @@ -574,7 +576,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) static inline void sil24_host_intr(struct ata_port *ap) { struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 slot_stat; slot_stat = readl(port + PORT_SLOT_STAT); @@ -689,7 +691,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_port_info *pinfo = &sil24_port_info[board_id]; struct ata_probe_ent *probe_ent = NULL; struct sil24_host_priv *hpriv = NULL; - void *host_base = NULL, *port_base = NULL; + void __iomem *host_base = NULL; + void __iomem *port_base = NULL; int i, rc; if (!printed_version++) @@ -771,7 +774,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { - void *port = port_base + i * PORT_REGS_SIZE; + void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; u32 tmp; int cnt; -- cgit From ac19bff25b6834d858274406a686f2227dd8489d Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 29 Oct 2005 13:58:21 -0400 Subject: [libata] ensure ->tf_read() hook reads Status and Error registers We want ->tf_read() to get a complete snapshot of all taskfile registers, without requiring the callers to manually call ata_chk_status() and ata_chk_err() themselves. This also fixes a minor bug in sata_vsc where the lower bits of the feature register were incorrectly placed in the HOB (high order bits) portion of struct ata_taskfile. --- drivers/scsi/libata-core.c | 4 ++++ drivers/scsi/pdc_adma.c | 2 +- drivers/scsi/sata_qstor.c | 2 +- drivers/scsi/sata_svw.c | 22 ++++++++++++++++------ drivers/scsi/sata_vsc.c | 20 ++++++++++++++------ 5 files changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f53d7b8ac33f..56c81f0aa1d9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -370,6 +370,8 @@ static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; + tf->command = ata_check_status(ap); + tf->feature = ata_chk_err(ap); tf->nsect = inb(ioaddr->nsect_addr); tf->lbal = inb(ioaddr->lbal_addr); tf->lbam = inb(ioaddr->lbam_addr); @@ -402,6 +404,8 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; + tf->command = ata_check_status(ap); + tf->feature = ata_chk_err(ap); tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 7999817915c3..af99feb9d237 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -490,7 +490,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set) if (qc && (!(qc->tf.ctl & ATA_NIEN))) { /* check main status, clearing INTRQ */ - u8 status = ata_chk_status(ap); + u8 status = ata_check_status(ap); if ((status & ATA_BUSY)) continue; DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 250dafa6bc36..1aaf3304d397 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -433,7 +433,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) if (qc && (!(qc->tf.ctl & ATA_NIEN))) { /* check main status, clearing INTRQ */ - u8 status = ata_chk_status(ap); + u8 status = ata_check_status(ap); if ((status & ATA_BUSY)) continue; DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index e0f9570bc6dd..46208f52d0e1 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -84,6 +84,8 @@ /* Port stride */ #define K2_SATA_PORT_OFFSET 0x100 +static u8 k2_stat_check_status(struct ata_port *ap); + static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) { @@ -136,16 +138,24 @@ static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; - u16 nsect, lbal, lbam, lbah; + u16 nsect, lbal, lbam, lbah, feature; - nsect = tf->nsect = readw(ioaddr->nsect_addr); - lbal = tf->lbal = readw(ioaddr->lbal_addr); - lbam = tf->lbam = readw(ioaddr->lbam_addr); - lbah = tf->lbah = readw(ioaddr->lbah_addr); + tf->command = k2_stat_check_status(ap); tf->device = readw(ioaddr->device_addr); + feature = readw(ioaddr->error_addr); + nsect = readw(ioaddr->nsect_addr); + lbal = readw(ioaddr->lbal_addr); + lbam = readw(ioaddr->lbam_addr); + lbah = readw(ioaddr->lbah_addr); + + tf->feature = feature; + tf->nsect = nsect; + tf->lbal = lbal; + tf->lbam = lbam; + tf->lbah = lbah; if (tf->flags & ATA_TFLAG_LBA48) { - tf->hob_feature = readw(ioaddr->error_addr) >> 8; + tf->hob_feature = feature >> 8; tf->hob_nsect = nsect >> 8; tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 5af05fdf8544..54273e0063c7 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -153,16 +153,24 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; - u16 nsect, lbal, lbam, lbah; + u16 nsect, lbal, lbam, lbah, feature; - nsect = tf->nsect = readw(ioaddr->nsect_addr); - lbal = tf->lbal = readw(ioaddr->lbal_addr); - lbam = tf->lbam = readw(ioaddr->lbam_addr); - lbah = tf->lbah = readw(ioaddr->lbah_addr); + tf->command = ata_check_status(ap); tf->device = readw(ioaddr->device_addr); + feature = readw(ioaddr->error_addr); + nsect = readw(ioaddr->nsect_addr); + lbal = readw(ioaddr->lbal_addr); + lbam = readw(ioaddr->lbam_addr); + lbah = readw(ioaddr->lbah_addr); + + tf->feature = feature; + tf->nsect = nsect; + tf->lbal = lbal; + tf->lbam = lbam; + tf->lbah = lbah; if (tf->flags & ATA_TFLAG_LBA48) { - tf->hob_feature = readb(ioaddr->error_addr); + tf->hob_feature = feature >> 8; tf->hob_nsect = nsect >> 8; tf->hob_lbal = lbal >> 8; tf->hob_lbam = lbam >> 8; -- cgit From 57f3bda88a5e5a2810016820a932cb82931dcb1c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 28 Oct 2005 20:37:23 -0700 Subject: [PATCH] libata-core cleanups (updated) libata-core cleanups: - use kzalloc() instead of kmalloc() + memset(); - use one exit path in ata_device_add(); Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 56c81f0aa1d9..b1b1c6f01419 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4258,11 +4258,10 @@ int ata_device_add(const struct ata_probe_ent *ent) DPRINTK("ENTER\n"); /* alloc a container for our list of ATA ports (buses) */ - host_set = kmalloc(sizeof(struct ata_host_set) + + host_set = kzalloc(sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *)), GFP_KERNEL); if (!host_set) return 0; - memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *))); spin_lock_init(&host_set->lock); host_set->dev = dev; @@ -4302,10 +4301,8 @@ int ata_device_add(const struct ata_probe_ent *ent) count++; } - if (!count) { - kfree(host_set); - return 0; - } + if (!count) + goto err_free_ret; /* obtain irq, that is shared between channels */ if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, @@ -4363,6 +4360,7 @@ err_out: ata_host_remove(host_set->ports[i], 1); scsi_host_put(host_set->ports[i]->host); } +err_free_ret: kfree(host_set); VPRINTK("EXIT, returning 0\n"); return 0; @@ -4472,15 +4470,13 @@ ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) { struct ata_probe_ent *probe_ent; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); if (!probe_ent) { printk(KERN_ERR DRV_NAME "(%s): out of memory\n", kobject_name(&(dev->kobj))); return NULL; } - memset(probe_ent, 0, sizeof(*probe_ent)); - INIT_LIST_HEAD(&probe_ent->node); probe_ent->dev = dev; -- cgit From 2ab540becd1bcf9c6886370fd8c67e56dd1c9f3a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 29 Oct 2005 06:38:44 +0100 Subject: [PATCH] sata_sil24 iomem annotations and fixes trivial iomem annotations + missing memcpy_fromio() caught by those Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 32d730bd5bb6..51855d3bac64 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -220,8 +220,8 @@ struct sil24_port_priv { /* ap->host_set->private_data */ struct sil24_host_priv { - void *host_base; /* global controller control (128 bytes @BAR0) */ - void *port_base; /* port registers (4 * 8192 bytes @BAR2) */ + void __iomem *host_base; /* global controller control (128 bytes @BAR0) */ + void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */ }; static u8 sil24_check_status(struct ata_port *ap); @@ -349,10 +349,12 @@ static struct ata_port_info sil24_port_info[] = { static inline void sil24_update_tf(struct ata_port *ap) { struct sil24_port_priv *pp = ap->private_data; - void *port = (void *)ap->ioaddr.cmd_addr; - struct sil24_prb *prb = port; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + struct sil24_prb __iomem *prb = port; + u8 fis[6 * 4]; - ata_tf_from_fis(prb->fis, &pp->tf); + memcpy_fromio(fis, prb->fis, 6 * 4); + ata_tf_from_fis(fis, &pp->tf); } static u8 sil24_check_status(struct ata_port *ap) @@ -376,9 +378,9 @@ static int sil24_scr_map[] = { static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg) { - void *scr_addr = (void *)ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { - void *addr; + void __iomem *addr; addr = scr_addr + sil24_scr_map[sc_reg] * 4; return readl(scr_addr + sil24_scr_map[sc_reg] * 4); } @@ -387,9 +389,9 @@ static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg) static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) { - void *scr_addr = (void *)ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { - void *addr; + void __iomem *addr; addr = scr_addr + sil24_scr_map[sc_reg] * 4; writel(val, scr_addr + sil24_scr_map[sc_reg] * 4); } @@ -454,7 +456,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) static int sil24_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); @@ -467,7 +469,7 @@ static void sil24_irq_clear(struct ata_port *ap) /* unused */ } -static int __sil24_reset_controller(void *port) +static int __sil24_reset_controller(void __iomem *port) { int cnt; u32 tmp; @@ -493,7 +495,7 @@ static void sil24_reset_controller(struct ata_port *ap) { printk(KERN_NOTICE DRV_NAME " ata%u: resetting controller...\n", ap->id); - if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr)) + if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr)) printk(KERN_ERR DRV_NAME " ata%u: failed to reset controller\n", ap->id); } @@ -527,7 +529,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) { struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct sil24_port_priv *pp = ap->private_data; - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 irq_stat, cmd_err, sstatus, serror; irq_stat = readl(port + PORT_IRQ_STAT); @@ -574,7 +576,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) static inline void sil24_host_intr(struct ata_port *ap) { struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - void *port = (void *)ap->ioaddr.cmd_addr; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; u32 slot_stat; slot_stat = readl(port + PORT_SLOT_STAT); @@ -689,7 +691,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_port_info *pinfo = &sil24_port_info[board_id]; struct ata_probe_ent *probe_ent = NULL; struct sil24_host_priv *hpriv = NULL; - void *host_base = NULL, *port_base = NULL; + void __iomem *host_base = NULL; + void __iomem *port_base = NULL; int i, rc; if (!printed_version++) @@ -771,7 +774,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { - void *port = port_base + i * PORT_REGS_SIZE; + void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; u32 tmp; int cnt; -- cgit From 15b6e09b66b1e534377dbd6c4d6a5d097062315c Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 13 Jun 2005 19:55:42 +0000 Subject: dec_esp: Use physical addresses These should really be addresses obtained with ioremap() or some bus-specific backend, but for now... Signed-off-by: Ralf Baechle --- drivers/scsi/dec_esp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c index 315f95a0d6c0..4f39890b44ac 100644 --- a/drivers/scsi/dec_esp.c +++ b/drivers/scsi/dec_esp.c @@ -228,7 +228,7 @@ static int dec_esp_detect(Scsi_Host_Template * tpnt) mem_start = get_tc_base_addr(slot); /* Store base addr into esp struct */ - esp->slot = PHYSADDR(mem_start); + esp->slot = CPHYSADDR(mem_start); esp->dregs = 0; esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG); -- cgit From 378f058cc49bcda7fa63d3cd86d2f9a0a5188b1c Mon Sep 17 00:00:00 2001 From: David Hardeman Date: Sat, 17 Sep 2005 17:55:31 +1000 Subject: [PATCH] Use sg_set_buf/sg_init_one where applicable This patch uses sg_set_buf/sg_init_one in some places where it was duplicated. Signed-off-by: David Hardeman Cc: James Bottomley Cc: Greg KH Cc: "David S. Miller" Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Herbert Xu --- drivers/scsi/arm/scsi.h | 6 +++--- drivers/scsi/libata-core.c | 10 ++-------- drivers/scsi/sg.c | 5 ++--- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h index 48e1c4d9738b..19937640e2e7 100644 --- a/drivers/scsi/arm/scsi.h +++ b/drivers/scsi/arm/scsi.h @@ -10,6 +10,8 @@ * Commonly used scsi driver functions. */ +#include + #define BELT_AND_BRACES /* @@ -22,9 +24,7 @@ static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int BUG_ON(bufs + 1 > max); - sg->page = virt_to_page(SCp->ptr); - sg->offset = offset_in_page(SCp->ptr); - sg->length = SCp->this_residual; + sg_set_buf(sg, SCp->ptr, SCp->this_residual); if (bufs) memcpy(sg + 1, SCp->buffer + 1, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b1b1c6f01419..5ca97605ff35 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "scsi.h" #include "scsi_priv.h" @@ -2576,19 +2577,12 @@ void ata_qc_prep(struct ata_queued_cmd *qc) void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) { - struct scatterlist *sg; - qc->flags |= ATA_QCFLAG_SINGLE; - memset(&qc->sgent, 0, sizeof(qc->sgent)); qc->sg = &qc->sgent; qc->n_elem = 1; qc->buf_virt = buf; - - sg = qc->sg; - sg->page = virt_to_page(buf); - sg->offset = (unsigned long) buf & ~PAGE_MASK; - sg->length = buflen; + sg_init_one(qc->sg, buf, buflen); } /** diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 861e51375d70..07fee811c09e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -49,6 +49,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */ #include #include #include +#include #include "scsi.h" #include @@ -1992,9 +1993,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) if (!p) break; } - sclp->page = virt_to_page(p); - sclp->offset = offset_in_page(p); - sclp->length = ret_sz; + sg_set_buf(sclp, p, ret_sz); SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n", k, sg_scatg2virt(sclp), ret_sz)); -- cgit From 0169e284f6b6b263cc7c2ed25986b96cd6fda610 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 29 Oct 2005 21:25:10 -0400 Subject: [libata] remove ata_chk_err(), ->check_err() hook. We now depend on ->tf_read() to provide us with the contents of the Error shadow register. --- drivers/scsi/ahci.c | 9 --------- drivers/scsi/libata-core.c | 41 +++++++++-------------------------------- drivers/scsi/sata_mv.c | 18 ------------------ drivers/scsi/sata_sil24.c | 8 -------- 4 files changed, 9 insertions(+), 67 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index fe8187d6f58b..03829aedfd39 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -192,7 +192,6 @@ static void ahci_port_stop(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); -static u8 ahci_check_err(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); @@ -221,7 +220,6 @@ static const struct ata_port_operations ahci_ops = { .check_status = ahci_check_status, .check_altstatus = ahci_check_status, - .check_err = ahci_check_err, .dev_select = ata_noop_dev_select, .tf_read = ahci_tf_read, @@ -458,13 +456,6 @@ static u8 ahci_check_status(struct ata_port *ap) return readl(mmio + PORT_TFDATA) & 0xFF; } -static u8 ahci_check_err(struct ata_port *ap) -{ - void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; - - return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF; -} - static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ahci_port_priv *pp = ap->private_data; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b1b1c6f01419..d2f71a2331bb 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -371,7 +371,7 @@ static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) struct ata_ioports *ioaddr = &ap->ioaddr; tf->command = ata_check_status(ap); - tf->feature = ata_chk_err(ap); + tf->feature = inb(ioaddr->error_addr); tf->nsect = inb(ioaddr->nsect_addr); tf->lbal = inb(ioaddr->lbal_addr); tf->lbam = inb(ioaddr->lbam_addr); @@ -405,7 +405,7 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) struct ata_ioports *ioaddr = &ap->ioaddr; tf->command = ata_check_status(ap); - tf->feature = ata_chk_err(ap); + tf->feature = readb((void __iomem *)ioaddr->error_addr); tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); @@ -525,30 +525,6 @@ u8 ata_altstatus(struct ata_port *ap) } -/** - * ata_chk_err - Read device error reg - * @ap: port where the device is - * - * Reads ATA taskfile error register for - * currently-selected device and return its value. - * - * Note: may NOT be used as the check_err() entry in - * ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -u8 ata_chk_err(struct ata_port *ap) -{ - if (ap->ops->check_err) - return ap->ops->check_err(ap); - - if (ap->flags & ATA_FLAG_MMIO) { - return readb((void __iomem *) ap->ioaddr.error_addr); - } - return inb(ap->ioaddr.error_addr); -} - /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert @@ -901,8 +877,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) memset(&tf, 0, sizeof(tf)); - err = ata_chk_err(ap); ap->ops->tf_read(ap, &tf); + err = tf.feature; dev->class = ATA_DEV_NONE; @@ -1139,7 +1115,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) unsigned int major_version; u16 tmp; unsigned long xfer_modes; - u8 status; unsigned int using_edd; DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; @@ -1193,8 +1168,11 @@ retry: else wait_for_completion(&wait); - status = ata_chk_status(ap); - if (status & ATA_ERR) { + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->ops->tf_read(ap, &qc->tf); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + if (qc->tf.command & ATA_ERR) { /* * arg! EDD works for all test cases, but seems to return * the ATA signature for some ATAPI devices. Until the @@ -1207,7 +1185,7 @@ retry: * to have this problem. */ if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) { - u8 err = ata_chk_err(ap); + u8 err = qc->tf.feature; if (err & ATA_ABORTED) { dev->class = ATA_DEV_ATAPI; qc->cursg = 0; @@ -4873,7 +4851,6 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status); EXPORT_SYMBOL_GPL(ata_altstatus); -EXPORT_SYMBOL_GPL(ata_chk_err); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 422e0b6f603a..dcef5fe8600b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -258,7 +258,6 @@ struct mv_host_priv { static void mv_irq_clear(struct ata_port *ap); static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); -static u8 mv_check_err(struct ata_port *ap); static void mv_phy_reset(struct ata_port *ap); static void mv_host_stop(struct ata_host_set *host_set); static int mv_port_start(struct ata_port *ap); @@ -296,7 +295,6 @@ static const struct ata_port_operations mv_ops = { .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, - .check_err = mv_check_err, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, @@ -1184,22 +1182,6 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, return IRQ_RETVAL(handled); } -/** - * mv_check_err - Return the error shadow register to caller. - * @ap: ATA channel to manipulate - * - * Marvell requires DMA to be stopped before accessing shadow - * registers. So we do that, then return the needed register. - * - * LOCKING: - * Inherited from caller. FIXME: protect mv_stop_dma with lock? - */ -static u8 mv_check_err(struct ata_port *ap) -{ - mv_stop_dma(ap); /* can't read shadow regs if DMA on */ - return readb((void __iomem *) ap->ioaddr.error_addr); -} - /** * mv_phy_reset - Perform eDMA reset followed by COMRESET * @ap: ATA channel to manipulate diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 51855d3bac64..e18a1e2bb65e 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -225,7 +225,6 @@ struct sil24_host_priv { }; static u8 sil24_check_status(struct ata_port *ap); -static u8 sil24_check_err(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); @@ -280,7 +279,6 @@ static const struct ata_port_operations sil24_ops = { .check_status = sil24_check_status, .check_altstatus = sil24_check_status, - .check_err = sil24_check_err, .dev_select = ata_noop_dev_select, .tf_read = sil24_tf_read, @@ -363,12 +361,6 @@ static u8 sil24_check_status(struct ata_port *ap) return pp->tf.command; } -static u8 sil24_check_err(struct ata_port *ap) -{ - struct sil24_port_priv *pp = ap->private_data; - return pp->tf.feature; -} - static int sil24_scr_map[] = { [SCR_CONTROL] = 0, [SCR_STATUS] = 1, -- cgit From b5810039a54e5babf428e9a1e89fc1940fabff11 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Sat, 29 Oct 2005 18:16:12 -0700 Subject: [PATCH] core remove PageReserved Remove PageReserved() calls from core code by tightening VM_RESERVED handling in mm/ to cover PageReserved functionality. PageReserved special casing is removed from get_page and put_page. All setting and clearing of PageReserved is retained, and it is now flagged in the page_alloc checks to help ensure we don't introduce any refcount based freeing of Reserved pages. MAP_PRIVATE, PROT_WRITE of VM_RESERVED regions is tentatively being deprecated. We never completely handled it correctly anyway, and is be reintroduced in future if required (Hugh has a proof of concept). Once PageReserved() calls are removed from kernel/power/swsusp.c, and all arch/ and driver code, the Set and Clear calls, and the PG_reserved bit can be trivially removed. Last real user of PageReserved is swsusp, which uses PageReserved to determine whether a struct page points to valid memory or not. This still needs to be addressed (a generic page_is_ram() should work). A last caveat: the ZERO_PAGE is now refcounted and managed with rmap (and thus mapcounted and count towards shared rss). These writes to the struct page could cause excessive cacheline bouncing on big systems. There are a number of ways this could be addressed if it is an issue. Signed-off-by: Nick Piggin Refcount bug fix for filemap_xip.c Signed-off-by: Carsten Otte Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sg.c | 12 ++++++++---- drivers/scsi/st.c | 10 +++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 861e51375d70..2d30b46806bf 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1886,13 +1886,17 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, int i; for (i=0; i < nr_pages; i++) { - if (dirtied && !PageReserved(sgl[i].page)) - SetPageDirty(sgl[i].page); - /* unlock_page(sgl[i].page); */ + struct page *page = sgl[i].page; + + /* XXX: just for debug. Remove when PageReserved is removed */ + BUG_ON(PageReserved(page)); + if (dirtied) + SetPageDirty(page); + /* unlock_page(page); */ /* FIXME: cache flush missing for rw==READ * FIXME: call the correct reference counting function */ - page_cache_release(sgl[i].page); + page_cache_release(page); } return 0; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 5eb54d8019b4..da9766283bd7 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4526,12 +4526,16 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p int i; for (i=0; i < nr_pages; i++) { - if (dirtied && !PageReserved(sgl[i].page)) - SetPageDirty(sgl[i].page); + struct page *page = sgl[i].page; + + /* XXX: just for debug. Remove when PageReserved is removed */ + BUG_ON(PageReserved(page)); + if (dirtied) + SetPageDirty(page); /* FIXME: cache flush missing for rw==READ * FIXME: call the correct reference counting function */ - page_cache_release(sgl[i].page); + page_cache_release(page); } return 0; -- cgit