diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 |
commit | a8931ef380c92d121ae74ecfb03b2d63f72eea6f (patch) | |
tree | 980fb6b019e11e6cb1ece55b7faff184721a8053 /drivers/scsi | |
parent | 90574d0a4d4b73308ae54a2a57a4f3f1fa98e984 (diff) | |
parent | e5a5816f7875207cb0a0a7032e39a4686c5e10a4 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/scsi')
54 files changed, 1014 insertions, 477 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index b31faeccb9cd..867f6fd5c2c0 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1278,7 +1278,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) error = 0; /* Check for command packet errors */ if (full_command_packet->command.newcommand.status != 0) { - if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id] != NULL) { error = twa_fill_sense(tw_dev, request_id, 1, 1); } else { /* Skip ioctl error prints */ @@ -1290,7 +1290,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) /* Check for correct state */ if (tw_dev->state[request_id] != TW_S_POSTED) { - if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id] != NULL) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted"); TW_CLEAR_ALL_INTERRUPTS(tw_dev); goto twa_interrupt_bail; @@ -1298,7 +1298,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) } /* Check for internal command completion */ - if (tw_dev->srb[request_id] == 0) { + if (tw_dev->srb[request_id] == NULL) { if (request_id != tw_dev->chrdev_request_id) { if (twa_aen_complete(tw_dev, request_id)) TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt"); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f4c4fe90240a..f5a9addb7050 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -599,7 +599,7 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, (struct NCR_700_command_slot *)SCp->host_scribble; dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); if (slot->flags == NCR_700_FLAG_AUTOSENSE) { char *cmnd = NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_700_DEBUG @@ -1004,7 +1004,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * here */ NCR_700_unmap(hostdata, SCp, slot); dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), + MAX_COMMAND_SIZE, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; @@ -1901,7 +1901,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->resume_offset = 0; slot->pCmd = dma_map_single(hostdata->dev, SCp->cmnd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); + MAX_COMMAND_SIZE, DMA_TO_DEVICE); NCR_700_start_command(SCp); return 0; } diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 99c57b0c1d54..81ccbd7f9e34 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -504,10 +504,9 @@ config SCSI_AIC7XXX_OLD source "drivers/scsi/aic7xxx/Kconfig.aic79xx" source "drivers/scsi/aic94xx/Kconfig" -# All the I2O code and drivers do not seem to be 64bit safe. config SCSI_DPT_I2O tristate "Adaptec I2O RAID support " - depends on !64BIT && SCSI && PCI && VIRT_TO_BUS + depends on SCSI && PCI && VIRT_TO_BUS help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained @@ -1680,6 +1679,7 @@ config MAC_SCSI config SCSI_MAC_ESP tristate "Macintosh NCR53c9[46] SCSI" depends on MAC && SCSI + select SCSI_SPI_ATTRS help This is the NCR 53c9x SCSI controller found on most of the 68040 based Macintoshes. diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 792b2e807bf3..ced3eebe252c 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -895,7 +895,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru } else { scb->tag_msg = 0; /* No tag support */ } - memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len); + memcpy(scb->cdb, cmd->cmnd, scb->cdb_len); } /** diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 460d4024c46c..aa4e77c25273 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -498,6 +498,11 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid = 1; + /* sense_key holds the current state of the spin-up */ + if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) + fsa_dev_ptr->sense_data.sense_key = NOT_READY; + else if (fsa_dev_ptr->sense_data.sense_key == NOT_READY) + fsa_dev_ptr->sense_data.sense_key = NO_SENSE; fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + @@ -1509,20 +1514,35 @@ static void io_callback(void *context, struct fib * fibptr) scsi_dma_unmap(scsicmd); readreply = (struct aac_read_reply *)fib_data(fibptr); - if (le32_to_cpu(readreply->status) == ST_OK) - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - else { + switch (le32_to_cpu(readreply->status)) { + case ST_OK: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_GOOD; + dev->fsa_dev[cid].sense_data.sense_key = NO_SENSE; + break; + case ST_NOT_READY: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense(&dev->fsa_dev[cid].sense_data, NOT_READY, + SENCODE_BECOMING_READY, ASENCODE_BECOMING_READY, 0, 0); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), + SCSI_SENSE_BUFFERSIZE)); + break; + default: #ifdef AAC_DETAILED_STATUS_INFO printk(KERN_WARNING "io_callback: io failed, status = %d\n", le32_to_cpu(readreply->status)); #endif - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; set_sense(&dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0); memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), SCSI_SENSE_BUFFERSIZE)); + break; } aac_fib_complete(fibptr); aac_fib_free(fibptr); @@ -1863,6 +1883,84 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) return SCSI_MLQUEUE_HOST_BUSY; } +static void aac_start_stop_callback(void *context, struct fib *fibptr) +{ + struct scsi_cmnd *scsicmd = context; + + if (!aac_valid_context(scsicmd, fibptr)) + return; + + BUG_ON(fibptr == NULL); + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + scsicmd->scsi_done(scsicmd); +} + +static int aac_start_stop(struct scsi_cmnd *scsicmd) +{ + int status; + struct fib *cmd_fibcontext; + struct aac_power_management *pmcmd; + struct scsi_device *sdev = scsicmd->device; + struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; + + if (!(aac->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_POWER_MANAGEMENT)) { + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_GOOD; + scsicmd->scsi_done(scsicmd); + return 0; + } + + if (aac->in_reset) + return SCSI_MLQUEUE_HOST_BUSY; + + /* + * Allocate and initialize a Fib + */ + cmd_fibcontext = aac_fib_alloc(aac); + if (!cmd_fibcontext) + return SCSI_MLQUEUE_HOST_BUSY; + + aac_fib_init(cmd_fibcontext); + + pmcmd = fib_data(cmd_fibcontext); + pmcmd->command = cpu_to_le32(VM_ContainerConfig); + pmcmd->type = cpu_to_le32(CT_POWER_MANAGEMENT); + /* Eject bit ignored, not relevant */ + pmcmd->sub = (scsicmd->cmnd[4] & 1) ? + cpu_to_le32(CT_PM_START_UNIT) : cpu_to_le32(CT_PM_STOP_UNIT); + pmcmd->cid = cpu_to_le32(sdev_id(sdev)); + pmcmd->parm = (scsicmd->cmnd[1] & 1) ? + cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0; + + /* + * Now send the Fib to the adapter + */ + status = aac_fib_send(ContainerCommand, + cmd_fibcontext, + sizeof(struct aac_power_management), + FsaNormal, + 0, 1, + (fib_callback)aac_start_stop_callback, + (void *)scsicmd); + + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } + + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); + return SCSI_MLQUEUE_HOST_BUSY; +} + /** * aac_scsi_cmd() - Process SCSI command * @scsicmd: SCSI command block @@ -1899,7 +1997,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * If the target container doesn't exist, it may have * been newly created */ - if ((fsa_dev_ptr[cid].valid & 1) == 0) { + if (((fsa_dev_ptr[cid].valid & 1) == 0) || + (fsa_dev_ptr[cid].sense_data.sense_key == + NOT_READY)) { switch (scsicmd->cmnd[0]) { case SERVICE_ACTION_IN: if (!(dev->raw_io_interface) || @@ -2091,8 +2191,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); /* Do not cache partition table for arrays */ scsicmd->device->removable = 1; - - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; @@ -2187,15 +2287,32 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * These commands are all No-Ops */ case TEST_UNIT_READY: + if (fsa_dev_ptr[cid].sense_data.sense_key == NOT_READY) { + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense(&dev->fsa_dev[cid].sense_data, + NOT_READY, SENCODE_BECOMING_READY, + ASENCODE_BECOMING_READY, 0, 0); + memcpy(scsicmd->sense_buffer, + &dev->fsa_dev[cid].sense_data, + min_t(size_t, + sizeof(dev->fsa_dev[cid].sense_data), + SCSI_SENSE_BUFFERSIZE)); + scsicmd->scsi_done(scsicmd); + return 0; + } + /* FALLTHRU */ case RESERVE: case RELEASE: case REZERO_UNIT: case REASSIGN_BLOCKS: case SEEK_10: - case START_STOP: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; + + case START_STOP: + return aac_start_stop(scsicmd); } switch (scsicmd->cmnd[0]) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 113ca9c8934c..73916adb8f80 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2455 +# define AAC_DRIVER_BUILD 2456 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -34,8 +34,8 @@ #define CONTAINER_TO_ID(cont) (cont) #define CONTAINER_TO_LUN(cont) (0) -#define aac_phys_to_logical(x) (x+1) -#define aac_logical_to_phys(x) (x?x-1:0) +#define aac_phys_to_logical(x) ((x)+1) +#define aac_logical_to_phys(x) ((x)?(x)-1:0) /* #define AAC_DETAILED_STATUS_INFO */ @@ -424,6 +424,8 @@ struct aac_init */ __le32 InitFlags; /* flags for supported features */ #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 +#define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 +#define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 __le32 MaxIoCommands; /* max outstanding commands */ __le32 MaxIoSize; /* largest I/O command */ __le32 MaxFibSize; /* largest FIB to adapter */ @@ -867,8 +869,10 @@ struct aac_supplement_adapter_info }; #define AAC_FEATURE_FALCON cpu_to_le32(0x00000010) #define AAC_FEATURE_JBOD cpu_to_le32(0x08000000) -#define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001) -#define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) +/* SupportedOptions2 */ +#define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001) +#define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) +#define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) #define AAC_SIS_VERSION_V3 3 #define AAC_SIS_SLOT_UNKNOWN 0xFF @@ -1148,6 +1152,7 @@ struct aac_dev #define ST_DQUOT 69 #define ST_STALE 70 #define ST_REMOTE 71 +#define ST_NOT_READY 72 #define ST_BADHANDLE 10001 #define ST_NOT_SYNC 10002 #define ST_BAD_COOKIE 10003 @@ -1269,6 +1274,18 @@ struct aac_synchronize_reply { u8 data[16]; }; +#define CT_POWER_MANAGEMENT 245 +#define CT_PM_START_UNIT 2 +#define CT_PM_STOP_UNIT 3 +#define CT_PM_UNIT_IMMEDIATE 1 +struct aac_power_management { + __le32 command; /* VM_ContainerConfig */ + __le32 type; /* CT_POWER_MANAGEMENT */ + __le32 sub; /* CT_PM_* */ + __le32 cid; + __le32 parm; /* CT_PM_sub_* */ +}; + #define CT_PAUSE_IO 65 #define CT_RELEASE_IO 66 struct aac_pause { @@ -1536,6 +1553,7 @@ struct aac_mntent { #define FSCS_NOTCLEAN 0x0001 /* fsck is necessary before mounting */ #define FSCS_READONLY 0x0002 /* possible result of broken mirror */ #define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */ +#define FSCS_NOT_READY 0x0008 /* Array spinning up to fulfil request */ struct aac_query_mount { __le32 command; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 294a802450be..cbac06355107 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -97,6 +97,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); } + init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME | + INITFLAGS_DRIVER_SUPPORTS_PM); init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); init->MaxFibSize = cpu_to_le32(dev->max_fib_size); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index ef67816a6fe5..289304aab690 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -515,7 +515,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } udelay(5); } - } else if (down_interruptible(&fibptr->event_wait) == 0) { + } else if (down_interruptible(&fibptr->event_wait)) { fibptr->done = 2; up(&fibptr->event_wait); } @@ -906,15 +906,22 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) case AifEnAddJBOD: case AifEnDeleteJBOD: container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); - if ((container >> 28)) + if ((container >> 28)) { + container = (u32)-1; break; + } channel = (container >> 24) & 0xF; - if (channel >= dev->maximum_num_channels) + if (channel >= dev->maximum_num_channels) { + container = (u32)-1; break; + } id = container & 0xFFFF; - if (id >= dev->maximum_num_physicals) + if (id >= dev->maximum_num_physicals) { + container = (u32)-1; break; + } lun = (container >> 16) & 0xFF; + container = (u32)-1; channel = aac_phys_to_logical(channel); device_config_needed = (((__le32 *)aifcmd->data)[0] == @@ -933,13 +940,18 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) case EM_DRIVE_REMOVAL: container = le32_to_cpu( ((__le32 *)aifcmd->data)[2]); - if ((container >> 28)) + if ((container >> 28)) { + container = (u32)-1; break; + } channel = (container >> 24) & 0xF; - if (channel >= dev->maximum_num_channels) + if (channel >= dev->maximum_num_channels) { + container = (u32)-1; break; + } id = container & 0xFFFF; lun = (container >> 16) & 0xFF; + container = (u32)-1; if (id >= dev->maximum_num_physicals) { /* legacy dev_t ? */ if ((0x2000 <= id) || lun || channel || @@ -1025,9 +1037,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) break; } + container = 0; +retry_next: if (device_config_needed == NOTHING) - for (container = 0; container < dev->maximum_num_containers; - ++container) { + for (; container < dev->maximum_num_containers; ++container) { if ((dev->fsa_dev[container].config_waiting_on == 0) && (dev->fsa_dev[container].config_needed != NOTHING) && time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) { @@ -1110,6 +1123,11 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) } if (device_config_needed == ADD) scsi_add_device(dev->scsi_host_ptr, channel, id, lun); + if (channel == CONTAINER_CHANNEL) { + container++; + device_config_needed = NOTHING; + goto retry_next; + } } static int _aac_reset_adapter(struct aac_dev *aac, int forced) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c109f63f8279..1f7c83607f84 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -401,6 +401,8 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; + if (aac->jbod && (sdev->type == TYPE_DISK)) + sdev->removable = 1; if ((sdev->type == TYPE_DISK) && (sdev_channel(sdev) != CONTAINER_CHANNEL) && (!aac->jbod || sdev->inq_periph_qual) && @@ -809,6 +811,12 @@ static ssize_t aac_show_flags(struct device *cdev, "SAI_READ_CAPACITY_16\n"); if (dev->jbod) len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n"); + if (dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_POWER_MANAGEMENT) + len += snprintf(buf + len, PAGE_SIZE - len, + "SUPPORTED_POWER_MANAGEMENT\n"); + if (dev->msi) + len += snprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n"); return len; } @@ -1106,7 +1114,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, aac->pdev = pdev; aac->name = aac_driver_template.name; aac->id = shost->unique_id; - aac->cardtype = index; + aac->cardtype = index; INIT_LIST_HEAD(&aac->entry); aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL); @@ -1146,19 +1154,19 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, goto out_deinit; /* - * Lets override negotiations and drop the maximum SG limit to 34 - */ + * Lets override negotiations and drop the maximum SG limit to 34 + */ if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) && (shost->sg_tablesize > 34)) { shost->sg_tablesize = 34; shost->max_sectors = (shost->sg_tablesize * 8) + 112; - } + } - if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && + if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && (shost->sg_tablesize > 17)) { shost->sg_tablesize = 17; shost->max_sectors = (shost->sg_tablesize * 8) + 112; - } + } error = pci_set_dma_max_seg_size(pdev, (aac->adapter_info.options & AAC_OPT_NEW_COMM) ? @@ -1174,7 +1182,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, else aac->printf_enabled = 0; - /* + /* * max channel will be the physical channels plus 1 virtual channel * all containers are on the virtual channel 0 (CONTAINER_CHANNEL) * physical channels are address by their actual physical number+1 diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index f5215fd4b73d..0899cb61e3dd 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -3582,7 +3582,7 @@ static int checksetup(struct aha152x_setup *setup) if (i == ARRAY_SIZE(ports)) return 0; - if ( request_region(setup->io_port, IO_RANGE, "aha152x")==0 ) { + if (!request_region(setup->io_port, IO_RANGE, "aha152x")) { printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port); return 0; } @@ -3830,7 +3830,7 @@ static int __init aha152x_init(void) iounmap(p); } if (!ok && setup_count == 0) - return 0; + return -ENODEV; printk(KERN_INFO "aha152x: BIOS test: passed, "); #else @@ -3842,7 +3842,7 @@ static int __init aha152x_init(void) if ((setup_count == 1) && (setup[0].io_port == ports[i])) continue; - if ( request_region(ports[i], IO_RANGE, "aha152x")==0 ) { + if (!request_region(ports[i], IO_RANGE, "aha152x")) { printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]); continue; } @@ -3909,14 +3909,14 @@ static int __init aha152x_init(void) #endif } - return 1; + return 0; } static void __exit aha152x_exit(void) { - struct aha152x_hostdata *hd; + struct aha152x_hostdata *hd, *tmp; - list_for_each_entry(hd, &aha152x_host_list, host_list) { + list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) { struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata); aha152x_release(shost); diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 90f5e0a6f2e3..2a730c470f62 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -529,10 +529,10 @@ static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha) /* The first entry, 0, is used for dynamic ids, the rest for devices * we know about. */ -static struct asd_pcidev_struct { +static const struct asd_pcidev_struct { const char * name; int (*setup)(struct asd_ha_struct *asd_ha); -} asd_pcidev_data[] = { +} asd_pcidev_data[] __devinitconst = { /* Id 0 is used for dynamic ids. */ { .name = "Adaptec AIC-94xx SAS/SATA Host Adapter", .setup = asd_aic9410_setup @@ -735,7 +735,7 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha) static int __devinit asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - struct asd_pcidev_struct *asd_dev; + const struct asd_pcidev_struct *asd_dev; unsigned asd_id = (unsigned) id->driver_data; struct asd_ha_struct *asd_ha; struct Scsi_Host *shost; diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index db6de5e6afb3..7d311541c76c 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -747,7 +747,7 @@ static void send_s870(struct atp_unit *dev,unsigned char c) dev->quhd[c] = 0; } workreq = dev->quereq[c][dev->quhd[c]]; - if (dev->id[c][scmd_id(workreq)].curr_req == 0) { + if (dev->id[c][scmd_id(workreq)].curr_req == NULL) { dev->id[c][scmd_id(workreq)].curr_req = workreq; dev->last_cmd[c] = scmd_id(workreq); goto cmd_subp; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 75c84d7b9ce8..c4b938bc30d3 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -910,9 +910,9 @@ static int ch_probe(struct device *dev) ch->minor = minor; sprintf(ch->name,"ch%d",ch->minor); - class_dev = device_create(ch_sysfs_class, dev, - MKDEV(SCSI_CHANGER_MAJOR,ch->minor), - "s%s", ch->name); + class_dev = device_create_drvdata(ch_sysfs_class, dev, + MKDEV(SCSI_CHANGER_MAJOR, ch->minor), + ch, "s%s", ch->name); if (IS_ERR(class_dev)) { printk(KERN_WARNING "ch%d: device_create failed\n", ch->minor); @@ -926,7 +926,6 @@ static int ch_probe(struct device *dev) if (init) ch_init_elem(ch); - dev_set_drvdata(dev, ch); sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); return 0; diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 403a7f2d8f9b..9785d7384199 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -28,7 +28,6 @@ #define SERVICE_ACTION_OUT_12 0xa9 #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f -#define VARIABLE_LENGTH_CMD 0x7f @@ -210,7 +209,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short variable length command, " "len=%d ext_len=%d", len, cdb_len); @@ -300,7 +299,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) cdb0 = cdbp[0]; switch(cdb0) { case VARIABLE_LENGTH_CMD: - len = cdbp[7] + 8; + len = scsi_varlen_cdb_length(cdbp); if (len < 10) { printk("short opcode=0x%x command, len=%d " "ext_len=%d", cdb0, len, cdb_len); @@ -335,10 +334,7 @@ void __scsi_print_command(unsigned char *cdb) int k, len; print_opcode_name(cdb, 0); - if (VARIABLE_LENGTH_CMD == cdb[0]) - len = cdb[7] + 8; - else - len = COMMAND_SIZE(cdb[0]); + len = scsi_command_size(cdb); /* print out all bytes in cdb */ for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h index cc784e8f6e9d..f60236721e0d 100644 --- a/drivers/scsi/dpt/dpti_ioctl.h +++ b/drivers/scsi/dpt/dpti_ioctl.h @@ -89,7 +89,7 @@ typedef struct { int njobs; /* # of jobs sent to HA */ int qdepth; /* Controller queue depth. */ int wakebase; /* mpx wakeup base index. */ - uLONG SGsize; /* Scatter/Gather list size. */ + uINT SGsize; /* Scatter/Gather list size. */ unsigned heads; /* heads for drives on cntlr. */ unsigned sectors; /* sectors for drives on cntlr. */ uCHAR do_drive32; /* Flag for Above 16 MB Ability */ @@ -97,8 +97,8 @@ typedef struct { char idPAL[4]; /* 4 Bytes Of The ID Pal */ uCHAR primary; /* 1 For Primary, 0 For Secondary */ uCHAR eataVersion; /* EATA Version */ - uLONG cpLength; /* EATA Command Packet Length */ - uLONG spLength; /* EATA Status Packet Length */ + uINT cpLength; /* EATA Command Packet Length */ + uINT spLength; /* EATA Status Packet Length */ uCHAR drqNum; /* DRQ Index (0,5,6,7) */ uCHAR flag1; /* EATA Flags 1 (Byte 9) */ uCHAR flag2; /* EATA Flags 2 (Byte 30) */ @@ -107,23 +107,23 @@ typedef struct { typedef struct { uSHORT length; // Remaining length of this uSHORT drvrHBAnum; // Relative HBA # used by the driver - uLONG baseAddr; // Base I/O address + uINT baseAddr; // Base I/O address uSHORT blinkState; // Blink LED state (0=Not in blink LED) uCHAR pciBusNum; // PCI Bus # (Optional) uCHAR pciDeviceNum; // PCI Device # (Optional) uSHORT hbaFlags; // Miscellaneous HBA flags uSHORT Interrupt; // Interrupt set for this device. # if (defined(_DPT_ARC)) - uLONG baseLength; + uINT baseLength; ADAPTER_OBJECT *AdapterObject; LARGE_INTEGER DmaLogicalAddress; PVOID DmaVirtualAddress; LARGE_INTEGER ReplyLogicalAddress; PVOID ReplyVirtualAddress; # else - uLONG reserved1; // Reserved for future expansion - uLONG reserved2; // Reserved for future expansion - uLONG reserved3; // Reserved for future expansion + uINT reserved1; // Reserved for future expansion + uINT reserved2; // Reserved for future expansion + uINT reserved3; // Reserved for future expansion # endif } drvrHBAinfo_S; diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h index 94bc894d1200..a6644b332b53 100644 --- a/drivers/scsi/dpt/dptsig.h +++ b/drivers/scsi/dpt/dptsig.h @@ -33,11 +33,7 @@ /* to make sure we are talking the same size under all OS's */ typedef unsigned char sigBYTE; typedef unsigned short sigWORD; -#if (defined(_MULTI_DATAMODEL) && defined(sun) && !defined(_ILP32)) -typedef uint32_t sigLONG; -#else -typedef unsigned long sigLONG; -#endif +typedef unsigned int sigINT; /* * use sigWORDLittleEndian for: @@ -89,7 +85,7 @@ typedef unsigned long sigLONG; /* ------------------------------------------------------------------ */ /* What type of processor the file is meant to run on. */ /* This will let us know whether to read sigWORDs as high/low or low/high. */ -#define PROC_INTEL 0x00 /* Intel 80x86 */ +#define PROC_INTEL 0x00 /* Intel 80x86/ia64 */ #define PROC_MOTOROLA 0x01 /* Motorola 68K */ #define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */ #define PROC_ALPHA 0x03 /* DEC Alpha */ @@ -108,6 +104,7 @@ typedef unsigned long sigLONG; #define PROC_486 0x08 /* Intel 80486 */ #define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */ #define PROC_SEXIUM 0x20 /* Intel 686 aka P6 aka Pentium Pro or MMX */ +#define PROC_IA64 0x40 /* Intel IA64 processor */ /* PROC_i960: */ #define PROC_960RX 0x01 /* Intel 80960RC/RD */ @@ -300,7 +297,7 @@ typedef struct dpt_sig { sigBYTE dsFiletype; /* type of file */ sigBYTE dsFiletypeFlags; /* flags to specify load type, etc. */ sigBYTE dsOEM; /* OEM file was created for */ - sigLONG dsOS; /* which Operating systems */ + sigINT dsOS; /* which Operating systems */ sigWORD dsCapabilities; /* RAID levels, etc. */ sigWORD dsDeviceSupp; /* Types of SCSI devices supported */ sigWORD dsAdapterSupp; /* DPT adapter families supported */ diff --git a/drivers/scsi/dpt/sys_info.h b/drivers/scsi/dpt/sys_info.h index d23b70c8c768..a90c4cb8ea8b 100644 --- a/drivers/scsi/dpt/sys_info.h +++ b/drivers/scsi/dpt/sys_info.h @@ -145,8 +145,8 @@ uCHAR smartROMRevision; uSHORT flags; /* See bit definitions above */ uSHORT conventionalMemSize; /* in KB */ - uLONG extendedMemSize; /* in KB */ - uLONG osType; /* Same as DPTSIG's definition */ + uINT extendedMemSize; /* in KB */ + uINT osType; /* Same as DPTSIG's definition */ uCHAR osMajorVersion; uCHAR osMinorVersion; /* The OS version */ uCHAR osRevision; diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index ac92ac143b46..8508816f303d 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -29,11 +29,6 @@ /*#define DEBUG 1 */ /*#define UARTDELAY 1 */ -/* On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates - high pages. Keep the macro around because of the broken unmerged ia64 tree */ - -#define ADDR32 (0) - #include <linux/module.h> MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn"); @@ -108,27 +103,28 @@ static dpt_sig_S DPTI_sig = { static DEFINE_MUTEX(adpt_configuration_lock); -static struct i2o_sys_tbl *sys_tbl = NULL; -static int sys_tbl_ind = 0; -static int sys_tbl_len = 0; +static struct i2o_sys_tbl *sys_tbl; +static dma_addr_t sys_tbl_pa; +static int sys_tbl_ind; +static int sys_tbl_len; static adpt_hba* hba_chain = NULL; static int hba_count = 0; +static struct class *adpt_sysfs_class; + +#ifdef CONFIG_COMPAT +static long compat_adpt_ioctl(struct file *, unsigned int, unsigned long); +#endif + static const struct file_operations adpt_fops = { .ioctl = adpt_ioctl, .open = adpt_open, - .release = adpt_close -}; - -#ifdef REBOOT_NOTIFIER -static struct notifier_block adpt_reboot_notifier = -{ - adpt_reboot_event, - NULL, - 0 -}; + .release = adpt_close, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_adpt_ioctl, #endif +}; /* Structures and definitions for synchronous message posting. * See adpt_i2o_post_wait() for description @@ -151,6 +147,21 @@ static DEFINE_SPINLOCK(adpt_post_wait_lock); *============================================================================ */ +static inline int dpt_dma64(adpt_hba *pHba) +{ + return (sizeof(dma_addr_t) > 4 && (pHba)->dma64); +} + +static inline u32 dma_high(dma_addr_t addr) +{ + return upper_32_bits(addr); +} + +static inline u32 dma_low(dma_addr_t addr) +{ + return (u32)addr; +} + static u8 adpt_read_blink_led(adpt_hba* host) { if (host->FwDebugBLEDflag_P) { @@ -178,8 +189,6 @@ static int adpt_detect(struct scsi_host_template* sht) struct pci_dev *pDev = NULL; adpt_hba* pHba; - adpt_init(); - PINFO("Detecting Adaptec I2O RAID controllers...\n"); /* search for all Adatpec I2O RAID cards */ @@ -247,13 +256,29 @@ rebuild_sys_tab: adpt_inquiry(pHba); } + adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o"); + if (IS_ERR(adpt_sysfs_class)) { + printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n"); + adpt_sysfs_class = NULL; + } + for (pHba = hba_chain; pHba; pHba = pHba->next) { - if( adpt_scsi_register(pHba,sht) < 0){ + if (adpt_scsi_host_alloc(pHba, sht) < 0){ adpt_i2o_delete_hba(pHba); continue; } pHba->initialized = TRUE; pHba->state &= ~DPTI_STATE_RESET; + if (adpt_sysfs_class) { + struct device *dev = device_create(adpt_sysfs_class, + NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), + "dpti%d", pHba->unit); + if (IS_ERR(dev)) { + printk(KERN_WARNING"dpti%d: unable to " + "create device in dpt_i2o class\n", + pHba->unit); + } + } } // Register our control device node @@ -282,7 +307,7 @@ static int adpt_release(struct Scsi_Host *host) static void adpt_inquiry(adpt_hba* pHba) { - u32 msg[14]; + u32 msg[17]; u32 *mptr; u32 *lenptr; int direction; @@ -290,11 +315,12 @@ static void adpt_inquiry(adpt_hba* pHba) u32 len; u32 reqlen; u8* buf; + dma_addr_t addr; u8 scb[16]; s32 rcode; memset(msg, 0, sizeof(msg)); - buf = kmalloc(80,GFP_KERNEL|ADDR32); + buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL); if(!buf){ printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name); return; @@ -305,7 +331,10 @@ static void adpt_inquiry(adpt_hba* pHba) direction = 0x00000000; scsidir =0x40000000; // DATA IN (iop<--dev) - reqlen = 14; // SINGLE SGE + if (dpt_dma64(pHba)) + reqlen = 17; // SINGLE SGE, 64 bit + else + reqlen = 14; // SINGLE SGE, 32 bit /* Stick the headers on */ msg[0] = reqlen<<16 | SGL_OFFSET_12; msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID); @@ -338,8 +367,16 @@ static void adpt_inquiry(adpt_hba* pHba) /* Now fill in the SGList and command */ *lenptr = len; - *mptr++ = 0xD0000000|direction|len; - *mptr++ = virt_to_bus(buf); + if (dpt_dma64(pHba)) { + *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ + *mptr++ = 1 << PAGE_SHIFT; + *mptr++ = 0xD0000000|direction|len; + *mptr++ = dma_low(addr); + *mptr++ = dma_high(addr); + } else { + *mptr++ = 0xD0000000|direction|len; + *mptr++ = addr; + } // Send it on it's way rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120); @@ -347,7 +384,7 @@ static void adpt_inquiry(adpt_hba* pHba) sprintf(pHba->detail, "Adaptec I2O RAID"); printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); if (rcode != -ETIME && rcode != -EINTR) - kfree(buf); + dma_free_coherent(&pHba->pDev->dev, 80, buf, addr); } else { memset(pHba->detail, 0, sizeof(pHba->detail)); memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); @@ -356,7 +393,7 @@ static void adpt_inquiry(adpt_hba* pHba) memcpy(&(pHba->detail[40]), " FW: ", 4); memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); pHba->detail[48] = '\0'; /* precautionary */ - kfree(buf); + dma_free_coherent(&pHba->pDev->dev, 80, buf, addr); } adpt_i2o_status_get(pHba); return ; @@ -632,6 +669,91 @@ stop_output: return len; } +/* + * Turn a struct scsi_cmnd * into a unique 32 bit 'context'. + */ +static u32 adpt_cmd_to_context(struct scsi_cmnd *cmd) +{ + return (u32)cmd->serial_number; +} + +/* + * Go from a u32 'context' to a struct scsi_cmnd * . + * This could probably be made more efficient. + */ +static struct scsi_cmnd * + adpt_cmd_from_context(adpt_hba * pHba, u32 context) +{ + struct scsi_cmnd * cmd; + struct scsi_device * d; + + if (context == 0) + return NULL; + + spin_unlock(pHba->host->host_lock); + shost_for_each_device(d, pHba->host) { + unsigned long flags; + spin_lock_irqsave(&d->list_lock, flags); + list_for_each_entry(cmd, &d->cmd_list, list) { + if (((u32)cmd->serial_number == context)) { + spin_unlock_irqrestore(&d->list_lock, flags); + scsi_device_put(d); + spin_lock(pHba->host->host_lock); + return cmd; + } + } + spin_unlock_irqrestore(&d->list_lock, flags); + } + spin_lock(pHba->host->host_lock); + + return NULL; +} + +/* + * Turn a pointer to ioctl reply data into an u32 'context' + */ +static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply) +{ +#if BITS_PER_LONG == 32 + return (u32)(unsigned long)reply; +#else + ulong flags = 0; + u32 nr, i; + + spin_lock_irqsave(pHba->host->host_lock, flags); + nr = ARRAY_SIZE(pHba->ioctl_reply_context); + for (i = 0; i < nr; i++) { + if (pHba->ioctl_reply_context[i] == NULL) { + pHba->ioctl_reply_context[i] = reply; + break; + } + } + spin_unlock_irqrestore(pHba->host->host_lock, flags); + if (i >= nr) { + kfree (reply); + printk(KERN_WARNING"%s: Too many outstanding " + "ioctl commands\n", pHba->name); + return (u32)-1; + } + + return i; +#endif +} + +/* + * Go from an u32 'context' to a pointer to ioctl reply data. + */ +static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context) +{ +#if BITS_PER_LONG == 32 + return (void *)(unsigned long)context; +#else + void *p = pHba->ioctl_reply_context[context]; + pHba->ioctl_reply_context[context] = NULL; + + return p; +#endif +} /*=========================================================================== * Error Handling routines @@ -660,7 +782,7 @@ static int adpt_abort(struct scsi_cmnd * cmd) msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; msg[2] = 0; msg[3]= 0; - msg[4] = (u32)cmd; + msg[4] = adpt_cmd_to_context(cmd); if (pHba->host) spin_lock_irq(pHba->host->host_lock); rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER); @@ -861,27 +983,6 @@ static void adpt_i2o_sys_shutdown(void) printk(KERN_INFO "Adaptec I2O controllers down.\n"); } -/* - * reboot/shutdown notification. - * - * - Quiesce each IOP in the system - * - */ - -#ifdef REBOOT_NOTIFIER -static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p) -{ - - if(code != SYS_RESTART && code != SYS_HALT && code != SYS_POWER_OFF) - return NOTIFY_DONE; - - adpt_i2o_sys_shutdown(); - - return NOTIFY_DONE; -} -#endif - - static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) { @@ -893,6 +994,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev u32 hba_map1_area_size = 0; void __iomem *base_addr_virt = NULL; void __iomem *msg_addr_virt = NULL; + int dma64 = 0; int raptorFlag = FALSE; @@ -906,9 +1008,21 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev } pci_set_master(pDev); - if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) + + /* + * See if we should enable dma64 mode. + */ + if (sizeof(dma_addr_t) > 4 && + pci_set_dma_mask(pDev, DMA_64BIT_MASK) == 0) { + if (dma_get_required_mask(&pDev->dev) > DMA_32BIT_MASK) + dma64 = 1; + } + if (!dma64 && pci_set_dma_mask(pDev, DMA_32BIT_MASK) != 0) return -EINVAL; + /* adapter only supports message blocks below 4GB */ + pci_set_consistent_dma_mask(pDev, DMA_32BIT_MASK); + base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); @@ -929,6 +1043,25 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev raptorFlag = TRUE; } +#if BITS_PER_LONG == 64 + /* + * The original Adaptec 64 bit driver has this comment here: + * "x86_64 machines need more optimal mappings" + * + * I assume some HBAs report ridiculously large mappings + * and we need to limit them on platforms with IOMMUs. + */ + if (raptorFlag == TRUE) { + if (hba_map0_area_size > 128) + hba_map0_area_size = 128; + if (hba_map1_area_size > 524288) + hba_map1_area_size = 524288; + } else { + if (hba_map0_area_size > 524288) + hba_map0_area_size = 524288; + } +#endif + base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { pci_release_regions(pDev); @@ -991,16 +1124,22 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev pHba->state = DPTI_STATE_RESET; pHba->pDev = pDev; pHba->devices = NULL; + pHba->dma64 = dma64; // Initializing the spinlocks spin_lock_init(&pHba->state_lock); spin_lock_init(&adpt_post_wait_lock); if(raptorFlag == 0){ - printk(KERN_INFO"Adaptec I2O RAID controller %d at %p size=%x irq=%d\n", - hba_count-1, base_addr_virt, hba_map0_area_size, pDev->irq); + printk(KERN_INFO "Adaptec I2O RAID controller" + " %d at %p size=%x irq=%d%s\n", + hba_count-1, base_addr_virt, + hba_map0_area_size, pDev->irq, + dma64 ? " (64-bit DMA)" : ""); } else { - printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d\n",hba_count-1, pDev->irq); + printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d%s\n", + hba_count-1, pDev->irq, + dma64 ? " (64-bit DMA)" : ""); printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size); printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size); } @@ -1053,10 +1192,26 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } - kfree(pHba->hrt); - kfree(pHba->lct); - kfree(pHba->status_block); - kfree(pHba->reply_pool); + if(pHba->FwDebugBuffer_P) + iounmap(pHba->FwDebugBuffer_P); + if(pHba->hrt) { + dma_free_coherent(&pHba->pDev->dev, + pHba->hrt->num_entries * pHba->hrt->entry_len << 2, + pHba->hrt, pHba->hrt_pa); + } + if(pHba->lct) { + dma_free_coherent(&pHba->pDev->dev, pHba->lct_size, + pHba->lct, pHba->lct_pa); + } + if(pHba->status_block) { + dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block), + pHba->status_block, pHba->status_block_pa); + } + if(pHba->reply_pool) { + dma_free_coherent(&pHba->pDev->dev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + pHba->reply_pool, pHba->reply_pool_pa); + } for(d = pHba->devices; d ; d = next){ next = d->next; @@ -1075,23 +1230,19 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) pci_dev_put(pHba->pDev); kfree(pHba); + if (adpt_sysfs_class) + device_destroy(adpt_sysfs_class, + MKDEV(DPTI_I2O_MAJOR, pHba->unit)); + if(hba_count <= 0){ unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER); + if (adpt_sysfs_class) { + class_destroy(adpt_sysfs_class); + adpt_sysfs_class = NULL; + } } } - -static int adpt_init(void) -{ - printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); -#ifdef REBOOT_NOTIFIER - register_reboot_notifier(&adpt_reboot_notifier); -#endif - - return 0; -} - - static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) { struct adpt_device* d; @@ -1283,6 +1434,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) { u32 msg[8]; u8* status; + dma_addr_t addr; u32 m = EMPTY_QUEUE ; ulong timeout = jiffies + (TMOUT_IOPRESET*HZ); @@ -1305,12 +1457,13 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); - status = kzalloc(4, GFP_KERNEL|ADDR32); + status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL); if(status == NULL) { adpt_send_nop(pHba, m); printk(KERN_ERR"IOP reset failed - no free memory.\n"); return -ENOMEM; } + memset(status,0,4); msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; @@ -1318,8 +1471,8 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) msg[3]=0; msg[4]=0; msg[5]=0; - msg[6]=virt_to_bus(status); - msg[7]=0; + msg[6]=dma_low(addr); + msg[7]=dma_high(addr); memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg)); wmb(); @@ -1329,7 +1482,10 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) while(*status == 0){ if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name); - kfree(status); + /* We lose 4 bytes of "status" here, but we cannot + free these because controller may awake and corrupt + those bytes at any time */ + /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */ return -ETIMEDOUT; } rmb(); @@ -1348,6 +1504,10 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) } if(time_after(jiffies,timeout)){ printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); + /* We lose 4 bytes of "status" here, but we + cannot free these because controller may + awake and corrupt those bytes at any time */ + /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */ return -ETIMEDOUT; } schedule_timeout_uninterruptible(1); @@ -1364,7 +1524,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) PDEBUG("%s: Reset completed.\n", pHba->name); } - kfree(status); + dma_free_coherent(&pHba->pDev->dev, 4, status, addr); #ifdef UARTDELAY // This delay is to allow someone attached to the card through the debug UART to // set up the dump levels that they want before the rest of the initialization sequence @@ -1636,6 +1796,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) u32 i = 0; u32 rcode = 0; void *p = NULL; + dma_addr_t addr; ulong flags = 0; memset(&msg, 0, MAX_MESSAGE_SIZE*4); @@ -1668,10 +1829,13 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) } sg_offset = (msg[0]>>4)&0xf; msg[2] = 0x40000000; // IOCTL context - msg[3] = (u32)reply; + msg[3] = adpt_ioctl_to_context(pHba, reply); + if (msg[3] == (u32)-1) + return -EBUSY; + memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize); if(sg_offset) { - // TODO 64bit fix + // TODO add 64 bit API struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset); sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); if (sg_count > pHba->sg_tablesize){ @@ -1690,7 +1854,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) } sg_size = sg[i].flag_count & 0xffffff; /* Allocate memory for the transfer */ - p = kmalloc(sg_size, GFP_KERNEL|ADDR32); + p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL); if(!p) { printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", pHba->name,sg_size,i,sg_count); @@ -1700,15 +1864,15 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. /* Copy in the user's SG buffer if necessary */ if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { - // TODO 64bit fix - if (copy_from_user(p,(void __user *)sg[i].addr_bus, sg_size)) { + // sg_simple_element API is 32 bit + if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) { printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i); rcode = -EFAULT; goto cleanup; } } - //TODO 64bit fix - sg[i].addr_bus = (u32)virt_to_bus(p); + /* sg_simple_element API is 32 bit, but addr < 4GB */ + sg[i].addr_bus = addr; } } @@ -1736,7 +1900,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) if(sg_offset) { /* Copy back the Scatter Gather buffers back to user space */ u32 j; - // TODO 64bit fix + // TODO add 64 bit API struct sg_simple_element* sg; int sg_size; @@ -1756,14 +1920,14 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) } sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); - // TODO 64bit fix + // TODO add 64 bit API sg = (struct sg_simple_element*)(msg + sg_offset); for (j = 0; j < sg_count; j++) { /* Copy out the SG list to user's buffer if necessary */ if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { sg_size = sg[j].flag_count & 0xffffff; - // TODO 64bit fix - if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) { + // sg_simple_element API is 32 bit + if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) { printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus); rcode = -EFAULT; goto cleanup; @@ -1787,56 +1951,22 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) cleanup: - if (rcode != -ETIME && rcode != -EINTR) + if (rcode != -ETIME && rcode != -EINTR) { + struct sg_simple_element *sg = + (struct sg_simple_element*) (msg +sg_offset); kfree (reply); - while(sg_index) { - if(sg_list[--sg_index]) { - if (rcode != -ETIME && rcode != -EINTR) - kfree(sg_list[sg_index]); + while(sg_index) { + if(sg_list[--sg_index]) { + dma_free_coherent(&pHba->pDev->dev, + sg[sg_index].flag_count & 0xffffff, + sg_list[sg_index], + sg[sg_index].addr_bus); + } } } return rcode; } - -/* - * This routine returns information about the system. This does not effect - * any logic and if the info is wrong - it doesn't matter. - */ - -/* Get all the info we can not get from kernel services */ -static int adpt_system_info(void __user *buffer) -{ - sysInfo_S si; - - memset(&si, 0, sizeof(si)); - - si.osType = OS_LINUX; - si.osMajorVersion = 0; - si.osMinorVersion = 0; - si.osRevision = 0; - si.busType = SI_PCI_BUS; - si.processorFamily = DPTI_sig.dsProcessorFamily; - -#if defined __i386__ - adpt_i386_info(&si); -#elif defined (__ia64__) - adpt_ia64_info(&si); -#elif defined(__sparc__) - adpt_sparc_info(&si); -#elif defined (__alpha__) - adpt_alpha_info(&si); -#else - si.processorType = 0xff ; -#endif - if(copy_to_user(buffer, &si, sizeof(si))){ - printk(KERN_WARNING"dpti: Could not copy buffer TO user\n"); - return -EFAULT; - } - - return 0; -} - #if defined __ia64__ static void adpt_ia64_info(sysInfo_S* si) { @@ -1847,7 +1977,6 @@ static void adpt_ia64_info(sysInfo_S* si) } #endif - #if defined __sparc__ static void adpt_sparc_info(sysInfo_S* si) { @@ -1857,7 +1986,6 @@ static void adpt_sparc_info(sysInfo_S* si) si->processorType = PROC_ULTRASPARC; } #endif - #if defined __alpha__ static void adpt_alpha_info(sysInfo_S* si) { @@ -1869,7 +1997,6 @@ static void adpt_alpha_info(sysInfo_S* si) #endif #if defined __i386__ - static void adpt_i386_info(sysInfo_S* si) { // This is all the info we need for now @@ -1890,9 +2017,45 @@ static void adpt_i386_info(sysInfo_S* si) break; } } +#endif +/* + * This routine returns information about the system. This does not effect + * any logic and if the info is wrong - it doesn't matter. + */ + +/* Get all the info we can not get from kernel services */ +static int adpt_system_info(void __user *buffer) +{ + sysInfo_S si; + + memset(&si, 0, sizeof(si)); + + si.osType = OS_LINUX; + si.osMajorVersion = 0; + si.osMinorVersion = 0; + si.osRevision = 0; + si.busType = SI_PCI_BUS; + si.processorFamily = DPTI_sig.dsProcessorFamily; + +#if defined __i386__ + adpt_i386_info(&si); +#elif defined (__ia64__) + adpt_ia64_info(&si); +#elif defined(__sparc__) + adpt_sparc_info(&si); +#elif defined (__alpha__) + adpt_alpha_info(&si); +#else + si.processorType = 0xff ; #endif + if (copy_to_user(buffer, &si, sizeof(si))){ + printk(KERN_WARNING"dpti: Could not copy buffer TO user\n"); + return -EFAULT; + } + return 0; +} static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) @@ -1978,6 +2141,38 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, return error; } +#ifdef CONFIG_COMPAT +static long compat_adpt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct inode *inode; + long ret; + + inode = file->f_dentry->d_inode; + + lock_kernel(); + + switch(cmd) { + case DPT_SIGNATURE: + case I2OUSRCMD: + case DPT_CTRLINFO: + case DPT_SYSINFO: + case DPT_BLINKLED: + case I2ORESETCMD: + case I2ORESCANCMD: + case (DPT_TARGET_BUSY & 0xFFFF): + case DPT_TARGET_BUSY: + ret = adpt_ioctl(inode, file, cmd, arg); + break; + default: + ret = -ENOIOCTLCMD; + } + + unlock_kernel(); + + return ret; +} +#endif static irqreturn_t adpt_isr(int irq, void *dev_id) { @@ -2009,7 +2204,16 @@ static irqreturn_t adpt_isr(int irq, void *dev_id) goto out; } } - reply = bus_to_virt(m); + if (pHba->reply_pool_pa <= m && + m < pHba->reply_pool_pa + + (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) { + reply = (u8 *)pHba->reply_pool + + (m - pHba->reply_pool_pa); + } else { + /* Ick, we should *never* be here */ + printk(KERN_ERR "dpti: reply frame not from pool\n"); + reply = (u8 *)bus_to_virt(m); + } if (readl(reply) & MSG_FAIL) { u32 old_m = readl(reply+28); @@ -2029,7 +2233,7 @@ static irqreturn_t adpt_isr(int irq, void *dev_id) } context = readl(reply+8); if(context & 0x40000000){ // IOCTL - void *p = (void *)readl(reply+12); + void *p = adpt_ioctl_from_context(pHba, readl(reply+12)); if( p != NULL) { memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4); } @@ -2043,15 +2247,17 @@ static irqreturn_t adpt_isr(int irq, void *dev_id) status = I2O_POST_WAIT_OK; } if(!(context & 0x40000000)) { - cmd = (struct scsi_cmnd*) readl(reply+12); + cmd = adpt_cmd_from_context(pHba, + readl(reply+12)); if(cmd != NULL) { printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); } } adpt_i2o_post_wait_complete(context, status); } else { // SCSI message - cmd = (struct scsi_cmnd*) readl(reply+12); + cmd = adpt_cmd_from_context (pHba, readl(reply+12)); if(cmd != NULL){ + scsi_dma_unmap(cmd); if(cmd->serial_number != 0) { // If not timedout adpt_i2o_to_scsi(reply, cmd); } @@ -2072,6 +2278,7 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d int i; u32 msg[MAX_MESSAGE_SIZE]; u32* mptr; + u32* lptr; u32 *lenptr; int direction; int scsidir; @@ -2079,6 +2286,7 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d u32 len; u32 reqlen; s32 rcode; + dma_addr_t addr; memset(msg, 0 , sizeof(msg)); len = scsi_bufflen(cmd); @@ -2118,7 +2326,7 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d // I2O_CMD_SCSI_EXEC msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); msg[2] = 0; - msg[3] = (u32)cmd; /* We want the SCSI control block back */ + msg[3] = adpt_cmd_to_context(cmd); /* Want SCSI control block back */ // Our cards use the transaction context as the tag for queueing // Adaptec/DPT Private stuff msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); @@ -2136,7 +2344,13 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d memcpy(mptr, cmd->cmnd, cmd->cmd_len); mptr+=4; lenptr=mptr++; /* Remember me - fill in when we know */ - reqlen = 14; // SINGLE SGE + if (dpt_dma64(pHba)) { + reqlen = 16; // SINGLE SGE + *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ + *mptr++ = 1 << PAGE_SHIFT; + } else { + reqlen = 14; // SINGLE SGE + } /* Now fill in the SGList and command */ nseg = scsi_dma_map(cmd); @@ -2146,12 +2360,16 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d len = 0; scsi_for_each_sg(cmd, sg, nseg, i) { + lptr = mptr; *mptr++ = direction|0x10000000|sg_dma_len(sg); len+=sg_dma_len(sg); - *mptr++ = sg_dma_address(sg); + addr = sg_dma_address(sg); + *mptr++ = dma_low(addr); + if (dpt_dma64(pHba)) + *mptr++ = dma_high(addr); /* Make this an end of list */ if (i == nseg - 1) - mptr[-2] = direction|0xD0000000|sg_dma_len(sg); + *lptr = direction|0xD0000000|sg_dma_len(sg); } reqlen = mptr - msg; *lenptr = len; @@ -2177,13 +2395,13 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d } -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) +static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht) { - struct Scsi_Host *host = NULL; + struct Scsi_Host *host; - host = scsi_register(sht, sizeof(adpt_hba*)); + host = scsi_host_alloc(sht, sizeof(adpt_hba*)); if (host == NULL) { - printk ("%s: scsi_register returned NULL\n",pHba->name); + printk("%s: scsi_host_alloc returned NULL\n", pHba->name); return -1; } host->hostdata[0] = (unsigned long)pHba; @@ -2200,7 +2418,7 @@ static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) host->max_lun = 256; host->max_channel = pHba->top_scsi_channel + 1; host->cmd_per_lun = 1; - host->unique_id = (uint) pHba; + host->unique_id = (u32)sys_tbl_pa + pHba->unit; host->sg_tablesize = pHba->sg_tablesize; host->can_queue = pHba->post_fifo_size; @@ -2640,11 +2858,10 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m) static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) { u8 *status; + dma_addr_t addr; u32 __iomem *msg = NULL; int i; ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ; - u32* ptr; - u32 outbound_frame; // This had to be a 32 bit address u32 m; do { @@ -2663,13 +2880,14 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - status = kzalloc(4, GFP_KERNEL|ADDR32); + status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL); if (!status) { adpt_send_nop(pHba, m); printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", pHba->name); return -ENOMEM; } + memset(status, 0, 4); writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); @@ -2678,7 +2896,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) writel(4096, &msg[4]); /* Host page frame size */ writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */ writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */ - writel(virt_to_bus(status), &msg[7]); + writel((u32)addr, &msg[7]); writel(m, pHba->post_port); wmb(); @@ -2693,6 +2911,10 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) rmb(); if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); + /* We lose 4 bytes of "status" here, but we + cannot free these because controller may + awake and corrupt those bytes at any time */ + /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */ return -ETIMEDOUT; } schedule_timeout_uninterruptible(1); @@ -2701,25 +2923,30 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) // If the command was successful, fill the fifo with our reply // message packets if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { - kfree(status); + dma_free_coherent(&pHba->pDev->dev, 4, status, addr); return -2; } - kfree(status); + dma_free_coherent(&pHba->pDev->dev, 4, status, addr); - kfree(pHba->reply_pool); + if(pHba->reply_pool != NULL) { + dma_free_coherent(&pHba->pDev->dev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + pHba->reply_pool, pHba->reply_pool_pa); + } - pHba->reply_pool = kzalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); + pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + &pHba->reply_pool_pa, GFP_KERNEL); if (!pHba->reply_pool) { printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name); return -ENOMEM; } + memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); - ptr = pHba->reply_pool; for(i = 0; i < pHba->reply_fifo_size; i++) { - outbound_frame = (u32)virt_to_bus(ptr); - writel(outbound_frame, pHba->reply_port); + writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4), + pHba->reply_port); wmb(); - ptr += REPLY_FRAME_SIZE; } adpt_i2o_status_get(pHba); return 0; @@ -2743,11 +2970,11 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) u32 m; u32 __iomem *msg; u8 *status_block=NULL; - ulong status_block_bus; if(pHba->status_block == NULL) { - pHba->status_block = (i2o_status_block*) - kmalloc(sizeof(i2o_status_block),GFP_KERNEL|ADDR32); + pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev, + sizeof(i2o_status_block), + &pHba->status_block_pa, GFP_KERNEL); if(pHba->status_block == NULL) { printk(KERN_ERR "dpti%d: Get Status Block failed; Out of memory. \n", @@ -2757,7 +2984,6 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) } memset(pHba->status_block, 0, sizeof(i2o_status_block)); status_block = (u8*)(pHba->status_block); - status_block_bus = virt_to_bus(pHba->status_block); timeout = jiffies+TMOUT_GETSTATUS*HZ; do { rmb(); @@ -2782,8 +3008,8 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) writel(0, &msg[3]); writel(0, &msg[4]); writel(0, &msg[5]); - writel(((u32)status_block_bus)&0xffffffff, &msg[6]); - writel(0, &msg[7]); + writel( dma_low(pHba->status_block_pa), &msg[6]); + writel( dma_high(pHba->status_block_pa), &msg[7]); writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes //post message @@ -2812,7 +3038,17 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) } // Calculate the Scatter Gather list size - pHba->sg_tablesize = (pHba->status_block->inbound_frame_size * 4 -40)/ sizeof(struct sg_simple_element); + if (dpt_dma64(pHba)) { + pHba->sg_tablesize + = ((pHba->status_block->inbound_frame_size * 4 + - 14 * sizeof(u32)) + / (sizeof(struct sg_simple_element) + sizeof(u32))); + } else { + pHba->sg_tablesize + = ((pHba->status_block->inbound_frame_size * 4 + - 12 * sizeof(u32)) + / sizeof(struct sg_simple_element)); + } if (pHba->sg_tablesize > SG_LIST_ELEMENTS) { pHba->sg_tablesize = SG_LIST_ELEMENTS; } @@ -2863,7 +3099,9 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) } do { if (pHba->lct == NULL) { - pHba->lct = kmalloc(pHba->lct_size, GFP_KERNEL|ADDR32); + pHba->lct = dma_alloc_coherent(&pHba->pDev->dev, + pHba->lct_size, &pHba->lct_pa, + GFP_KERNEL); if(pHba->lct == NULL) { printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n", pHba->name); @@ -2879,7 +3117,7 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) msg[4] = 0xFFFFFFFF; /* All devices */ msg[5] = 0x00000000; /* Report now */ msg[6] = 0xD0000000|pHba->lct_size; - msg[7] = virt_to_bus(pHba->lct); + msg[7] = (u32)pHba->lct_pa; if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) { printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", @@ -2890,7 +3128,8 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) if ((pHba->lct->table_size << 2) > pHba->lct_size) { pHba->lct_size = pHba->lct->table_size << 2; - kfree(pHba->lct); + dma_free_coherent(&pHba->pDev->dev, pHba->lct_size, + pHba->lct, pHba->lct_pa); pHba->lct = NULL; } } while (pHba->lct == NULL); @@ -2901,13 +3140,19 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO; if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) { pHba->FwDebugBufferSize = buf[1]; - pHba->FwDebugBuffer_P = pHba->base_addr_virt + buf[0]; - pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P + FW_DEBUG_FLAGS_OFFSET; - pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P + FW_DEBUG_BLED_OFFSET; - pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1; - pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P + FW_DEBUG_STR_LENGTH_OFFSET; - pHba->FwDebugBuffer_P += buf[2]; - pHba->FwDebugFlags = 0; + pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0], + pHba->FwDebugBufferSize); + if (pHba->FwDebugBuffer_P) { + pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P + + FW_DEBUG_FLAGS_OFFSET; + pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P + + FW_DEBUG_BLED_OFFSET; + pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1; + pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P + + FW_DEBUG_STR_LENGTH_OFFSET; + pHba->FwDebugBuffer_P += buf[2]; + pHba->FwDebugFlags = 0; + } } return 0; @@ -2915,25 +3160,30 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) static int adpt_i2o_build_sys_table(void) { - adpt_hba* pHba = NULL; + adpt_hba* pHba = hba_chain; int count = 0; + if (sys_tbl) + dma_free_coherent(&pHba->pDev->dev, sys_tbl_len, + sys_tbl, sys_tbl_pa); + sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs (hba_count) * sizeof(struct i2o_sys_tbl_entry); - kfree(sys_tbl); - - sys_tbl = kzalloc(sys_tbl_len, GFP_KERNEL|ADDR32); + sys_tbl = dma_alloc_coherent(&pHba->pDev->dev, + sys_tbl_len, &sys_tbl_pa, GFP_KERNEL); if (!sys_tbl) { printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); return -ENOMEM; } + memset(sys_tbl, 0, sys_tbl_len); sys_tbl->num_entries = hba_count; sys_tbl->version = I2OVERSION; sys_tbl->change_ind = sys_tbl_ind++; for(pHba = hba_chain; pHba; pHba = pHba->next) { + u64 addr; // Get updated Status Block so we have the latest information if (adpt_i2o_status_get(pHba)) { sys_tbl->num_entries--; @@ -2949,8 +3199,9 @@ static int adpt_i2o_build_sys_table(void) sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size; sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities; - sys_tbl->iops[count].inbound_low = (u32)virt_to_bus(pHba->post_port); - sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus(pHba->post_port)>>32); + addr = pHba->base_addr_phys + 0x40; + sys_tbl->iops[count].inbound_low = dma_low(addr); + sys_tbl->iops[count].inbound_high = dma_high(addr); count++; } @@ -3086,7 +3337,8 @@ static s32 adpt_i2o_hrt_get(adpt_hba* pHba) do { if (pHba->hrt == NULL) { - pHba->hrt=kmalloc(size, GFP_KERNEL|ADDR32); + pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev, + size, &pHba->hrt_pa, GFP_KERNEL); if (pHba->hrt == NULL) { printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name); return -ENOMEM; @@ -3098,7 +3350,7 @@ static s32 adpt_i2o_hrt_get(adpt_hba* pHba) msg[2]= 0; msg[3]= 0; msg[4]= (0xD0000000 | size); /* Simple transaction */ - msg[5]= virt_to_bus(pHba->hrt); /* Dump it here */ + msg[5]= (u32)pHba->hrt_pa; /* Dump it here */ if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) { printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret); @@ -3106,8 +3358,10 @@ static s32 adpt_i2o_hrt_get(adpt_hba* pHba) } if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) { - size = pHba->hrt->num_entries * pHba->hrt->entry_len << 2; - kfree(pHba->hrt); + int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2; + dma_free_coherent(&pHba->pDev->dev, size, + pHba->hrt, pHba->hrt_pa); + size = newsize; pHba->hrt = NULL; } } while(pHba->hrt == NULL); @@ -3121,33 +3375,54 @@ static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 *resblk; + u8 *opblk_va; + dma_addr_t opblk_pa; + u8 *resblk_va; + dma_addr_t resblk_pa; int size; /* 8 bytes for header */ - resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32); - if (resblk == NULL) { + resblk_va = dma_alloc_coherent(&pHba->pDev->dev, + sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL); + if (resblk_va == NULL) { printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); return -ENOMEM; } + opblk_va = dma_alloc_coherent(&pHba->pDev->dev, + sizeof(opblk), &opblk_pa, GFP_KERNEL); + if (opblk_va == NULL) { + dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); + printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n", + pHba->name); + return -ENOMEM; + } if (field == -1) /* whole group */ opblk[4] = -1; + memcpy(opblk_va, opblk, sizeof(opblk)); size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen)); + opblk_va, opblk_pa, sizeof(opblk), + resblk_va, resblk_pa, sizeof(u8)*(8+buflen)); + dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa); if (size == -ETIME) { + dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); return -ETIME; } else if (size == -EINTR) { + dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); return -EINTR; } - memcpy(buf, resblk+8, buflen); /* cut off header */ + memcpy(buf, resblk_va+8, buflen); /* cut off header */ - kfree(resblk); + dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); if (size < 0) return size; @@ -3164,10 +3439,11 @@ static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk, int oplen, void *resblk, int reslen) + void *opblk_va, dma_addr_t opblk_pa, int oplen, + void *resblk_va, dma_addr_t resblk_pa, int reslen) { u32 msg[9]; - u32 *res = (u32 *)resblk; + u32 *res = (u32 *)resblk_va; int wait_status; msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; @@ -3176,12 +3452,12 @@ static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, msg[3] = 0; msg[4] = 0; msg[5] = 0x54000000 | oplen; /* OperationBlock */ - msg[6] = virt_to_bus(opblk); + msg[6] = (u32)opblk_pa; msg[7] = 0xD0000000 | reslen; /* ResultBlock */ - msg[8] = virt_to_bus(resblk); + msg[8] = (u32)resblk_pa; if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { - printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk); + printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va); return wait_status; /* -DetailedStatus */ } @@ -3284,7 +3560,7 @@ static int adpt_i2o_systab_send(adpt_hba* pHba) * Private i/o space declaration */ msg[6] = 0x54000000 | sys_tbl_len; - msg[7] = virt_to_phys(sys_tbl); + msg[7] = (u32)sys_tbl_pa; msg[8] = 0x54000000 | 0; msg[9] = 0; msg[10] = 0xD4000000 | 0; @@ -3323,11 +3599,10 @@ static static void adpt_delay(int millisec) #endif static struct scsi_host_template driver_template = { + .module = THIS_MODULE, .name = "dpt_i2o", .proc_name = "dpt_i2o", .proc_info = adpt_proc_info, - .detect = adpt_detect, - .release = adpt_release, .info = adpt_info, .queuecommand = adpt_queue, .eh_abort_handler = adpt_abort, @@ -3341,5 +3616,48 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, }; -#include "scsi_module.c" + +static int __init adpt_init(void) +{ + int error; + adpt_hba *pHba, *next; + + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); + + error = adpt_detect(&driver_template); + if (error < 0) + return error; + if (hba_chain == NULL) + return -ENODEV; + + for (pHba = hba_chain; pHba; pHba = pHba->next) { + error = scsi_add_host(pHba->host, &pHba->pDev->dev); + if (error) + goto fail; + scsi_scan_host(pHba->host); + } + return 0; +fail: + for (pHba = hba_chain; pHba; pHba = next) { + next = pHba->next; + scsi_remove_host(pHba->host); + } + return error; +} + +static void __exit adpt_exit(void) +{ + adpt_hba *pHba, *next; + + for (pHba = hba_chain; pHba; pHba = pHba->next) + scsi_remove_host(pHba->host); + for (pHba = hba_chain; pHba; pHba = next) { + next = pHba->next; + adpt_release(pHba->host); + } +} + +module_init(adpt_init); +module_exit(adpt_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index fd79068c5869..337746d46043 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -84,7 +84,6 @@ static int adpt_device_reset(struct scsi_cmnd* cmd); #define PCI_DPT_DEVICE_ID (0xA501) // DPT PCI I2O Device ID #define PCI_DPT_RAPTOR_DEVICE_ID (0xA511) -//#define REBOOT_NOTIFIER 1 /* Debugging macro from Linux Device Drivers - Rubini */ #undef PDEBUG #ifdef DEBUG @@ -229,14 +228,19 @@ typedef struct _adpt_hba { u32 post_fifo_size; u32 reply_fifo_size; u32* reply_pool; + dma_addr_t reply_pool_pa; u32 sg_tablesize; // Scatter/Gather List Size. u8 top_scsi_channel; u8 top_scsi_id; u8 top_scsi_lun; + u8 dma64; i2o_status_block* status_block; + dma_addr_t status_block_pa; i2o_hrt* hrt; + dma_addr_t hrt_pa; i2o_lct* lct; + dma_addr_t lct_pa; uint lct_size; struct i2o_device* devices; struct adpt_channel channel[MAX_CHANNEL]; @@ -249,6 +253,7 @@ typedef struct _adpt_hba { void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED u32 FwDebugFlags; + u32 *ioctl_reply_context[4]; } adpt_hba; struct sg_simple_element { @@ -264,9 +269,6 @@ static void adpt_i2o_sys_shutdown(void); static int adpt_init(void); static int adpt_i2o_build_sys_table(void); static irqreturn_t adpt_isr(int irq, void *dev_id); -#ifdef REBOOT_NOTIFIER -static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p); -#endif static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d); static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, @@ -275,7 +277,8 @@ static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, static const char *adpt_i2o_get_class_name(int class); #endif static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk, int oplen, void *resblk, int reslen); + void *opblk, dma_addr_t opblk_pa, int oplen, + void *resblk, dma_addr_t resblk_pa, int reslen); static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout); static int adpt_i2o_lct_get(adpt_hba* pHba); static int adpt_i2o_parse_lct(adpt_hba* pHba); @@ -289,7 +292,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht); +static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); static s32 adpt_rescan(adpt_hba* pHba); @@ -313,19 +316,6 @@ static int adpt_close(struct inode *inode, struct file *file); static void adpt_delay(int millisec); #endif -#if defined __ia64__ -static void adpt_ia64_info(sysInfo_S* si); -#endif -#if defined __sparc__ -static void adpt_sparc_info(sysInfo_S* si); -#endif -#if defined __alpha__ -static void adpt_sparc_info(sysInfo_S* si); -#endif -#if defined __i386__ -static void adpt_i386_info(sysInfo_S* si); -#endif - #define PRINT_BUFFER_SIZE 512 #define HBA_FLAGS_DBG_FLAGS_MASK 0xffff0000 // Mask for debug flags diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index a0b6d414953d..59fbef08d690 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2359,6 +2359,24 @@ void scsi_esp_unregister(struct esp *esp) } EXPORT_SYMBOL(scsi_esp_unregister); +static int esp_target_alloc(struct scsi_target *starget) +{ + struct esp *esp = shost_priv(dev_to_shost(&starget->dev)); + struct esp_target_data *tp = &esp->target[starget->id]; + + tp->starget = starget; + + return 0; +} + +static void esp_target_destroy(struct scsi_target *starget) +{ + struct esp *esp = shost_priv(dev_to_shost(&starget->dev)); + struct esp_target_data *tp = &esp->target[starget->id]; + + tp->starget = NULL; +} + static int esp_slave_alloc(struct scsi_device *dev) { struct esp *esp = shost_priv(dev->host); @@ -2370,8 +2388,6 @@ static int esp_slave_alloc(struct scsi_device *dev) return -ENOMEM; dev->hostdata = lp; - tp->starget = dev->sdev_target; - spi_min_period(tp->starget) = esp->min_period; spi_max_offset(tp->starget) = 15; @@ -2608,6 +2624,8 @@ struct scsi_host_template scsi_esp_template = { .name = "esp", .info = esp_info, .queuecommand = esp_queuecommand, + .target_alloc = esp_target_alloc, + .target_destroy = esp_target_destroy, .slave_alloc = esp_slave_alloc, .slave_configure = esp_slave_configure, .slave_destroy = esp_slave_destroy, diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index c6d6e7c6559a..46771d4c81bd 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -465,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; - memcpy(scp->cmnd, cmnd, 12); + scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; cmndinfo.internal_cmd_str = gdtcmd; cmndinfo.internal_command = 1; @@ -550,7 +550,6 @@ static int __init gdth_search_isa(ulong32 bios_adr) #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI -static bool gdth_pci_registered; static bool gdth_search_vortex(ushort device) { @@ -3724,6 +3723,8 @@ static void gdth_log_event(gdth_evt_data *dvr, char *buffer) } #ifdef GDTH_STATISTICS +static unchar gdth_timer_running; + static void gdth_timeout(ulong data) { ulong32 i; @@ -3731,7 +3732,10 @@ static void gdth_timeout(ulong data) gdth_ha_str *ha; ulong flags; - BUG_ON(list_empty(&gdth_instances)); + if(unlikely(list_empty(&gdth_instances))) { + gdth_timer_running = 0; + return; + } ha = list_first_entry(&gdth_instances, gdth_ha_str, list); spin_lock_irqsave(&ha->smp_lock, flags); @@ -3751,6 +3755,22 @@ static void gdth_timeout(ulong data) add_timer(&gdth_timer); spin_unlock_irqrestore(&ha->smp_lock, flags); } + +static void gdth_timer_init(void) +{ + if (gdth_timer_running) + return; + gdth_timer_running = 1; + TRACE2(("gdth_detect(): Initializing timer !\n")); + gdth_timer.expires = jiffies + HZ; + gdth_timer.data = 0L; + gdth_timer.function = gdth_timeout; + add_timer(&gdth_timer); +} +#else +static inline void gdth_timer_init(void) +{ +} #endif static void __init internal_setup(char *str,int *ints) @@ -4735,6 +4755,7 @@ static int __init gdth_isa_probe_one(ulong32 isa_bios) if (error) goto out_free_coal_stat; list_add_tail(&ha->list, &gdth_instances); + gdth_timer_init(); scsi_scan_host(shp); @@ -4865,6 +4886,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot) if (error) goto out_free_coal_stat; list_add_tail(&ha->list, &gdth_instances); + gdth_timer_init(); scsi_scan_host(shp); @@ -5011,6 +5033,7 @@ static int gdth_pci_probe_one(gdth_pci_str *pcistr, list_add_tail(&ha->list, &gdth_instances); pci_set_drvdata(ha->pdev, ha); + gdth_timer_init(); scsi_scan_host(shp); @@ -5110,6 +5133,7 @@ static int __init gdth_init(void) /* initializations */ gdth_polling = TRUE; gdth_clear_events(); + init_timer(&gdth_timer); /* As default we do not probe for EISA or ISA controllers */ if (probe_eisa_isa) { @@ -5132,23 +5156,17 @@ static int __init gdth_init(void) #ifdef CONFIG_PCI /* scanning for PCI controllers */ - if (pci_register_driver(&gdth_pci_driver) == 0) - gdth_pci_registered = true; + if (pci_register_driver(&gdth_pci_driver)) { + gdth_ha_str *ha; + + list_for_each_entry(ha, &gdth_instances, list) + gdth_remove_one(ha); + return -ENODEV; + } #endif /* CONFIG_PCI */ TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); - if (list_empty(&gdth_instances)) - return -ENODEV; - -#ifdef GDTH_STATISTICS - TRACE2(("gdth_detect(): Initializing timer !\n")); - init_timer(&gdth_timer); - gdth_timer.expires = jiffies + HZ; - gdth_timer.data = 0L; - gdth_timer.function = gdth_timeout; - add_timer(&gdth_timer); -#endif major = register_chrdev(0,"gdth", &gdth_fops); register_reboot_notifier(&gdth_notifier); gdth_polling = FALSE; @@ -5167,8 +5185,7 @@ static void __exit gdth_exit(void) #endif #ifdef CONFIG_PCI - if (gdth_pci_registered) - pci_unregister_driver(&gdth_pci_driver); + pci_unregister_driver(&gdth_pci_driver); #endif list_for_each_entry(ha, &gdth_instances, list) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 3690360d7a79..c6457bfc8a49 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -456,6 +456,10 @@ static int __scsi_host_match(struct device *dev, void *data) * * Return value: * A pointer to located Scsi_Host or NULL. + * + * The caller must do a scsi_host_put() to drop the reference + * that scsi_host_get() took. The put_device() below dropped + * the reference from class_find_device(). **/ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { @@ -463,9 +467,10 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) struct Scsi_Host *shost = ERR_PTR(-ENXIO); cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match); - if (cdev) + if (cdev) { shost = scsi_host_get(class_to_shost(cdev)); - + put_device(cdev); + } return shost; } EXPORT_SYMBOL(scsi_host_lookup); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 5b7be1e9841c..da876d3924be 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -444,7 +444,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) { printk(KERN_ERR "scsi%d: pci resource invalid\n", hba->host->host_no); - return 0; + return NULL; } mem_base_phy = pci_resource_start(pcidev, index); @@ -454,7 +454,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) if (!mem_base_virt) { printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", hba->host->host_no); - return 0; + return NULL; } return mem_base_virt; } @@ -476,11 +476,11 @@ static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba) { hba->u.mv.regs = hptiop_map_pci_bar(hba, 0); - if (hba->u.mv.regs == 0) + if (hba->u.mv.regs == NULL) return -1; hba->u.mv.mu = hptiop_map_pci_bar(hba, 2); - if (hba->u.mv.mu == 0) { + if (hba->u.mv.mu == NULL) { iounmap(hba->u.mv.regs); return -1; } @@ -763,9 +763,9 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, scp, host->host_no, scp->device->channel, scp->device->id, scp->device->lun, - *((u32 *)&scp->cmnd), - *((u32 *)&scp->cmnd + 1), - *((u32 *)&scp->cmnd + 2), + ((u32 *)scp->cmnd)[0], + ((u32 *)scp->cmnd)[1], + ((u32 *)scp->cmnd)[2], _req->index, _req->req_virt); scp->result = 0; @@ -1210,8 +1210,8 @@ static void hptiop_remove(struct pci_dev *pcidev) static struct hptiop_adapter_ops hptiop_itl_ops = { .iop_wait_ready = iop_wait_ready_itl, - .internal_memalloc = 0, - .internal_memfree = 0, + .internal_memalloc = NULL, + .internal_memfree = NULL, .map_pci_bar = hptiop_map_pci_bar_itl, .unmap_pci_bar = hptiop_unmap_pci_bar_itl, .enable_intr = hptiop_enable_intr_itl, diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 4a922c57125e..5d23368a1bce 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -686,7 +686,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct) } if (cmnd) { - cmnd->result = rsp->status; + cmnd->result |= rsp->status; if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION) memcpy(cmnd->sense_buffer, rsp->data, @@ -730,6 +730,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, u16 lun = lun_from_dev(cmnd->device); u8 out_fmt, in_fmt; + cmnd->result = (DID_OK << 16); evt_struct = get_event_struct(&hostdata->pool); if (!evt_struct) return SCSI_MLQUEUE_HOST_BUSY; @@ -738,7 +739,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, srp_cmd = &evt_struct->iu.srp.cmd; memset(srp_cmd, 0x00, SRP_MAX_IU_LEN); srp_cmd->opcode = SRP_CMD; - memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd)); + memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb)); srp_cmd->lun = ((u64) lun) << 48; if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { @@ -1347,6 +1348,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, del_timer(&evt_struct->timer); + if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd) + evt_struct->cmnd->result = DID_ERROR << 16; if (evt_struct->done) evt_struct->done(evt_struct); else diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h index 90f1a61283ad..204604501ad8 100644 --- a/drivers/scsi/ibmvscsi/viosrp.h +++ b/drivers/scsi/ibmvscsi/viosrp.h @@ -59,6 +59,16 @@ enum viosrp_crq_formats { VIOSRP_INLINE_FORMAT = 0x07 }; +enum viosrp_crq_status { + VIOSRP_OK = 0x0, + VIOSRP_NONRECOVERABLE_ERR = 0x1, + VIOSRP_VIOLATES_MAX_XFER = 0x2, + VIOSRP_PARTNER_PANIC = 0x3, + VIOSRP_DEVICE_BUSY = 0x8, + VIOSRP_ADAPTER_FAIL = 0x10, + VIOSRP_OK2 = 0x99, +}; + struct viosrp_crq { u8 valid; /* used by RPA */ u8 format; /* SCSI vs out-of-band */ diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index dbae3fdb8506..e3f739776bad 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2590,7 +2590,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c cblk->hastat = 0; cblk->tastat = 0; /* Command the command */ - memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len); + memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len); /* Set up tags */ if (cmnd->device->tagged_supported) { /* Tag Support */ diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index de5ae6a65029..999e91ea7451 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2791,7 +2791,7 @@ static ssize_t ipr_store_adapter_state(struct device *dev, static struct device_attribute ipr_ioa_state_attr = { .attr = { - .name = "state", + .name = "online_state", .mode = S_IRUGO | S_IWUSR, }, .show = ipr_show_adapter_state, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 010c1b9b178c..b43bf1d60dac 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -730,7 +730,9 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; - } + } else + mod_timer(&conn->transport_timer, + jiffies + conn->recv_timeout); iscsi_free_mgmt_task(conn, mtask); break; default: @@ -1453,19 +1455,20 @@ static void iscsi_check_transport_timeouts(unsigned long data) { struct iscsi_conn *conn = (struct iscsi_conn *)data; struct iscsi_session *session = conn->session; - unsigned long timeout, next_timeout = 0, last_recv; + unsigned long recv_timeout, next_timeout = 0, last_recv; spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) goto done; - timeout = conn->recv_timeout; - if (!timeout) + recv_timeout = conn->recv_timeout; + if (!recv_timeout) goto done; - timeout *= HZ; + recv_timeout *= HZ; last_recv = conn->last_recv; - if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), + if (conn->ping_mtask && + time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), jiffies)) { iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " "expired, last rx %lu, last ping %lu, " @@ -1476,15 +1479,13 @@ static void iscsi_check_transport_timeouts(unsigned long data) return; } - if (time_before_eq(last_recv + timeout, jiffies)) { - if (time_before_eq(conn->last_ping, last_recv)) { - /* send a ping to try to provoke some traffic */ - debug_scsi("Sending nopout as ping on conn %p\n", conn); - iscsi_send_nopout(conn, NULL); - } - next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); + if (time_before_eq(last_recv + recv_timeout, jiffies)) { + /* send a ping to try to provoke some traffic */ + debug_scsi("Sending nopout as ping on conn %p\n", conn); + iscsi_send_nopout(conn, NULL); + next_timeout = conn->last_ping + (conn->ping_timeout * HZ); } else - next_timeout = last_recv + timeout; + next_timeout = last_recv + recv_timeout; debug_scsi("Setting next tmo %lu\n", next_timeout); mod_timer(&conn->transport_timer, next_timeout); diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index cd37bd69a115..887682a24e36 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -650,7 +650,7 @@ static void __exit mac_esp_exit(void) MODULE_DESCRIPTION("Mac ESP SCSI driver"); MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>"); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL v2"); MODULE_VERSION(DRV_VERSION); module_init(mac_esp_init); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 820f91fb63ba..70a0f11f48b2 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -3168,6 +3168,23 @@ megaraid_mbox_support_random_del(adapter_t *adapter) uint8_t raw_mbox[sizeof(mbox_t)]; int rval; + /* + * Newer firmware on Dell CERC expect a different + * random deletion handling, so disable it. + */ + if (adapter->pdev->vendor == PCI_VENDOR_ID_AMI && + adapter->pdev->device == PCI_DEVICE_ID_AMI_MEGARAID3 && + adapter->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && + adapter->pdev->subsystem_device == PCI_SUBSYS_ID_CERC_ATA100_4CH && + (adapter->fw_version[0] > '6' || + (adapter->fw_version[0] == '6' && + adapter->fw_version[2] > '6') || + (adapter->fw_version[0] == '6' + && adapter->fw_version[2] == '6' + && adapter->fw_version[3] > '1'))) { + con_log(CL_DLEVEL1, ("megaraid: disable random deletion\n")); + return 0; + } mbox = (mbox_t *)raw_mbox; diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 626459d1e902..c1d86d961a92 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -88,6 +88,7 @@ #define PCI_SUBSYS_ID_PERC3_QC 0x0471 #define PCI_SUBSYS_ID_PERC3_DC 0x0493 #define PCI_SUBSYS_ID_PERC3_SC 0x0475 +#define PCI_SUBSYS_ID_CERC_ATA100_4CH 0x0511 #define MBOX_MAX_SCSI_CMDS 128 // number of cmds reserved for kernel diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index b937e9cddb23..7d84c8bbcf3f 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_sas.c - * Version : v00.00.03.16-rc1 + * Version : v00.00.03.20-rc1 * * Authors: * (email-id : megaraidlinux@lsi.com) @@ -2650,12 +2650,13 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, return; } +#ifdef CONFIG_PM /** * megasas_suspend - driver suspend entry point * @pdev: PCI device structure * @state: PCI power state to suspend routine */ -static int __devinit +static int megasas_suspend(struct pci_dev *pdev, pm_message_t state) { struct Scsi_Host *host; @@ -2687,7 +2688,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) * megasas_resume- driver resume entry point * @pdev: PCI device structure */ -static int __devinit +static int megasas_resume(struct pci_dev *pdev) { int rval; @@ -2782,12 +2783,16 @@ fail_ready_state: return -ENODEV; } +#else +#define megasas_suspend NULL +#define megasas_resume NULL +#endif /** * megasas_detach_one - PCI hot"un"plug entry point * @pdev: PCI device structure */ -static void megasas_detach_one(struct pci_dev *pdev) +static void __devexit megasas_detach_one(struct pci_dev *pdev) { int i; struct Scsi_Host *host; diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 3a997eb457bf..b0c41e671702 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -18,9 +18,9 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.03.16-rc1" -#define MEGASAS_RELDATE "Nov. 07, 2007" -#define MEGASAS_EXT_VERSION "Thu. Nov. 07 10:09:32 PDT 2007" +#define MEGASAS_VERSION "00.00.03.20-rc1" +#define MEGASAS_RELDATE "March 10, 2008" +#define MEGASAS_EXT_VERSION "Mon. March 10 11:02:31 PDT 2008" /* * Device IDs diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 31f7aec44d90..243d8becd30f 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5695,13 +5695,12 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S struct device *osst_member; int err; - osst_member = device_create(osst_sysfs_class, device, dev, "%s", name); + osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name); if (IS_ERR(osst_member)) { printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name); return PTR_ERR(osst_member); } - dev_set_drvdata(osst_member, STp); err = device_create_file(osst_member, &dev_attr_ADR_rev); if (err) goto err_out; diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 09ab3eac1c1a..3754ab87f89a 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2007,7 +2007,7 @@ qla1280_set_defaults(struct scsi_qla_host *ha) nv->bus[bus].config_2.req_ack_active_negation = 1; nv->bus[bus].config_2.data_line_active_negation = 1; nv->bus[bus].selection_timeout = 250; - nv->bus[bus].max_queue_depth = 256; + nv->bus[bus].max_queue_depth = 32; if (IS_ISP1040(ha)) { nv->bus[bus].bus_reset_delay = 3; @@ -2051,7 +2051,7 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target) status = qla1280_mailbox_command(ha, 0x0f, mb); /* Save Tag queuing enable flag. */ - flag = (BIT_0 << target) & mb[0]; + flag = (BIT_0 << target); if (nv->bus[bus].target[target].parameter.tag_queuing) ha->bus_settings[bus].qtag_enables |= flag; @@ -2811,7 +2811,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Check for room in outstanding command list. */ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && - ha->outstanding_cmds[cnt] != 0; cnt++); + ha->outstanding_cmds[cnt] != NULL; cnt++); if (cnt >= MAX_OUTSTANDING_COMMANDS) { status = 1; @@ -2858,7 +2858,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ @@ -3127,7 +3127,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Load SCSI command packet. */ pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, CMD_CDBP(cmd), CMD_CDBLEN(cmd)); /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ /* Set transfer direction. */ diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 287690853caf..8dd88fc1244a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -70,6 +70,9 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, case 2: qla2x00_alloc_fw_dump(ha); break; + case 3: + qla2x00_system_error(ha); + break; } return (count); } @@ -886,9 +889,13 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t port_type = FC_PORTTYPE_UNKNOWN; + if (ha->parent) { + fc_host_port_type(shost) = FC_PORTTYPE_NPIV; + return; + } switch (ha->current_topology) { case ISP_CFG_NL: port_type = FC_PORTTYPE_LPORT; @@ -1172,10 +1179,10 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) qla24xx_disable_vp(vha); qla24xx_deallocate_vp_id(vha); - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); ha->cur_vport_count--; clear_bit(vha->vp_idx, ha->vp_idx_map); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); kfree(vha->node_name); kfree(vha->port_name); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 299eccf6cabd..8dd600013bd1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2457,7 +2457,7 @@ typedef struct scsi_qla_host { #define MBX_INTR_WAIT 2 #define MBX_UPDATE_FLASH_ACTIVE 3 - struct semaphore vport_sem; /* Virtual port synchronization */ + struct mutex vport_lock; /* Virtual port synchronization */ struct completion mbx_cmd_comp; /* Serialize mbx access */ struct completion mbx_intr_comp; /* Used for completion notification */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f8827068d30f..9b4bebee6879 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -228,6 +228,9 @@ extern int qla24xx_abort_target(struct fc_port *, unsigned int); extern int qla24xx_lun_reset(struct fc_port *, unsigned int); extern int +qla2x00_system_error(scsi_qla_host_t *); + +extern int qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); extern int diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index e9bae27737d1..92fafbdbbaab 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -34,7 +34,11 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr) static inline void qla2x00_poll(scsi_qla_host_t *ha) { + unsigned long flags; + + local_irq_save(flags); ha->isp_ops->intr_handler(0, ha); + local_irq_restore(flags); } static __inline__ scsi_qla_host_t * diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5d9a64a7879b..ec63b79f900a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -272,8 +272,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) uint32_t rscn_entry, host_pid; uint8_t rscn_queue_index; unsigned long flags; - scsi_qla_host_t *vha; - int i; /* Setup to process RIO completion. */ handle_cnt = 0; @@ -544,18 +542,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_PORT_UPDATE: /* Port database update */ - if ((ha->flags.npiv_supported) && (ha->num_vhosts)) { - for_each_mapped_vp_idx(ha, i) { - list_for_each_entry(vha, &ha->vp_list, - vp_list) { - if ((mb[3] & 0xff) - == vha->vp_idx) { - ha = vha; - break; - } - } - } - } + /* Only handle SCNs for our Vport index. */ + if (ha->parent && ha->vp_idx != (mb[3] & 0xff)) + break; + /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process @@ -590,18 +580,12 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_RSCN_UPDATE: /* State Change Registration */ - if ((ha->flags.npiv_supported) && (ha->num_vhosts)) { - for_each_mapped_vp_idx(ha, i) { - list_for_each_entry(vha, &ha->vp_list, - vp_list) { - if ((mb[3] & 0xff) - == vha->vp_idx) { - ha = vha; - break; - } - } - } - } + /* Check if the Vport has issued a SCR */ + if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags)) + break; + /* Only handle SCNs for our Vport index. */ + if (ha->parent && ha->vp_idx != (mb[3] & 0xff)) + break; DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", ha->host_no)); @@ -1132,25 +1116,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) break; qla2x00_handle_sense(sp, sense_data, sense_len); - - /* - * In case of a Underrun condition, set both the lscsi - * status and the completion status to appropriate - * values. - */ - if (resid && - ((unsigned)(scsi_bufflen(cp) - resid) < - cp->underflow)) { - DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Mid-layer underflow " - "detected (%x of %x bytes)...returning " - "error status.\n", ha->host_no, - cp->device->channel, cp->device->id, - cp->device->lun, resid, - scsi_bufflen(cp))); - - cp->result = DID_ERROR << 16 | lscsi_status; - } } else { /* * If RISC reports underrun and target does not report @@ -1639,12 +1604,12 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) ha = dev_id; reg = &ha->iobase->isp24; - spin_lock(&ha->hardware_lock); + spin_lock_irq(&ha->hardware_lock); qla24xx_process_response_queue(ha); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock(&ha->hardware_lock); + spin_unlock_irq(&ha->hardware_lock); return IRQ_HANDLED; } @@ -1663,7 +1628,7 @@ qla24xx_msix_default(int irq, void *dev_id) reg = &ha->iobase->isp24; status = 0; - spin_lock(&ha->hardware_lock); + spin_lock_irq(&ha->hardware_lock); do { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { @@ -1716,7 +1681,7 @@ qla24xx_msix_default(int irq, void *dev_id) } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); } while (0); - spin_unlock(&ha->hardware_lock); + spin_unlock_irq(&ha->hardware_lock); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 210060420809..250d2f604397 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2303,8 +2303,6 @@ qla24xx_lun_reset(struct fc_port *fcport, unsigned int l) return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l); } -#if 0 - int qla2x00_system_error(scsi_qla_host_t *ha) { @@ -2312,7 +2310,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_FWI2_CAPABLE(ha)) + if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2334,8 +2332,6 @@ qla2x00_system_error(scsi_qla_host_t *ha) return rval; } -#endif /* 0 */ - /** * qla2x00_set_serdes_params() - * @ha: HA context @@ -2508,7 +2504,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma, if (mb) memcpy(mb, mcp->mb, 8 * sizeof(*mb)); if (dwords) - *dwords = mcp->mb[6]; + *dwords = buffers; } return rval; @@ -2807,9 +2803,9 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) */ map = (vp_index - 1) / 8; pos = (vp_index - 1) & 7; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vce->vp_idx_map[map] |= 1 << pos; - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0); if (rval != QLA_SUCCESS) { diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index f2b04979e5f0..62a3ad6e8ecb 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -32,12 +32,12 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) scsi_qla_host_t *ha = vha->parent; /* Find an empty slot and assign an vp_id */ - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vp_id = find_first_zero_bit(ha->vp_idx_map, ha->max_npiv_vports + 1); if (vp_id > ha->max_npiv_vports) { DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n", vp_id, ha->max_npiv_vports)); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vp_id; } @@ -45,7 +45,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) ha->num_vhosts++; vha->vp_idx = vp_id; list_add_tail(&vha->vp_list, &ha->vp_list); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vp_id; } @@ -55,12 +55,12 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) uint16_t vp_id; scsi_qla_host_t *ha = vha->parent; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); vp_id = vha->vp_idx; ha->num_vhosts--; clear_bit(vp_id, ha->vp_idx_map); list_del(&vha->vp_list); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); } static scsi_qla_host_t * @@ -145,9 +145,9 @@ qla24xx_enable_vp(scsi_qla_host_t *vha) } /* Initialize the new vport unless it is a persistent port */ - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); ret = qla24xx_modify_vp_config(vha); - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); if (ret != QLA_SUCCESS) { fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED); @@ -406,6 +406,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) INIT_LIST_HEAD(&vha->list); INIT_LIST_HEAD(&vha->fcports); INIT_LIST_HEAD(&vha->vp_fcports); + INIT_LIST_HEAD(&vha->work_list); vha->dpc_flags = 0L; set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); @@ -437,10 +438,10 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->flags.init_done = 1; num_hosts++; - down(&ha->vport_sem); + mutex_lock(&ha->vport_lock); set_bit(vha->vp_idx, ha->vp_idx_map); ha->cur_vport_count++; - up(&ha->vport_sem); + mutex_unlock(&ha->vport_lock); return vha; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3223fd16bcfe..48eaa3bb5433 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -10,6 +10,7 @@ #include <linux/vmalloc.h> #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/mutex.h> #include <scsi/scsi_tcq.h> #include <scsi/scsicam.h> @@ -1631,7 +1632,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* load the F/W, read paramaters, and init the H/W */ ha->instance = num_hosts; - init_MUTEX(&ha->vport_sem); + mutex_init(&ha->vport_lock); init_completion(&ha->mbx_cmd_comp); complete(&ha->mbx_cmd_comp); init_completion(&ha->mbx_intr_comp); @@ -2156,13 +2157,14 @@ static int qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked) { unsigned long flags; + scsi_qla_host_t *pha = to_qla_parent(ha); if (!locked) - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); list_add_tail(&e->list, &ha->work_list); qla2xxx_wake_dpc(ha); if (!locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); return QLA_SUCCESS; } @@ -2202,12 +2204,13 @@ static void qla2x00_do_work(struct scsi_qla_host *ha) { struct qla_work_evt *e; + scsi_qla_host_t *pha = to_qla_parent(ha); - spin_lock_irq(&ha->hardware_lock); + spin_lock_irq(&pha->hardware_lock); while (!list_empty(&ha->work_list)) { e = list_entry(ha->work_list.next, struct qla_work_evt, list); list_del_init(&e->list); - spin_unlock_irq(&ha->hardware_lock); + spin_unlock_irq(&pha->hardware_lock); switch (e->type) { case QLA_EVT_AEN: @@ -2221,9 +2224,9 @@ qla2x00_do_work(struct scsi_qla_host *ha) } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); - spin_lock_irq(&ha->hardware_lock); + spin_lock_irq(&pha->hardware_lock); } - spin_unlock_irq(&ha->hardware_lock); + spin_unlock_irq(&pha->hardware_lock); } /************************************************************************** @@ -2634,7 +2637,7 @@ qla2x00_timer(scsi_qla_host_t *ha) #define FW_FILE_ISP24XX "ql2400_fw.bin" #define FW_FILE_ISP25XX "ql2500_fw.bin" -static DECLARE_MUTEX(qla_fw_lock); +static DEFINE_MUTEX(qla_fw_lock); static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, @@ -2665,7 +2668,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP25XX]; } - down(&qla_fw_lock); + mutex_lock(&qla_fw_lock); if (blob->fw) goto out; @@ -2678,7 +2681,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) } out: - up(&qla_fw_lock); + mutex_unlock(&qla_fw_lock); return blob; } @@ -2687,11 +2690,11 @@ qla2x00_release_firmware(void) { int idx; - down(&qla_fw_lock); + mutex_lock(&qla_fw_lock); for (idx = 0; idx < FW_BLOBS; idx++) if (qla_fw_blobs[idx].fw) release_firmware(qla_fw_blobs[idx].fw); - up(&qla_fw_lock); + mutex_unlock(&qla_fw_lock); } static pci_ers_result_t @@ -2864,7 +2867,8 @@ qla2x00_module_init(void) return -ENODEV; } - printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); + printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n", + qla2x00_version_str); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { kmem_cache_destroy(srb_cachep); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index afeae2bfe7eb..d058c8862b35 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k2" +#define QLA2XXX_VERSION "8.02.01-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 12d69d7c8577..110e776d1a07 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -79,15 +79,6 @@ static void scsi_done(struct scsi_cmnd *cmd); #define MIN_RESET_PERIOD (15*HZ) /* - * Macro to determine the size of SCSI command. This macro takes vendor - * unique commands into account. SCSI commands in groups 6 and 7 are - * vendor unique and we will depend upon the command length being - * supplied correctly in cmd_len. - */ -#define CDB_SIZE(cmd) (((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \ - COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len) - -/* * Note - the initial logging level can be set here to log events at boot time. * After the system is up, you may enable logging via the /proc interface. */ @@ -469,6 +460,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask); if (!cmd) { scsi_put_host_cmd_pool(gfp_mask); + shost->cmd_pool = NULL; return -ENOMEM; } list_add(&cmd->list, &shost->free_list); @@ -481,6 +473,13 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) */ void scsi_destroy_command_freelist(struct Scsi_Host *shost) { + /* + * If cmd_pool is NULL the free list was not initialized, so + * do not attempt to release resources. + */ + if (!shost->cmd_pool) + return; + while (!list_empty(&shost->free_list)) { struct scsi_cmnd *cmd; @@ -701,9 +700,11 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ - if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) { + if (cmd->cmd_len > cmd->device->host->max_cmd_len) { SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long.\n")); + printk("queuecommand : command too long. " + "cdb_size=%d host->max_cmd_len=%d\n", + cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); scsi_done(cmd); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1eaba6cd80f4..eaf5a8add1ba 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -626,7 +626,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) * @scmd: SCSI command structure to hijack * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed - * @cmnd_size: size in bytes of @cmnd + * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to save a scsi command information before re-execution @@ -648,12 +648,14 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * command. */ ses->cmd_len = scmd->cmd_len; - memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->cmnd = scmd->cmnd; ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->next_rq = scmd->request->next_rq; ses->result = scmd->result; + scmd->cmnd = ses->eh_cmnd; + memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->request->next_rq = NULL; @@ -665,14 +667,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->sdb.table.sgl = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->sdb.table.nents = 1; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); scmd->cmnd[0] = REQUEST_SENSE; scmd->cmnd[4] = scmd->sdb.length; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->sc_data_direction = DMA_NONE; if (cmnd) { - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + BUG_ON(cmnd_size > BLK_MAX_CDB); memcpy(scmd->cmnd, cmnd, cmnd_size); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } @@ -705,7 +706,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) * Restore original data */ scmd->cmd_len = ses->cmd_len; - memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->cmnd = ses->cmnd; scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->request->next_rq = ses->next_rq; @@ -1775,8 +1776,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); - + scmd->cmnd = req.cmd; + scmd->scsi_done = scsi_reset_provider_done_command; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d545ad1cf47a..a82d2fe80fb5 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -445,7 +445,7 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) scsi_set_resid(cmd, 0); memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); + cmd->cmd_len = scsi_command_size(cmd->cmnd); } void scsi_device_unbusy(struct scsi_device *sdev) @@ -1094,6 +1094,8 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, cmd->tag = req->tag; cmd->request = req; + cmd->cmnd = req->cmd; + return cmd; } @@ -1131,8 +1133,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) req->buffer = NULL; } - BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); - memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); cmd->cmd_len = req->cmd_len; if (!req->data_len) cmd->sc_data_direction = DMA_NONE; @@ -1169,6 +1169,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; + memset(cmd->cmnd, 0, BLK_MAX_CDB); return scsi_init_io(cmd, GFP_ATOMIC); } EXPORT_SYMBOL(scsi_setup_fs_cmnd); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 049103f1d16f..93d2b6714453 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -359,7 +359,12 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct scsi_device *sdev = to_scsi_device(dev); + struct scsi_device *sdev; + + if (dev->type != &scsi_dev_type) + return 0; + + sdev = to_scsi_device(dev); add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index ee8496aa0336..257e097c39af 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -107,6 +107,8 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, cmd->jiffies_at_alloc = jiffies; cmd->request = rq; + cmd->cmnd = rq->cmd; + rq->special = cmd; rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_flags |= REQ_TYPE_BLOCK_PC; diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 45df83b9d847..0fe031f003e7 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -61,7 +61,7 @@ static int ses_probe(struct device *dev) return err; } -#define SES_TIMEOUT 30 +#define SES_TIMEOUT (30 * HZ) #define SES_RETRIES 3 static int ses_recv_diag(struct scsi_device *sdev, int page_code, diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index c9d7f721b9e2..ea0edd1b2e76 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1441,17 +1441,18 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) if (sg_sysfs_valid) { struct device *sg_class_member; - sg_class_member = device_create(sg_sysfs_class, cl_dev->parent, - MKDEV(SCSI_GENERIC_MAJOR, - sdp->index), - "%s", disk->disk_name); + sg_class_member = device_create_drvdata(sg_sysfs_class, + cl_dev->parent, + MKDEV(SCSI_GENERIC_MAJOR, + sdp->index), + sdp, + "%s", disk->disk_name); if (IS_ERR(sg_class_member)) { printk(KERN_ERR "sg_add: " "device_create failed\n"); error = PTR_ERR(sg_class_member); goto cdev_add_err; } - dev_set_drvdata(sg_class_member, sdp); error = sysfs_create_link(&scsidp->sdev_gendev.kobj, &sg_class_member->kobj, "generic"); if (error) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7ee86d4a7618..c82df8bd4d89 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -178,6 +178,9 @@ int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr) the_result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr, SR_TIMEOUT, retries--); + if (scsi_sense_valid(sshdr) && + sshdr->sense_key == UNIT_ATTENTION) + sdev->changed = 1; } while (retries > 0 && (!scsi_status_is_good(the_result) || diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e8db66ad0bde..6e5a5bb31311 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4424,17 +4424,19 @@ static int 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 = - device_create(st_sysfs_class, &STp->device->sdev_gendev, - MKDEV(SCSI_TAPE_MAJOR, - TAPE_MINOR(dev_num, mode, rew)), - "%s", name); + device_create_drvdata(st_sysfs_class, + &STp->device->sdev_gendev, + MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(dev_num, + mode, rew)), + &STp->modes[mode], + "%s", name); if (IS_ERR(st_class_member)) { printk(KERN_WARNING "st%d: device_create failed\n", dev_num); error = PTR_ERR(st_class_member); goto out; } - dev_set_drvdata(st_class_member, &STp->modes[mode]); error = device_create_file(st_class_member, &dev_attr_defined); diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 640333b1e75c..329eb8780e74 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -744,7 +744,8 @@ static int wait_on_busy(unsigned long iobase, unsigned int loop) { static int board_inquiry(unsigned int j) { struct mscp *cpp; dma_addr_t id_dma_addr; - unsigned int time, limit = 0; + unsigned int limit = 0; + unsigned long time; id_dma_addr = pci_map_single(HD(j)->pdev, HD(j)->board_id, sizeof(HD(j)->board_id), PCI_DMA_BIDIRECTIONAL); @@ -1392,7 +1393,8 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { } static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { - unsigned int i, j, time, k, c, limit = 0; + unsigned int i, j, k, c, limit = 0; + unsigned long time; int arg_done = FALSE; struct scsi_cmnd *SCpnt; |