mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge remote-tracking branch 'scsi-queue/drivers-for-3.19' into for-linus
Conflicts: drivers/scsi/scsi_debug.c Agreed and tested resolution to a merge problem between a fix in scsi_debug and a driver update Signed-off-by: James Bottomley <[email protected]>
This commit is contained in:
commit
096cbc35ea
154 changed files with 7010 additions and 11822 deletions
|
|
@ -189,19 +189,6 @@ static ssize_t twa_show_stats(struct device *dev,
|
|||
return len;
|
||||
} /* End twa_show_stats() */
|
||||
|
||||
/* This function will set a devices queue depth */
|
||||
static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
|
||||
int reason)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > TW_Q_LENGTH-2)
|
||||
queue_depth = TW_Q_LENGTH-2;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
return queue_depth;
|
||||
} /* End twa_change_queue_depth() */
|
||||
|
||||
/* Create sysfs 'stats' entry */
|
||||
static struct device_attribute twa_host_stats_attr = {
|
||||
.attr = {
|
||||
|
|
@ -2016,7 +2003,7 @@ static struct scsi_host_template driver_template = {
|
|||
.queuecommand = twa_scsi_queue,
|
||||
.eh_host_reset_handler = twa_scsi_eh_reset,
|
||||
.bios_param = twa_scsi_biosparam,
|
||||
.change_queue_depth = twa_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.can_queue = TW_Q_LENGTH-2,
|
||||
.slave_configure = twa_slave_configure,
|
||||
.this_id = -1,
|
||||
|
|
|
|||
|
|
@ -191,19 +191,6 @@ static ssize_t twl_show_stats(struct device *dev,
|
|||
return len;
|
||||
} /* End twl_show_stats() */
|
||||
|
||||
/* This function will set a devices queue depth */
|
||||
static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth,
|
||||
int reason)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > TW_Q_LENGTH-2)
|
||||
queue_depth = TW_Q_LENGTH-2;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
return queue_depth;
|
||||
} /* End twl_change_queue_depth() */
|
||||
|
||||
/* stats sysfs attribute initializer */
|
||||
static struct device_attribute twl_host_stats_attr = {
|
||||
.attr = {
|
||||
|
|
@ -1590,7 +1577,7 @@ static struct scsi_host_template driver_template = {
|
|||
.queuecommand = twl_scsi_queue,
|
||||
.eh_host_reset_handler = twl_scsi_eh_reset,
|
||||
.bios_param = twl_scsi_biosparam,
|
||||
.change_queue_depth = twl_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.can_queue = TW_Q_LENGTH-2,
|
||||
.slave_configure = twl_slave_configure,
|
||||
.this_id = -1,
|
||||
|
|
|
|||
|
|
@ -523,19 +523,6 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
|
|||
return len;
|
||||
} /* End tw_show_stats() */
|
||||
|
||||
/* This function will set a devices queue depth */
|
||||
static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
|
||||
int reason)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > TW_Q_LENGTH-2)
|
||||
queue_depth = TW_Q_LENGTH-2;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
return queue_depth;
|
||||
} /* End tw_change_queue_depth() */
|
||||
|
||||
/* Create sysfs 'stats' entry */
|
||||
static struct device_attribute tw_host_stats_attr = {
|
||||
.attr = {
|
||||
|
|
@ -2270,7 +2257,7 @@ static struct scsi_host_template driver_template = {
|
|||
.queuecommand = tw_scsi_queue,
|
||||
.eh_host_reset_handler = tw_scsi_eh_reset,
|
||||
.bios_param = tw_scsi_biosparam,
|
||||
.change_queue_depth = tw_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.can_queue = TW_Q_LENGTH-2,
|
||||
.slave_configure = tw_slave_configure,
|
||||
.this_id = -1,
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
|
|||
STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
|
||||
STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
|
||||
STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
|
||||
static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
|
||||
static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
|
||||
static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
|
||||
|
||||
STATIC struct device_attribute *NCR_700_dev_attrs[];
|
||||
|
|
@ -904,7 +904,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
|
|||
hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
|
||||
|
||||
SCp->device->tagged_supported = 0;
|
||||
scsi_adjust_queue_depth(SCp->device, host->cmd_per_lun);
|
||||
scsi_change_queue_depth(SCp->device, host->cmd_per_lun);
|
||||
scsi_set_tag_type(SCp->device, 0);
|
||||
} else {
|
||||
shost_printk(KERN_WARNING, host,
|
||||
|
|
@ -2052,7 +2052,7 @@ NCR_700_slave_configure(struct scsi_device *SDp)
|
|||
|
||||
/* to do here: allocate memory; build a queue_full list */
|
||||
if(SDp->tagged_supported) {
|
||||
scsi_adjust_queue_depth(SDp, NCR_700_DEFAULT_TAGS);
|
||||
scsi_change_queue_depth(SDp, NCR_700_DEFAULT_TAGS);
|
||||
NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
|
||||
}
|
||||
|
||||
|
|
@ -2075,16 +2075,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
|
|||
}
|
||||
|
||||
static int
|
||||
NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
|
||||
NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (depth > NCR_700_MAX_TAGS)
|
||||
depth = NCR_700_MAX_TAGS;
|
||||
|
||||
scsi_adjust_queue_depth(SDp, depth);
|
||||
return depth;
|
||||
return scsi_change_queue_depth(SDp, depth);
|
||||
}
|
||||
|
||||
static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
|
||||
|
|
@ -2105,12 +2100,12 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
|
|||
if (!tag_type) {
|
||||
/* shift back to the default unqueued number of commands
|
||||
* (the user can still raise this) */
|
||||
scsi_adjust_queue_depth(SDp, SDp->host->cmd_per_lun);
|
||||
scsi_change_queue_depth(SDp, SDp->host->cmd_per_lun);
|
||||
hostdata->tag_negotiated &= ~(1 << sdev_id(SDp));
|
||||
} else {
|
||||
/* Here, we cleared the negotiation flag above, so this
|
||||
* will force the driver to renegotiate */
|
||||
scsi_adjust_queue_depth(SDp, SDp->queue_depth);
|
||||
scsi_change_queue_depth(SDp, SDp->queue_depth);
|
||||
if (change_tag)
|
||||
NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2327,12 +2327,12 @@ static int blogic_slaveconfig(struct scsi_device *dev)
|
|||
if (qdepth == 0)
|
||||
qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
|
||||
adapter->qdepth[tgt_id] = qdepth;
|
||||
scsi_adjust_queue_depth(dev, qdepth);
|
||||
scsi_change_queue_depth(dev, qdepth);
|
||||
} else {
|
||||
adapter->tagq_ok &= ~(1 << tgt_id);
|
||||
qdepth = adapter->untag_qdepth;
|
||||
adapter->qdepth[tgt_id] = qdepth;
|
||||
scsi_adjust_queue_depth(dev, qdepth);
|
||||
scsi_change_queue_depth(dev, qdepth);
|
||||
}
|
||||
qdepth = 0;
|
||||
for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
|
||||
|
|
|
|||
|
|
@ -1341,13 +1341,15 @@ config SCSI_DC395x
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called dc395x.
|
||||
|
||||
config SCSI_DC390T
|
||||
tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
|
||||
config SCSI_AM53C974
|
||||
tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
---help---
|
||||
This driver supports PCI SCSI host adapters based on the Am53C974A
|
||||
chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
|
||||
PCscsi/PCnet (Am53/79C974) solutions.
|
||||
This is a new implementation base on the generic esp_scsi driver.
|
||||
|
||||
Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
|
||||
|
||||
|
|
@ -1355,7 +1357,7 @@ config SCSI_DC390T
|
|||
based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called tmscsim.
|
||||
module will be called am53c974.
|
||||
|
||||
config SCSI_T128
|
||||
tristate "Trantor T128/T128F/T228 SCSI support"
|
||||
|
|
@ -1451,6 +1453,14 @@ config SCSI_NSP32
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called nsp32.
|
||||
|
||||
config SCSI_WD719X
|
||||
tristate "Western Digital WD7193/7197/7296 support"
|
||||
depends on PCI && SCSI
|
||||
select EEPROM_93CX6
|
||||
---help---
|
||||
This is a driver for Western Digital WD7193, WD7197 and WD7296 PCI
|
||||
SCSI controllers (based on WD33C296A chip).
|
||||
|
||||
config SCSI_DEBUG
|
||||
tristate "SCSI debugging host simulator"
|
||||
depends on SCSI
|
||||
|
|
@ -1615,7 +1625,7 @@ config ATARI_SCSI_RESET_BOOT
|
|||
that leave the devices with SCSI operations partway completed.
|
||||
|
||||
config MAC_SCSI
|
||||
bool "Macintosh NCR5380 SCSI"
|
||||
tristate "Macintosh NCR5380 SCSI"
|
||||
depends on MAC && SCSI=y
|
||||
select SCSI_SPI_ATTRS
|
||||
help
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
|
|||
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
|
||||
obj-$(CONFIG_SCSI_EATA) += eata.o
|
||||
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
|
||||
obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
|
||||
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
|
||||
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
|
||||
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
|
||||
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
|
||||
|
|
@ -143,6 +143,7 @@ obj-$(CONFIG_SCSI_VIRTIO) += virtio_scsi.o
|
|||
obj-$(CONFIG_VMWARE_PVSCSI) += vmw_pvscsi.o
|
||||
obj-$(CONFIG_XEN_SCSI_FRONTEND) += xen-scsifront.o
|
||||
obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
|
||||
obj-$(CONFIG_SCSI_WD719X) += wd719x.o
|
||||
|
||||
obj-$(CONFIG_ARM) += arm/
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
* drew@colorado.edu
|
||||
* +1 (303) 666-5836
|
||||
*
|
||||
* DISTRIBUTION RELEASE 6.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
|
|
@ -279,7 +277,7 @@ static void do_reset(struct Scsi_Host *host);
|
|||
* Set up the internal fields in the SCSI command.
|
||||
*/
|
||||
|
||||
static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
|
||||
static inline void initialize_SCp(struct scsi_cmnd *cmd)
|
||||
{
|
||||
/*
|
||||
* Initialize the Scsi Pointer field so that all of the commands in the
|
||||
|
|
@ -574,12 +572,12 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
|
|||
int trying_irqs, i, mask;
|
||||
NCR5380_setup(instance);
|
||||
|
||||
for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
|
||||
for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
|
||||
if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
|
||||
trying_irqs |= mask;
|
||||
|
||||
timeout = jiffies + (250 * HZ / 1000);
|
||||
probe_irq = SCSI_IRQ_NONE;
|
||||
probe_irq = NO_IRQ;
|
||||
|
||||
/*
|
||||
* A interrupt is triggered whenever BSY = false, SEL = true
|
||||
|
|
@ -596,13 +594,13 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
|
|||
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
|
||||
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
|
||||
|
||||
while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout))
|
||||
while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
|
||||
schedule_timeout_uninterruptible(1);
|
||||
|
||||
NCR5380_write(SELECT_ENABLE_REG, 0);
|
||||
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
|
||||
|
||||
for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)
|
||||
for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
|
||||
if (trying_irqs & mask)
|
||||
free_irq(i, NULL);
|
||||
|
||||
|
|
@ -610,50 +608,70 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
|
|||
}
|
||||
|
||||
/**
|
||||
* NCR58380_print_options - show options
|
||||
* @instance: unused for now
|
||||
* NCR58380_info - report driver and host information
|
||||
* @instance: relevant scsi host instance
|
||||
*
|
||||
* Called by probe code indicating the NCR5380 driver options that
|
||||
* were selected. At some point this will switch to runtime options
|
||||
* read from the adapter in question
|
||||
* For use as the host template info() handler.
|
||||
*
|
||||
* Locks: none
|
||||
*/
|
||||
|
||||
static void __init __maybe_unused
|
||||
NCR5380_print_options(struct Scsi_Host *instance)
|
||||
static const char *NCR5380_info(struct Scsi_Host *instance)
|
||||
{
|
||||
printk(" generic options"
|
||||
#ifdef AUTOPROBE_IRQ
|
||||
" AUTOPROBE_IRQ"
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
return hostdata->info;
|
||||
}
|
||||
|
||||
static void prepare_info(struct Scsi_Host *instance)
|
||||
{
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
snprintf(hostdata->info, sizeof(hostdata->info),
|
||||
"%s, io_port 0x%lx, n_io_port %d, "
|
||||
"base 0x%lx, irq %d, "
|
||||
"can_queue %d, cmd_per_lun %d, "
|
||||
"sg_tablesize %d, this_id %d, "
|
||||
"flags { %s%s%s}, "
|
||||
#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
|
||||
"USLEEP_POLL %d, USLEEP_WAITLONG %d, "
|
||||
#endif
|
||||
#ifdef AUTOSENSE
|
||||
" AUTOSENSE"
|
||||
"options { %s} ",
|
||||
instance->hostt->name, instance->io_port, instance->n_io_port,
|
||||
instance->base, instance->irq,
|
||||
instance->can_queue, instance->cmd_per_lun,
|
||||
instance->sg_tablesize, instance->this_id,
|
||||
hostdata->flags & FLAG_NCR53C400 ? "NCR53C400 " : "",
|
||||
hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
|
||||
hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
|
||||
#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
|
||||
USLEEP_POLL, USLEEP_WAITLONG,
|
||||
#endif
|
||||
#ifdef AUTOPROBE_IRQ
|
||||
"AUTOPROBE_IRQ "
|
||||
#endif
|
||||
#ifdef DIFFERENTIAL
|
||||
" DIFFERENTIAL"
|
||||
"DIFFERENTIAL "
|
||||
#endif
|
||||
#ifdef REAL_DMA
|
||||
" REAL DMA"
|
||||
"REAL_DMA "
|
||||
#endif
|
||||
#ifdef REAL_DMA_POLL
|
||||
" REAL DMA POLL"
|
||||
"REAL_DMA_POLL "
|
||||
#endif
|
||||
#ifdef PARITY
|
||||
" PARITY"
|
||||
"PARITY "
|
||||
#endif
|
||||
#ifdef PSEUDO_DMA
|
||||
" PSEUDO DMA"
|
||||
"PSEUDO_DMA "
|
||||
#endif
|
||||
#ifdef UNSAFE
|
||||
" UNSAFE "
|
||||
"UNSAFE "
|
||||
#endif
|
||||
);
|
||||
printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
|
||||
printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
|
||||
if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
|
||||
printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
|
||||
}
|
||||
#ifdef NCR53C400
|
||||
"NCR53C400 "
|
||||
#endif
|
||||
"");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -672,6 +690,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
|
|||
NCR5380_dprint_phase(NDEBUG_ANY, instance);
|
||||
}
|
||||
|
||||
#ifdef PSEUDO_DMA
|
||||
/******************************************/
|
||||
/*
|
||||
* /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
|
||||
|
|
@ -689,19 +708,18 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
|
|||
static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
|
||||
char *buffer, int length)
|
||||
{
|
||||
#ifdef DTC_PUBLIC_RELEASE
|
||||
dtc_wmaxi = dtc_maxi = 0;
|
||||
#endif
|
||||
#ifdef PAS16_PUBLIC_RELEASE
|
||||
pas_wmaxi = pas_maxi = 0;
|
||||
#endif
|
||||
return (-ENOSYS); /* Currently this is a no-op */
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
hostdata->spin_max_r = 0;
|
||||
hostdata->spin_max_w = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef SPRINTF
|
||||
#define SPRINTF(args...) seq_printf(m, ## args)
|
||||
static
|
||||
void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
|
||||
void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m);
|
||||
static
|
||||
void lprint_command(unsigned char *cmd, struct seq_file *m);
|
||||
static
|
||||
|
|
@ -711,56 +729,31 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
|
|||
struct Scsi_Host *instance)
|
||||
{
|
||||
struct NCR5380_hostdata *hostdata;
|
||||
Scsi_Cmnd *ptr;
|
||||
struct scsi_cmnd *ptr;
|
||||
|
||||
hostdata = (struct NCR5380_hostdata *) instance->hostdata;
|
||||
|
||||
SPRINTF("NCR5380 core release=%d. ", NCR5380_PUBLIC_RELEASE);
|
||||
if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
|
||||
SPRINTF("ncr53c400 release=%d. ", NCR53C400_PUBLIC_RELEASE);
|
||||
#ifdef DTC_PUBLIC_RELEASE
|
||||
SPRINTF("DTC 3180/3280 release %d", DTC_PUBLIC_RELEASE);
|
||||
#endif
|
||||
#ifdef T128_PUBLIC_RELEASE
|
||||
SPRINTF("T128 release %d", T128_PUBLIC_RELEASE);
|
||||
#endif
|
||||
#ifdef GENERIC_NCR5380_PUBLIC_RELEASE
|
||||
SPRINTF("Generic5380 release %d", GENERIC_NCR5380_PUBLIC_RELEASE);
|
||||
#endif
|
||||
#ifdef PAS16_PUBLIC_RELEASE
|
||||
SPRINTF("PAS16 release=%d", PAS16_PUBLIC_RELEASE);
|
||||
#endif
|
||||
|
||||
SPRINTF("\nBase Addr: 0x%05lX ", (long) instance->base);
|
||||
SPRINTF("io_port: %04x ", (int) instance->io_port);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
SPRINTF("IRQ: None.\n");
|
||||
else
|
||||
SPRINTF("IRQ: %d.\n", instance->irq);
|
||||
|
||||
#ifdef DTC_PUBLIC_RELEASE
|
||||
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", dtc_wmaxi, dtc_maxi);
|
||||
#endif
|
||||
#ifdef PAS16_PUBLIC_RELEASE
|
||||
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
|
||||
#ifdef PSEUDO_DMA
|
||||
SPRINTF("Highwater I/O busy spin counts: write %d, read %d\n",
|
||||
hostdata->spin_max_w, hostdata->spin_max_r);
|
||||
#endif
|
||||
spin_lock_irq(instance->host_lock);
|
||||
if (!hostdata->connected)
|
||||
SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
|
||||
else
|
||||
lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
|
||||
lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m);
|
||||
SPRINTF("scsi%d: issue_queue\n", instance->host_no);
|
||||
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
|
||||
for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
|
||||
lprint_Scsi_Cmnd(ptr, m);
|
||||
|
||||
SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
|
||||
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
|
||||
for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
|
||||
lprint_Scsi_Cmnd(ptr, m);
|
||||
spin_unlock_irq(instance->host_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
|
||||
static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m)
|
||||
{
|
||||
SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
|
||||
SPRINTF(" command = ");
|
||||
|
|
@ -836,18 +829,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
|
|||
|
||||
INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
|
||||
|
||||
#ifdef NCR5380_STATS
|
||||
for (i = 0; i < 8; ++i) {
|
||||
hostdata->time_read[i] = 0;
|
||||
hostdata->time_write[i] = 0;
|
||||
hostdata->bytes_read[i] = 0;
|
||||
hostdata->bytes_write[i] = 0;
|
||||
}
|
||||
hostdata->timebase = 0;
|
||||
hostdata->pendingw = 0;
|
||||
hostdata->pendingr = 0;
|
||||
#endif
|
||||
|
||||
/* The CHECK code seems to break the 53C400. Will check it later maybe */
|
||||
if (flags & FLAG_NCR53C400)
|
||||
hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;
|
||||
|
|
@ -857,11 +838,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
|
|||
hostdata->host = instance;
|
||||
hostdata->time_expires = 0;
|
||||
|
||||
#ifndef AUTOSENSE
|
||||
if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
|
||||
printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" " without AUTOSENSE option, contingent allegiance conditions may\n"
|
||||
" be incorrectly cleared.\n", instance->host_no);
|
||||
#endif /* def AUTOSENSE */
|
||||
prepare_info(instance);
|
||||
|
||||
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
|
||||
NCR5380_write(MODE_REG, MR_BASE);
|
||||
|
|
@ -935,11 +912,11 @@ static void NCR5380_exit(struct Scsi_Host *instance)
|
|||
* Locks: host lock taken by caller
|
||||
*/
|
||||
|
||||
static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
|
||||
static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *))
|
||||
{
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
|
||||
Scsi_Cmnd *tmp;
|
||||
struct scsi_cmnd *tmp;
|
||||
|
||||
#if (NDEBUG & NDEBUG_NO_WRITE)
|
||||
switch (cmd->cmnd[0]) {
|
||||
|
|
@ -952,25 +929,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
|
|||
}
|
||||
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
|
||||
|
||||
#ifdef NCR5380_STATS
|
||||
switch (cmd->cmnd[0]) {
|
||||
case WRITE:
|
||||
case WRITE_6:
|
||||
case WRITE_10:
|
||||
hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
|
||||
hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
|
||||
hostdata->pendingw++;
|
||||
break;
|
||||
case READ:
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
|
||||
hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
|
||||
hostdata->pendingr++;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use the host_scribble field as a pointer to the next command
|
||||
* in a queue
|
||||
|
|
@ -992,7 +950,7 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
|
|||
cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
|
||||
hostdata->issue_queue = cmd;
|
||||
} else {
|
||||
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
|
||||
for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble);
|
||||
LIST(cmd, tmp);
|
||||
tmp->host_scribble = (unsigned char *) cmd;
|
||||
}
|
||||
|
|
@ -1023,7 +981,7 @@ static void NCR5380_main(struct work_struct *work)
|
|||
struct NCR5380_hostdata *hostdata =
|
||||
container_of(work, struct NCR5380_hostdata, coroutine.work);
|
||||
struct Scsi_Host *instance = hostdata->host;
|
||||
Scsi_Cmnd *tmp, *prev;
|
||||
struct scsi_cmnd *tmp, *prev;
|
||||
int done;
|
||||
|
||||
spin_lock_irq(instance->host_lock);
|
||||
|
|
@ -1036,7 +994,7 @@ static void NCR5380_main(struct work_struct *work)
|
|||
* Search through the issue_queue for a command destined
|
||||
* for a target that's not busy.
|
||||
*/
|
||||
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
|
||||
for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
|
||||
{
|
||||
if (prev != tmp)
|
||||
dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
|
||||
|
|
@ -1048,7 +1006,7 @@ static void NCR5380_main(struct work_struct *work)
|
|||
prev->host_scribble = tmp->host_scribble;
|
||||
} else {
|
||||
REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);
|
||||
hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
|
||||
hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble;
|
||||
}
|
||||
tmp->host_scribble = NULL;
|
||||
|
||||
|
|
@ -1073,14 +1031,14 @@ static void NCR5380_main(struct work_struct *work)
|
|||
hostdata->selecting = NULL;
|
||||
/* RvC: have to preset this to indicate a new command is being performed */
|
||||
|
||||
if (!NCR5380_select(instance, tmp,
|
||||
/*
|
||||
* REQUEST SENSE commands are issued without tagged
|
||||
* queueing, even on SCSI-II devices because the
|
||||
* contingent allegiance condition exists for the
|
||||
* entire unit.
|
||||
*/
|
||||
(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
|
||||
/*
|
||||
* REQUEST SENSE commands are issued without tagged
|
||||
* queueing, even on SCSI-II devices because the
|
||||
* contingent allegiance condition exists for the
|
||||
* entire unit.
|
||||
*/
|
||||
|
||||
if (!NCR5380_select(instance, tmp)) {
|
||||
break;
|
||||
} else {
|
||||
LIST(tmp, hostdata->issue_queue);
|
||||
|
|
@ -1095,9 +1053,9 @@ static void NCR5380_main(struct work_struct *work)
|
|||
/* exited locked */
|
||||
} /* if (!hostdata->connected) */
|
||||
if (hostdata->selecting) {
|
||||
tmp = (Scsi_Cmnd *) hostdata->selecting;
|
||||
tmp = (struct scsi_cmnd *) hostdata->selecting;
|
||||
/* Selection will drop and retake the lock */
|
||||
if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
|
||||
if (!NCR5380_select(instance, tmp)) {
|
||||
/* Ok ?? */
|
||||
} else {
|
||||
/* RvC: device failed, so we wait a long time
|
||||
|
|
@ -1216,47 +1174,16 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id)
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* collect_stats - collect stats on a scsi command
|
||||
* @hostdata: adapter
|
||||
* @cmd: command being issued
|
||||
*
|
||||
* Update the statistical data by parsing the command in question
|
||||
*/
|
||||
|
||||
static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
|
||||
{
|
||||
#ifdef NCR5380_STATS
|
||||
switch (cmd->cmnd[0]) {
|
||||
case WRITE:
|
||||
case WRITE_6:
|
||||
case WRITE_10:
|
||||
hostdata->time_write[scmd_id(cmd)] += (jiffies - hostdata->timebase);
|
||||
hostdata->pendingw--;
|
||||
break;
|
||||
case READ:
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
hostdata->time_read[scmd_id(cmd)] += (jiffies - hostdata->timebase);
|
||||
hostdata->pendingr--;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
|
||||
* int tag);
|
||||
* Function : int NCR5380_select(struct Scsi_Host *instance,
|
||||
* struct scsi_cmnd *cmd)
|
||||
*
|
||||
* Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
|
||||
* including ARBITRATION, SELECTION, and initial message out for
|
||||
* IDENTIFY and queue messages.
|
||||
*
|
||||
* Inputs : instance - instantiation of the 5380 driver on which this
|
||||
* target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
|
||||
* new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
|
||||
* the command that is presently connected.
|
||||
* target lives, cmd - SCSI command to execute.
|
||||
*
|
||||
* Returns : -1 if selection could not execute for some reason,
|
||||
* 0 if selection succeeded or failed because the target
|
||||
|
|
@ -1278,7 +1205,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
|
|||
* Locks: caller holds hostdata lock in IRQ mode
|
||||
*/
|
||||
|
||||
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
|
||||
static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
|
||||
{
|
||||
NCR5380_local_declare();
|
||||
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
|
||||
|
|
@ -1476,7 +1403,6 @@ part2:
|
|||
return -1;
|
||||
}
|
||||
cmd->result = DID_BAD_TARGET << 16;
|
||||
collect_stats(hostdata, cmd);
|
||||
cmd->scsi_done(cmd);
|
||||
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
|
||||
dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no);
|
||||
|
|
@ -1513,7 +1439,7 @@ part2:
|
|||
}
|
||||
|
||||
dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id);
|
||||
tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
|
||||
tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
|
||||
|
||||
len = 1;
|
||||
cmd->tag = 0;
|
||||
|
|
@ -2086,7 +2012,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
#endif
|
||||
unsigned char *data;
|
||||
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
|
||||
Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
|
||||
struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
|
||||
/* RvC: we need to set the end of the polling time */
|
||||
unsigned long poll_time = jiffies + USLEEP_POLL;
|
||||
|
||||
|
|
@ -2228,7 +2154,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
cmd->next_link->tag = cmd->tag;
|
||||
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
|
||||
dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
|
||||
collect_stats(hostdata, cmd);
|
||||
cmd->scsi_done(cmd);
|
||||
cmd = hostdata->connected;
|
||||
break;
|
||||
|
|
@ -2263,7 +2188,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
else if (status_byte(cmd->SCp.Status) != GOOD)
|
||||
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
|
||||
|
||||
#ifdef AUTOSENSE
|
||||
if ((cmd->cmnd[0] == REQUEST_SENSE) &&
|
||||
hostdata->ses.cmd_len) {
|
||||
scsi_eh_restore_cmnd(cmd, &hostdata->ses);
|
||||
|
|
@ -2278,12 +2202,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
LIST(cmd, hostdata->issue_queue);
|
||||
cmd->host_scribble = (unsigned char *)
|
||||
hostdata->issue_queue;
|
||||
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
|
||||
hostdata->issue_queue = (struct scsi_cmnd *) cmd;
|
||||
dprintk(NDEBUG_QUEUES, "scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
|
||||
} else
|
||||
#endif /* def AUTOSENSE */
|
||||
{
|
||||
collect_stats(hostdata, cmd);
|
||||
} else {
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
|
|
@ -2430,7 +2351,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
|
||||
hostdata->connected = NULL;
|
||||
cmd->result = DID_ERROR << 16;
|
||||
collect_stats(hostdata, cmd);
|
||||
cmd->scsi_done(cmd);
|
||||
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
|
||||
return;
|
||||
|
|
@ -2479,7 +2399,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
|
|||
* Function : void NCR5380_reselect (struct Scsi_Host *instance)
|
||||
*
|
||||
* Purpose : does reselection, initializing the instance->connected
|
||||
* field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
|
||||
* field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
|
||||
* nexus has been reestablished,
|
||||
*
|
||||
* Inputs : instance - this instance of the NCR5380.
|
||||
|
|
@ -2496,7 +2416,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
|
|||
int len;
|
||||
unsigned char msg[3];
|
||||
unsigned char *data;
|
||||
Scsi_Cmnd *tmp = NULL, *prev;
|
||||
struct scsi_cmnd *tmp = NULL, *prev;
|
||||
int abort = 0;
|
||||
NCR5380_setup(instance);
|
||||
|
||||
|
|
@ -2562,7 +2482,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
|
|||
*/
|
||||
|
||||
|
||||
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
|
||||
for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
|
||||
if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)
|
||||
) {
|
||||
if (prev) {
|
||||
|
|
@ -2570,7 +2490,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
|
|||
prev->host_scribble = tmp->host_scribble;
|
||||
} else {
|
||||
REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble);
|
||||
hostdata->disconnected_queue = (Scsi_Cmnd *) tmp->host_scribble;
|
||||
hostdata->disconnected_queue = (struct scsi_cmnd *) tmp->host_scribble;
|
||||
}
|
||||
tmp->host_scribble = NULL;
|
||||
break;
|
||||
|
|
@ -2601,7 +2521,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
|
|||
*
|
||||
* Inputs : instance - this instance of the NCR5380.
|
||||
*
|
||||
* Returns : pointer to the Scsi_Cmnd structure for which the I_T_L
|
||||
* Returns : pointer to the scsi_cmnd structure for which the I_T_L
|
||||
* nexus has been reestablished, on failure NULL is returned.
|
||||
*/
|
||||
|
||||
|
|
@ -2643,11 +2563,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
|
|||
#endif /* def REAL_DMA */
|
||||
|
||||
/*
|
||||
* Function : int NCR5380_abort (Scsi_Cmnd *cmd)
|
||||
* Function : int NCR5380_abort (struct scsi_cmnd *cmd)
|
||||
*
|
||||
* Purpose : abort a command
|
||||
*
|
||||
* Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
|
||||
* Inputs : cmd - the scsi_cmnd to abort, code - code to set the
|
||||
* host byte of the result field to, if zero DID_ABORTED is
|
||||
* used.
|
||||
*
|
||||
|
|
@ -2661,11 +2581,12 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
|
|||
* Locks: host lock taken by caller
|
||||
*/
|
||||
|
||||
static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
||||
static int NCR5380_abort(struct scsi_cmnd *cmd)
|
||||
{
|
||||
NCR5380_local_declare();
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
|
||||
Scsi_Cmnd *tmp, **prev;
|
||||
struct scsi_cmnd *tmp, **prev;
|
||||
|
||||
scmd_printk(KERN_WARNING, cmd, "aborting command\n");
|
||||
|
||||
|
|
@ -2713,10 +2634,10 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
|||
*/
|
||||
|
||||
dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no);
|
||||
for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
|
||||
for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
|
||||
if (cmd == tmp) {
|
||||
REMOVE(5, *prev, tmp, tmp->host_scribble);
|
||||
(*prev) = (Scsi_Cmnd *) tmp->host_scribble;
|
||||
(*prev) = (struct scsi_cmnd *) tmp->host_scribble;
|
||||
tmp->host_scribble = NULL;
|
||||
tmp->result = DID_ABORT << 16;
|
||||
dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no);
|
||||
|
|
@ -2769,20 +2690,20 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
|||
* it from the disconnected queue.
|
||||
*/
|
||||
|
||||
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
|
||||
for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = (struct scsi_cmnd *) tmp->host_scribble)
|
||||
if (cmd == tmp) {
|
||||
dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no);
|
||||
|
||||
if (NCR5380_select(instance, cmd, (int) cmd->tag))
|
||||
if (NCR5380_select(instance, cmd))
|
||||
return FAILED;
|
||||
dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no);
|
||||
|
||||
do_abort(instance);
|
||||
|
||||
for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
|
||||
for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
|
||||
if (cmd == tmp) {
|
||||
REMOVE(5, *prev, tmp, tmp->host_scribble);
|
||||
*prev = (Scsi_Cmnd *) tmp->host_scribble;
|
||||
*prev = (struct scsi_cmnd *) tmp->host_scribble;
|
||||
tmp->host_scribble = NULL;
|
||||
tmp->result = DID_ABORT << 16;
|
||||
tmp->scsi_done(tmp);
|
||||
|
|
@ -2805,7 +2726,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
|||
|
||||
|
||||
/*
|
||||
* Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd)
|
||||
* Function : int NCR5380_bus_reset (struct scsi_cmnd *cmd)
|
||||
*
|
||||
* Purpose : reset the SCSI bus.
|
||||
*
|
||||
|
|
@ -2814,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
|||
* Locks: host lock taken by caller
|
||||
*/
|
||||
|
||||
static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
|
||||
static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
* drew@colorado.edu
|
||||
* +1 (303) 666-5836
|
||||
*
|
||||
* DISTRIBUTION RELEASE 7
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
|
|
@ -25,13 +23,7 @@
|
|||
#define NCR5380_H
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#ifdef AUTOSENSE
|
||||
#include <scsi/scsi_eh.h>
|
||||
#endif
|
||||
|
||||
#define NCR5380_PUBLIC_RELEASE 7
|
||||
#define NCR53C400_PUBLIC_RELEASE 2
|
||||
|
||||
#define NDEBUG_ARBITRATION 0x1
|
||||
#define NDEBUG_AUTOSENSE 0x2
|
||||
|
|
@ -224,33 +216,44 @@
|
|||
#define DISCONNECT_LONG 2
|
||||
|
||||
/*
|
||||
* These are "special" values for the tag parameter passed to NCR5380_select.
|
||||
* "Special" value for the (unsigned char) command tag, to indicate
|
||||
* I_T_L nexus instead of I_T_L_Q.
|
||||
*/
|
||||
|
||||
#define TAG_NEXT -1 /* Use next free tag */
|
||||
#define TAG_NONE -2 /*
|
||||
* Establish I_T_L nexus instead of I_T_L_Q
|
||||
* even on SCSI-II devices.
|
||||
*/
|
||||
#define TAG_NONE 0xff
|
||||
|
||||
/*
|
||||
* These are "special" values for the irq and dma_channel fields of the
|
||||
* Scsi_Host structure
|
||||
*/
|
||||
|
||||
#define SCSI_IRQ_NONE 255
|
||||
#define DMA_NONE 255
|
||||
#define IRQ_AUTO 254
|
||||
#define DMA_AUTO 254
|
||||
#define PORT_AUTO 0xffff /* autoprobe io port for 53c400a */
|
||||
|
||||
#ifndef NO_IRQ
|
||||
#define NO_IRQ 0
|
||||
#endif
|
||||
|
||||
#define FLAG_HAS_LAST_BYTE_SENT 1 /* NCR53c81 or better */
|
||||
#define FLAG_CHECK_LAST_BYTE_SENT 2 /* Only test once */
|
||||
#define FLAG_NCR53C400 4 /* NCR53c400 */
|
||||
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
|
||||
#define FLAG_DTC3181E 16 /* DTC3181E */
|
||||
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
|
||||
#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
struct tag_alloc {
|
||||
DECLARE_BITMAP(allocated, MAX_TAGS);
|
||||
int nr_allocated;
|
||||
int queue_size;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct NCR5380_hostdata {
|
||||
NCR5380_implementation_fields; /* implementation specific */
|
||||
struct Scsi_Host *host; /* Host backpointer */
|
||||
|
|
@ -263,9 +266,9 @@ struct NCR5380_hostdata {
|
|||
volatile int dma_len; /* requested length of DMA */
|
||||
#endif
|
||||
volatile unsigned char last_message; /* last message OUT */
|
||||
volatile Scsi_Cmnd *connected; /* currently connected command */
|
||||
volatile Scsi_Cmnd *issue_queue; /* waiting to be issued */
|
||||
volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */
|
||||
volatile struct scsi_cmnd *connected; /* currently connected command */
|
||||
volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */
|
||||
volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */
|
||||
volatile int restart_select; /* we have disconnected,
|
||||
used to restart
|
||||
NCR5380_select() */
|
||||
|
|
@ -273,19 +276,21 @@ struct NCR5380_hostdata {
|
|||
int flags;
|
||||
unsigned long time_expires; /* in jiffies, set prior to sleeping */
|
||||
int select_time; /* timer in select for target response */
|
||||
volatile Scsi_Cmnd *selecting;
|
||||
volatile struct scsi_cmnd *selecting;
|
||||
struct delayed_work coroutine; /* our co-routine */
|
||||
#ifdef NCR5380_STATS
|
||||
unsigned timebase; /* Base for time calcs */
|
||||
long time_read[8]; /* time to do reads */
|
||||
long time_write[8]; /* time to do writes */
|
||||
unsigned long bytes_read[8]; /* bytes read */
|
||||
unsigned long bytes_write[8]; /* bytes written */
|
||||
unsigned pendingr;
|
||||
unsigned pendingw;
|
||||
#endif
|
||||
#ifdef AUTOSENSE
|
||||
struct scsi_eh_save ses;
|
||||
char info[256];
|
||||
int read_overruns; /* number of bytes to cut from a
|
||||
* transfer to handle chip overruns */
|
||||
int retain_dma_intr;
|
||||
struct work_struct main_task;
|
||||
volatile int main_running;
|
||||
#ifdef SUPPORT_TAGS
|
||||
struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */
|
||||
#endif
|
||||
#ifdef PSEUDO_DMA
|
||||
unsigned spin_max_r;
|
||||
unsigned spin_max_w;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -296,7 +301,8 @@ struct NCR5380_hostdata {
|
|||
#endif
|
||||
|
||||
#define dprintk(flg, fmt, ...) \
|
||||
do { if ((NDEBUG) & (flg)) pr_debug(fmt, ## __VA_ARGS__); } while (0)
|
||||
do { if ((NDEBUG) & (flg)) \
|
||||
printk(KERN_DEBUG fmt, ## __VA_ARGS__); } while (0)
|
||||
|
||||
#if NDEBUG
|
||||
#define NCR5380_dprint(flg, arg) \
|
||||
|
|
@ -320,17 +326,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance);
|
|||
static irqreturn_t NCR5380_intr(int irq, void *dev_id);
|
||||
#endif
|
||||
static void NCR5380_main(struct work_struct *work);
|
||||
static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
|
||||
static int NCR5380_abort(Scsi_Cmnd * cmd);
|
||||
static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
|
||||
static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int __maybe_unused NCR5380_show_info(struct seq_file *,
|
||||
struct Scsi_Host *);
|
||||
static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
|
||||
char *buffer, int length);
|
||||
|
||||
static const char *NCR5380_info(struct Scsi_Host *instance);
|
||||
static void NCR5380_reselect(struct Scsi_Host *instance);
|
||||
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
|
||||
static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd);
|
||||
#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
|
||||
static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -462,9 +462,9 @@ static int aac_slave_configure(struct scsi_device *sdev)
|
|||
depth = 256;
|
||||
else if (depth < 2)
|
||||
depth = 2;
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
scsi_change_queue_depth(sdev, depth);
|
||||
} else
|
||||
scsi_adjust_queue_depth(sdev, 1);
|
||||
scsi_change_queue_depth(sdev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -478,12 +478,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
|
|||
* total capacity and the queue depth supported by the target device.
|
||||
*/
|
||||
|
||||
static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
|
||||
int reason)
|
||||
static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
|
||||
(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
|
||||
struct scsi_device * dev;
|
||||
|
|
@ -504,10 +500,10 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
|
|||
depth = 256;
|
||||
else if (depth < 2)
|
||||
depth = 2;
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
} else
|
||||
scsi_adjust_queue_depth(sdev, 1);
|
||||
return sdev->queue_depth;
|
||||
return scsi_change_queue_depth(sdev, depth);
|
||||
}
|
||||
|
||||
return scsi_change_queue_depth(sdev, 1);
|
||||
}
|
||||
|
||||
static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
|
|
|
|||
|
|
@ -7706,7 +7706,7 @@ advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
|
|||
asc_dvc->cfg->can_tagged_qng |= tid_bit;
|
||||
asc_dvc->use_tagged_qng |= tid_bit;
|
||||
}
|
||||
scsi_adjust_queue_depth(sdev,
|
||||
scsi_change_queue_depth(sdev,
|
||||
asc_dvc->max_dvc_qng[sdev->id]);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -7847,10 +7847,8 @@ advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
|
|||
}
|
||||
}
|
||||
|
||||
if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
|
||||
scsi_adjust_queue_depth(sdev,
|
||||
adv_dvc->max_dvc_qng);
|
||||
}
|
||||
if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported)
|
||||
scsi_change_queue_depth(sdev, adv_dvc->max_dvc_qng);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1470,7 +1470,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
|
|||
switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
|
||||
case AHD_DEV_Q_BASIC:
|
||||
case AHD_DEV_Q_TAGGED:
|
||||
scsi_adjust_queue_depth(sdev,
|
||||
scsi_change_queue_depth(sdev,
|
||||
dev->openings + dev->active);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1480,7 +1480,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
|
|||
* serially on the controller/device. This should
|
||||
* remove some latency.
|
||||
*/
|
||||
scsi_adjust_queue_depth(sdev, 1);
|
||||
scsi_change_queue_depth(sdev, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1336,7 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
|
|||
switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
|
||||
case AHC_DEV_Q_BASIC:
|
||||
case AHC_DEV_Q_TAGGED:
|
||||
scsi_adjust_queue_depth(sdev,
|
||||
scsi_change_queue_depth(sdev,
|
||||
dev->openings + dev->active);
|
||||
default:
|
||||
/*
|
||||
|
|
@ -1345,7 +1345,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
|
|||
* serially on the controller/device. This should
|
||||
* remove some latency.
|
||||
*/
|
||||
scsi_adjust_queue_depth(sdev, 2);
|
||||
scsi_change_queue_depth(sdev, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ void asd_dev_gone(struct domain_device *dev);
|
|||
|
||||
void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id);
|
||||
|
||||
int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
|
||||
int asd_execute_task(struct sas_task *task, gfp_t gfp_flags);
|
||||
|
||||
void asd_set_dmamode(struct domain_device *dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -1200,8 +1200,7 @@ static void asd_start_scb_timers(struct list_head *list)
|
|||
* Case A: we can send the whole batch at once. Increment "pending"
|
||||
* in the beginning of this function, when it is checked, in order to
|
||||
* eliminate races when this function is called by multiple processes.
|
||||
* Case B: should never happen if the managing layer considers
|
||||
* lldd_queue_size.
|
||||
* Case B: should never happen.
|
||||
*/
|
||||
int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
|
||||
int num)
|
||||
|
|
|
|||
|
|
@ -49,14 +49,6 @@ MODULE_PARM_DESC(use_msi, "\n"
|
|||
"\tEnable(1) or disable(0) using PCI MSI.\n"
|
||||
"\tDefault: 0");
|
||||
|
||||
static int lldd_max_execute_num = 0;
|
||||
module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(collector, "\n"
|
||||
"\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
|
||||
"\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
|
||||
"\tThe aic94xx SAS LLDD supports both modes.\n"
|
||||
"\tDefault: 0 (Direct Mode).\n");
|
||||
|
||||
static struct scsi_transport_template *aic94xx_transport_template;
|
||||
static int asd_scan_finished(struct Scsi_Host *, unsigned long);
|
||||
static void asd_scan_start(struct Scsi_Host *);
|
||||
|
|
@ -84,6 +76,7 @@ static struct scsi_host_template aic94xx_sht = {
|
|||
.target_destroy = sas_target_destroy,
|
||||
.ioctl = sas_ioctl,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static int asd_map_memio(struct asd_ha_struct *asd_ha)
|
||||
|
|
@ -710,9 +703,6 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
|
|||
asd_ha->sas_ha.sas_port= sas_ports;
|
||||
asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
|
||||
|
||||
asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
|
||||
asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;
|
||||
|
||||
return sas_register_ha(&asd_ha->sas_ha);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -543,8 +543,7 @@ static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
|
|||
return res;
|
||||
}
|
||||
|
||||
int asd_execute_task(struct sas_task *task, const int num,
|
||||
gfp_t gfp_flags)
|
||||
int asd_execute_task(struct sas_task *task, gfp_t gfp_flags)
|
||||
{
|
||||
int res = 0;
|
||||
LIST_HEAD(alist);
|
||||
|
|
@ -553,11 +552,11 @@ int asd_execute_task(struct sas_task *task, const int num,
|
|||
struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
|
||||
unsigned long flags;
|
||||
|
||||
res = asd_can_queue(asd_ha, num);
|
||||
res = asd_can_queue(asd_ha, 1);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = num;
|
||||
res = 1;
|
||||
ascb = asd_ascb_alloc_list(asd_ha, &res, gfp_flags);
|
||||
if (res) {
|
||||
res = -ENOMEM;
|
||||
|
|
@ -568,7 +567,7 @@ int asd_execute_task(struct sas_task *task, const int num,
|
|||
list_for_each_entry(a, &alist, list) {
|
||||
a->uldd_task = t;
|
||||
t->lldd_task = a;
|
||||
t = list_entry(t->list.next, struct sas_task, list);
|
||||
break;
|
||||
}
|
||||
list_for_each_entry(a, &alist, list) {
|
||||
t = a->uldd_task;
|
||||
|
|
@ -601,7 +600,7 @@ int asd_execute_task(struct sas_task *task, const int num,
|
|||
}
|
||||
list_del_init(&alist);
|
||||
|
||||
res = asd_post_ascb_list(asd_ha, ascb, num);
|
||||
res = asd_post_ascb_list(asd_ha, ascb, 1);
|
||||
if (unlikely(res)) {
|
||||
a = NULL;
|
||||
__list_add(&alist, ascb->list.prev, &ascb->list);
|
||||
|
|
@ -639,6 +638,6 @@ out_err_unmap:
|
|||
out_err:
|
||||
if (ascb)
|
||||
asd_ascb_free_list(ascb);
|
||||
asd_can_dequeue(asd_ha, num);
|
||||
asd_can_dequeue(asd_ha, 1);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
586
drivers/scsi/am53c974.c
Normal file
586
drivers/scsi/am53c974.c
Normal file
|
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
* AMD am53c974 driver.
|
||||
* Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include "esp_scsi.h"
|
||||
|
||||
#define DRV_MODULE_NAME "am53c974"
|
||||
#define DRV_MODULE_VERSION "1.00"
|
||||
|
||||
static bool am53c974_debug;
|
||||
static bool am53c974_fenab = true;
|
||||
|
||||
#define esp_dma_log(f, a...) \
|
||||
do { \
|
||||
if (am53c974_debug) \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ##a); \
|
||||
} while (0)
|
||||
|
||||
#define ESP_DMA_CMD 0x10
|
||||
#define ESP_DMA_STC 0x11
|
||||
#define ESP_DMA_SPA 0x12
|
||||
#define ESP_DMA_WBC 0x13
|
||||
#define ESP_DMA_WAC 0x14
|
||||
#define ESP_DMA_STATUS 0x15
|
||||
#define ESP_DMA_SMDLA 0x16
|
||||
#define ESP_DMA_WMAC 0x17
|
||||
|
||||
#define ESP_DMA_CMD_IDLE 0x00
|
||||
#define ESP_DMA_CMD_BLAST 0x01
|
||||
#define ESP_DMA_CMD_ABORT 0x02
|
||||
#define ESP_DMA_CMD_START 0x03
|
||||
#define ESP_DMA_CMD_MASK 0x03
|
||||
#define ESP_DMA_CMD_DIAG 0x04
|
||||
#define ESP_DMA_CMD_MDL 0x10
|
||||
#define ESP_DMA_CMD_INTE_P 0x20
|
||||
#define ESP_DMA_CMD_INTE_D 0x40
|
||||
#define ESP_DMA_CMD_DIR 0x80
|
||||
|
||||
#define ESP_DMA_STAT_PWDN 0x01
|
||||
#define ESP_DMA_STAT_ERROR 0x02
|
||||
#define ESP_DMA_STAT_ABORT 0x04
|
||||
#define ESP_DMA_STAT_DONE 0x08
|
||||
#define ESP_DMA_STAT_SCSIINT 0x10
|
||||
#define ESP_DMA_STAT_BCMPLT 0x20
|
||||
|
||||
/* EEPROM is accessed with 16-bit values */
|
||||
#define DC390_EEPROM_READ 0x80
|
||||
#define DC390_EEPROM_LEN 0x40
|
||||
|
||||
/*
|
||||
* DC390 EEPROM
|
||||
*
|
||||
* 8 * 4 bytes of per-device options
|
||||
* followed by HBA specific options
|
||||
*/
|
||||
|
||||
/* Per-device options */
|
||||
#define DC390_EE_MODE1 0x00
|
||||
#define DC390_EE_SPEED 0x01
|
||||
|
||||
/* HBA-specific options */
|
||||
#define DC390_EE_ADAPT_SCSI_ID 0x40
|
||||
#define DC390_EE_MODE2 0x41
|
||||
#define DC390_EE_DELAY 0x42
|
||||
#define DC390_EE_TAG_CMD_NUM 0x43
|
||||
|
||||
#define DC390_EE_MODE1_PARITY_CHK 0x01
|
||||
#define DC390_EE_MODE1_SYNC_NEGO 0x02
|
||||
#define DC390_EE_MODE1_EN_DISC 0x04
|
||||
#define DC390_EE_MODE1_SEND_START 0x08
|
||||
#define DC390_EE_MODE1_TCQ 0x10
|
||||
|
||||
#define DC390_EE_MODE2_MORE_2DRV 0x01
|
||||
#define DC390_EE_MODE2_GREATER_1G 0x02
|
||||
#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
|
||||
#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
|
||||
#define DC390_EE_MODE2_NO_SEEK 0x10
|
||||
#define DC390_EE_MODE2_LUN_CHECK 0x20
|
||||
|
||||
struct pci_esp_priv {
|
||||
struct esp *esp;
|
||||
u8 dma_status;
|
||||
};
|
||||
|
||||
static void pci_esp_dma_drain(struct esp *esp);
|
||||
|
||||
static inline struct pci_esp_priv *pci_esp_get_priv(struct esp *esp)
|
||||
{
|
||||
struct pci_dev *pdev = esp->dev;
|
||||
|
||||
return pci_get_drvdata(pdev);
|
||||
}
|
||||
|
||||
static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
|
||||
{
|
||||
iowrite8(val, esp->regs + (reg * 4UL));
|
||||
}
|
||||
|
||||
static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
|
||||
{
|
||||
return ioread8(esp->regs + (reg * 4UL));
|
||||
}
|
||||
|
||||
static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
|
||||
{
|
||||
return iowrite32(val, esp->regs + (reg * 4UL));
|
||||
}
|
||||
|
||||
static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
|
||||
size_t sz, int dir)
|
||||
{
|
||||
return pci_map_single(esp->dev, buf, sz, dir);
|
||||
}
|
||||
|
||||
static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
|
||||
int num_sg, int dir)
|
||||
{
|
||||
return pci_map_sg(esp->dev, sg, num_sg, dir);
|
||||
}
|
||||
|
||||
static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
|
||||
size_t sz, int dir)
|
||||
{
|
||||
pci_unmap_single(esp->dev, addr, sz, dir);
|
||||
}
|
||||
|
||||
static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
|
||||
int num_sg, int dir)
|
||||
{
|
||||
pci_unmap_sg(esp->dev, sg, num_sg, dir);
|
||||
}
|
||||
|
||||
static int pci_esp_irq_pending(struct esp *esp)
|
||||
{
|
||||
struct pci_esp_priv *pep = pci_esp_get_priv(esp);
|
||||
|
||||
pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
|
||||
esp_dma_log("dma intr dreg[%02x]\n", pep->dma_status);
|
||||
|
||||
if (pep->dma_status & (ESP_DMA_STAT_ERROR |
|
||||
ESP_DMA_STAT_ABORT |
|
||||
ESP_DMA_STAT_DONE |
|
||||
ESP_DMA_STAT_SCSIINT))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_esp_reset_dma(struct esp *esp)
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
}
|
||||
|
||||
static void pci_esp_dma_drain(struct esp *esp)
|
||||
{
|
||||
u8 resid;
|
||||
int lim = 1000;
|
||||
|
||||
|
||||
if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
|
||||
(esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
|
||||
/* Data-In or Data-Out, nothing to be done */
|
||||
return;
|
||||
|
||||
while (--lim > 0) {
|
||||
resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
|
||||
if (resid <= 1)
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
if (resid > 1) {
|
||||
/* FIFO not cleared */
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"FIFO not cleared, %d bytes left\n",
|
||||
resid);
|
||||
}
|
||||
|
||||
/*
|
||||
* When there is a residual BCMPLT will never be set
|
||||
* (obviously). But we still have to issue the BLAST
|
||||
* command, otherwise the data will not being transferred.
|
||||
* But we'll never know when the BLAST operation is
|
||||
* finished. So check for some time and give up eventually.
|
||||
*/
|
||||
lim = 1000;
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
|
||||
while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
|
||||
if (--lim == 0)
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
|
||||
esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
|
||||
/* BLAST residual handling is currently untested */
|
||||
if (WARN_ON_ONCE(resid == 1)) {
|
||||
struct esp_cmd_entry *ent = esp->active_cmd;
|
||||
|
||||
ent->flags |= ESP_CMD_FLAG_RESIDUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_esp_dma_invalidate(struct esp *esp)
|
||||
{
|
||||
struct pci_esp_priv *pep = pci_esp_get_priv(esp);
|
||||
|
||||
esp_dma_log("invalidate DMA\n");
|
||||
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
|
||||
pep->dma_status = 0;
|
||||
}
|
||||
|
||||
static int pci_esp_dma_error(struct esp *esp)
|
||||
{
|
||||
struct pci_esp_priv *pep = pci_esp_get_priv(esp);
|
||||
|
||||
if (pep->dma_status & ESP_DMA_STAT_ERROR) {
|
||||
u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
|
||||
|
||||
if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (pep->dma_status & ESP_DMA_STAT_ABORT) {
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
|
||||
pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||
u32 dma_count, int write, u8 cmd)
|
||||
{
|
||||
struct pci_esp_priv *pep = pci_esp_get_priv(esp);
|
||||
u32 val = 0;
|
||||
|
||||
BUG_ON(!(cmd & ESP_CMD_DMA));
|
||||
|
||||
pep->dma_status = 0;
|
||||
|
||||
/* Set DMA engine to IDLE */
|
||||
if (write)
|
||||
/* DMA write direction logic is inverted */
|
||||
val |= ESP_DMA_CMD_DIR;
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
|
||||
|
||||
pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
|
||||
pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
|
||||
if (esp->config2 & ESP_CONFIG2_FENAB)
|
||||
pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
|
||||
|
||||
pci_esp_write32(esp, esp_count, ESP_DMA_STC);
|
||||
pci_esp_write32(esp, addr, ESP_DMA_SPA);
|
||||
|
||||
esp_dma_log("start dma addr[%x] count[%d:%d]\n",
|
||||
addr, esp_count, dma_count);
|
||||
|
||||
scsi_esp_cmd(esp, cmd);
|
||||
/* Send DMA Start command */
|
||||
pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
|
||||
}
|
||||
|
||||
static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
|
||||
{
|
||||
int dma_limit = 16;
|
||||
u32 base, end;
|
||||
|
||||
/*
|
||||
* If CONFIG2_FENAB is set we can
|
||||
* handle up to 24 bit addresses
|
||||
*/
|
||||
if (esp->config2 & ESP_CONFIG2_FENAB)
|
||||
dma_limit = 24;
|
||||
|
||||
if (dma_len > (1U << dma_limit))
|
||||
dma_len = (1U << dma_limit);
|
||||
|
||||
/*
|
||||
* Prevent crossing a 24-bit address boundary.
|
||||
*/
|
||||
base = dma_addr & ((1U << 24) - 1U);
|
||||
end = base + dma_len;
|
||||
if (end > (1U << 24))
|
||||
end = (1U <<24);
|
||||
dma_len = end - base;
|
||||
|
||||
return dma_len;
|
||||
}
|
||||
|
||||
static const struct esp_driver_ops pci_esp_ops = {
|
||||
.esp_write8 = pci_esp_write8,
|
||||
.esp_read8 = pci_esp_read8,
|
||||
.map_single = pci_esp_map_single,
|
||||
.map_sg = pci_esp_map_sg,
|
||||
.unmap_single = pci_esp_unmap_single,
|
||||
.unmap_sg = pci_esp_unmap_sg,
|
||||
.irq_pending = pci_esp_irq_pending,
|
||||
.reset_dma = pci_esp_reset_dma,
|
||||
.dma_drain = pci_esp_dma_drain,
|
||||
.dma_invalidate = pci_esp_dma_invalidate,
|
||||
.send_dma_cmd = pci_esp_send_dma_cmd,
|
||||
.dma_error = pci_esp_dma_error,
|
||||
.dma_length_limit = pci_esp_dma_length_limit,
|
||||
};
|
||||
|
||||
/*
|
||||
* Read DC-390 eeprom
|
||||
*/
|
||||
static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
|
||||
{
|
||||
u8 carry_flag = 1, j = 0x80, bval;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (carry_flag) {
|
||||
pci_write_config_byte(pdev, 0x80, 0x40);
|
||||
bval = 0xc0;
|
||||
} else
|
||||
bval = 0x80;
|
||||
|
||||
udelay(160);
|
||||
pci_write_config_byte(pdev, 0x80, bval);
|
||||
udelay(160);
|
||||
pci_write_config_byte(pdev, 0x80, 0);
|
||||
udelay(160);
|
||||
|
||||
carry_flag = (cmd & j) ? 1 : 0;
|
||||
j >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
u16 wval = 0;
|
||||
u8 bval;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
wval <<= 1;
|
||||
|
||||
pci_write_config_byte(pdev, 0x80, 0x80);
|
||||
udelay(160);
|
||||
pci_write_config_byte(pdev, 0x80, 0x40);
|
||||
udelay(160);
|
||||
pci_read_config_byte(pdev, 0x00, &bval);
|
||||
|
||||
if (bval == 0x22)
|
||||
wval |= 1;
|
||||
}
|
||||
|
||||
return wval;
|
||||
}
|
||||
|
||||
static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
|
||||
{
|
||||
u8 cmd = DC390_EEPROM_READ, i;
|
||||
|
||||
for (i = 0; i < DC390_EEPROM_LEN; i++) {
|
||||
pci_write_config_byte(pdev, 0xc0, 0);
|
||||
udelay(160);
|
||||
|
||||
dc390_eeprom_prepare_read(pdev, cmd++);
|
||||
*ptr++ = dc390_eeprom_get_data(pdev);
|
||||
|
||||
pci_write_config_byte(pdev, 0x80, 0);
|
||||
pci_write_config_byte(pdev, 0x80, 0);
|
||||
udelay(160);
|
||||
}
|
||||
}
|
||||
|
||||
static void dc390_check_eeprom(struct esp *esp)
|
||||
{
|
||||
u8 EEbuf[128];
|
||||
u16 *ptr = (u16 *)EEbuf, wval = 0;
|
||||
int i;
|
||||
|
||||
dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
|
||||
|
||||
for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
|
||||
wval += *ptr;
|
||||
|
||||
/* no Tekram EEprom found */
|
||||
if (wval != 0x1234) {
|
||||
struct pci_dev *pdev = esp->dev;
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"No valid Tekram EEprom found\n");
|
||||
return;
|
||||
}
|
||||
esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
|
||||
esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
|
||||
if (EEbuf[DC390_EE_MODE2] & DC390_EE_MODE2_ACTIVE_NEGATION)
|
||||
esp->config4 |= ESP_CONFIG4_RADE | ESP_CONFIG4_RAE;
|
||||
}
|
||||
|
||||
static int pci_esp_probe_one(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct scsi_host_template *hostt = &scsi_esp_template;
|
||||
int err = -ENODEV;
|
||||
struct Scsi_Host *shost;
|
||||
struct esp *esp;
|
||||
struct pci_esp_priv *pep;
|
||||
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"failed to set 32bit DMA mask\n");
|
||||
goto fail_disable_device;
|
||||
}
|
||||
|
||||
shost = scsi_host_alloc(hostt, sizeof(struct esp));
|
||||
if (!shost) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"failed to allocate scsi host\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_disable_device;
|
||||
}
|
||||
|
||||
pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
|
||||
if (!pep) {
|
||||
dev_printk(KERN_INFO, &pdev->dev,
|
||||
"failed to allocate esp_priv\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_host_alloc;
|
||||
}
|
||||
|
||||
esp = shost_priv(shost);
|
||||
esp->host = shost;
|
||||
esp->dev = pdev;
|
||||
esp->ops = &pci_esp_ops;
|
||||
/*
|
||||
* The am53c974 HBA has a design flaw of generating
|
||||
* spurious DMA completion interrupts when using
|
||||
* DMA for command submission.
|
||||
*/
|
||||
esp->flags |= ESP_FLAG_USE_FIFO;
|
||||
/*
|
||||
* Enable CONFIG2_FENAB to allow for large DMA transfers
|
||||
*/
|
||||
if (am53c974_fenab)
|
||||
esp->config2 |= ESP_CONFIG2_FENAB;
|
||||
|
||||
pep->esp = esp;
|
||||
|
||||
if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"pci memory selection failed\n");
|
||||
goto fail_priv_alloc;
|
||||
}
|
||||
|
||||
esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
||||
if (!esp->regs) {
|
||||
dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
|
||||
err = -EINVAL;
|
||||
goto fail_release_regions;
|
||||
}
|
||||
esp->dma_regs = esp->regs;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
esp->command_block = pci_alloc_consistent(pdev, 16,
|
||||
&esp->command_block_dma);
|
||||
if (!esp->command_block) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"failed to allocate command block\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_unmap_regs;
|
||||
}
|
||||
|
||||
err = request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
|
||||
DRV_MODULE_NAME, esp);
|
||||
if (err < 0) {
|
||||
dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
|
||||
goto fail_unmap_command_block;
|
||||
}
|
||||
|
||||
esp->scsi_id = 7;
|
||||
dc390_check_eeprom(esp);
|
||||
|
||||
shost->this_id = esp->scsi_id;
|
||||
shost->max_id = 8;
|
||||
shost->irq = pdev->irq;
|
||||
shost->io_port = pci_resource_start(pdev, 0);
|
||||
shost->n_io_port = pci_resource_len(pdev, 0);
|
||||
shost->unique_id = shost->io_port;
|
||||
esp->scsi_id_mask = (1 << esp->scsi_id);
|
||||
/* Assume 40MHz clock */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
pci_set_drvdata(pdev, pep);
|
||||
|
||||
err = scsi_esp_register(esp, &pdev->dev);
|
||||
if (err)
|
||||
goto fail_free_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_irq:
|
||||
free_irq(pdev->irq, esp);
|
||||
fail_unmap_command_block:
|
||||
pci_free_consistent(pdev, 16, esp->command_block,
|
||||
esp->command_block_dma);
|
||||
fail_unmap_regs:
|
||||
pci_iounmap(pdev, esp->regs);
|
||||
fail_release_regions:
|
||||
pci_release_regions(pdev);
|
||||
fail_priv_alloc:
|
||||
kfree(pep);
|
||||
fail_host_alloc:
|
||||
scsi_host_put(shost);
|
||||
fail_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void pci_esp_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct pci_esp_priv *pep = pci_get_drvdata(pdev);
|
||||
struct esp *esp = pep->esp;
|
||||
|
||||
scsi_esp_unregister(esp);
|
||||
free_irq(pdev->irq, esp);
|
||||
pci_free_consistent(pdev, 16, esp->command_block,
|
||||
esp->command_block_dma);
|
||||
pci_iounmap(pdev, esp->regs);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
kfree(pep);
|
||||
|
||||
scsi_host_put(esp->host);
|
||||
}
|
||||
|
||||
static struct pci_device_id am53c974_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
|
||||
|
||||
static struct pci_driver am53c974_driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
.id_table = am53c974_pci_tbl,
|
||||
.probe = pci_esp_probe_one,
|
||||
.remove = pci_esp_remove_one,
|
||||
};
|
||||
|
||||
static int __init am53c974_module_init(void)
|
||||
{
|
||||
return pci_register_driver(&am53c974_driver);
|
||||
}
|
||||
|
||||
static void __exit am53c974_module_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&am53c974_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("AM53C974 SCSI driver");
|
||||
MODULE_AUTHOR("Hannes Reinecke <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_MODULE_VERSION);
|
||||
MODULE_ALIAS("tmscsim");
|
||||
|
||||
module_param(am53c974_debug, bool, 0644);
|
||||
MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
|
||||
|
||||
module_param(am53c974_fenab, bool, 0444);
|
||||
MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
|
||||
|
||||
module_init(am53c974_module_init);
|
||||
module_exit(am53c974_module_exit);
|
||||
|
|
@ -114,16 +114,11 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
|
|||
static const char *arcmsr_info(struct Scsi_Host *);
|
||||
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *);
|
||||
static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
|
||||
int queue_depth, int reason)
|
||||
static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
|
||||
queue_depth = ARCMSR_MAX_CMD_PERLUN;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
return queue_depth;
|
||||
return scsi_change_queue_depth(sdev, queue_depth);
|
||||
}
|
||||
|
||||
static struct scsi_host_template arcmsr_scsi_host_template = {
|
||||
|
|
|
|||
|
|
@ -13,16 +13,12 @@
|
|||
#include <asm/ecard.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "../scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include <scsi/scsicam.h>
|
||||
|
||||
#define AUTOSENSE
|
||||
#define PSEUDO_DMA
|
||||
|
||||
#define CUMANASCSI_PUBLIC_RELEASE 1
|
||||
|
||||
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
|
||||
#define NCR5380_local_declare() struct Scsi_Host *_instance
|
||||
#define NCR5380_setup(instance) _instance = instance
|
||||
|
|
@ -30,6 +26,7 @@
|
|||
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
|
||||
#define NCR5380_intr cumanascsi_intr
|
||||
#define NCR5380_queue_command cumanascsi_queue_command
|
||||
#define NCR5380_info cumanascsi_info
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
unsigned ctrl; \
|
||||
|
|
@ -42,11 +39,6 @@ void cumanascsi_setup(char *str, int *ints)
|
|||
{
|
||||
}
|
||||
|
||||
const char *cumanascsi_info(struct Scsi_Host *spnt)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#define CTRL 0x16fc
|
||||
#define STAT 0x2004
|
||||
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
|
||||
|
|
@ -267,14 +259,6 @@ static int cumanascsi1_probe(struct expansion_card *ec,
|
|||
goto out_unmap;
|
||||
}
|
||||
|
||||
printk("scsi%d: at port 0x%08lx irq %d",
|
||||
host->host_no, host->io_port, host->irq);
|
||||
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
|
||||
host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
|
||||
printk("\nscsi%d:", host->host_no);
|
||||
NCR5380_print_options(host);
|
||||
printk("\n");
|
||||
|
||||
ret = scsi_add_host(host, &ec->dev);
|
||||
if (ret)
|
||||
goto out_free_irq;
|
||||
|
|
|
|||
|
|
@ -14,13 +14,9 @@
|
|||
#include <asm/ecard.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "../scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#define AUTOSENSE
|
||||
/*#define PSEUDO_DMA*/
|
||||
|
||||
#define OAKSCSI_PUBLIC_RELEASE 1
|
||||
#define DONT_USE_INTR
|
||||
|
||||
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
|
||||
|
|
@ -29,10 +25,9 @@
|
|||
|
||||
#define NCR5380_read(reg) readb(_base + ((reg) << 2))
|
||||
#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2))
|
||||
#define NCR5380_intr oakscsi_intr
|
||||
#define NCR5380_queue_command oakscsi_queue_command
|
||||
#define NCR5380_info oakscsi_info
|
||||
#define NCR5380_show_info oakscsi_show_info
|
||||
#define NCR5380_write_info oakscsi_write_info
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
void __iomem *base
|
||||
|
|
@ -42,11 +37,6 @@
|
|||
#undef START_DMA_INITIATOR_RECEIVE_REG
|
||||
#define START_DMA_INITIATOR_RECEIVE_REG (128 + 7)
|
||||
|
||||
const char * oakscsi_info (struct Scsi_Host *spnt)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#define STAT ((128 + 16) << 2)
|
||||
#define DATA ((128 + 8) << 2)
|
||||
|
||||
|
|
@ -114,7 +104,6 @@ printk("reading %p len %d\n", addr, len);
|
|||
static struct scsi_host_template oakscsi_template = {
|
||||
.module = THIS_MODULE,
|
||||
.show_info = oakscsi_show_info,
|
||||
.write_info = oakscsi_write_info,
|
||||
.name = "Oak 16-bit SCSI",
|
||||
.info = oakscsi_info,
|
||||
.queuecommand = oakscsi_queue_command,
|
||||
|
|
@ -150,19 +139,11 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
|
|||
goto unreg;
|
||||
}
|
||||
|
||||
host->irq = IRQ_NONE;
|
||||
host->irq = NO_IRQ;
|
||||
host->n_io_port = 255;
|
||||
|
||||
NCR5380_init(host, 0);
|
||||
|
||||
printk("scsi%d: at port 0x%08lx irqs disabled",
|
||||
host->host_no, host->io_port);
|
||||
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
|
||||
host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
|
||||
printk("\nscsi%d:", host->host_no);
|
||||
NCR5380_print_options(host);
|
||||
printk("\n");
|
||||
|
||||
ret = scsi_add_host(host, &ec->dev);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -64,45 +64,57 @@
|
|||
/**************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#define AUTOSENSE
|
||||
/* For the Atari version, use only polled IO or REAL_DMA */
|
||||
#define REAL_DMA
|
||||
/* Support tagged queuing? (on devices that are able to... :-) */
|
||||
#define SUPPORT_TAGS
|
||||
#define MAX_TAGS 32
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/nvram.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/atarihw.h>
|
||||
#include <asm/atariints.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "atari_scsi.h"
|
||||
#include "NCR5380.h"
|
||||
#include <asm/atari_stdma.h>
|
||||
#include <asm/atari_stram.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/stat.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
/* Definitions for the core NCR5380 driver. */
|
||||
|
||||
#define REAL_DMA
|
||||
#define SUPPORT_TAGS
|
||||
#define MAX_TAGS 32
|
||||
#define DMA_MIN_SIZE 32
|
||||
|
||||
#define NCR5380_implementation_fields /* none */
|
||||
|
||||
#define NCR5380_read(reg) atari_scsi_reg_read(reg)
|
||||
#define NCR5380_write(reg, value) atari_scsi_reg_write(reg, value)
|
||||
|
||||
#define NCR5380_queue_command atari_scsi_queue_command
|
||||
#define NCR5380_abort atari_scsi_abort
|
||||
#define NCR5380_show_info atari_scsi_show_info
|
||||
#define NCR5380_info atari_scsi_info
|
||||
|
||||
#define NCR5380_dma_read_setup(instance, data, count) \
|
||||
atari_scsi_dma_setup(instance, data, count, 0)
|
||||
#define NCR5380_dma_write_setup(instance, data, count) \
|
||||
atari_scsi_dma_setup(instance, data, count, 1)
|
||||
#define NCR5380_dma_residual(instance) \
|
||||
atari_scsi_dma_residual(instance)
|
||||
#define NCR5380_dma_xfer_len(instance, cmd, phase) \
|
||||
atari_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
|
||||
|
||||
#define NCR5380_acquire_dma_irq(instance) falcon_get_lock(instance)
|
||||
#define NCR5380_release_dma_irq(instance) falcon_release_lock()
|
||||
|
||||
#include "NCR5380.h"
|
||||
|
||||
|
||||
#define IS_A_TT() ATARIHW_PRESENT(TT_SCSI)
|
||||
|
||||
|
|
@ -149,23 +161,6 @@ static inline unsigned long SCSI_DMA_GETADR(void)
|
|||
return adr;
|
||||
}
|
||||
|
||||
static inline void ENABLE_IRQ(void)
|
||||
{
|
||||
if (IS_A_TT())
|
||||
atari_enable_irq(IRQ_TT_MFP_SCSI);
|
||||
else
|
||||
atari_enable_irq(IRQ_MFP_FSCSI);
|
||||
}
|
||||
|
||||
static inline void DISABLE_IRQ(void)
|
||||
{
|
||||
if (IS_A_TT())
|
||||
atari_disable_irq(IRQ_TT_MFP_SCSI);
|
||||
else
|
||||
atari_disable_irq(IRQ_MFP_FSCSI);
|
||||
}
|
||||
|
||||
|
||||
#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \
|
||||
(atari_scsi_host->hostdata))->dma_len)
|
||||
|
||||
|
|
@ -178,30 +173,9 @@ static inline void DISABLE_IRQ(void)
|
|||
#define AFTER_RESET_DELAY (5*HZ/2)
|
||||
#endif
|
||||
|
||||
/***************************** Prototypes *****************************/
|
||||
|
||||
#ifdef REAL_DMA
|
||||
static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
|
||||
static void atari_scsi_fetch_restbytes(void);
|
||||
static long atari_scsi_dma_residual(struct Scsi_Host *instance);
|
||||
static int falcon_classify_cmd(Scsi_Cmnd *cmd);
|
||||
static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
|
||||
Scsi_Cmnd *cmd, int write_flag);
|
||||
#endif
|
||||
static irqreturn_t scsi_tt_intr(int irq, void *dummy);
|
||||
static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
|
||||
static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
|
||||
static void falcon_get_lock(void);
|
||||
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
|
||||
static void atari_scsi_reset_boot(void);
|
||||
#endif
|
||||
static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
|
||||
static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
|
||||
static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
|
||||
static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
|
||||
|
||||
/************************* End of Prototypes **************************/
|
||||
|
||||
|
||||
static struct Scsi_Host *atari_scsi_host;
|
||||
static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
|
||||
|
|
@ -226,8 +200,6 @@ static char *atari_dma_orig_addr;
|
|||
/* mask for address bits that can't be used with the ST-DMA */
|
||||
static unsigned long atari_dma_stram_mask;
|
||||
#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0)
|
||||
/* number of bytes to cut from a transfer to handle NCR overruns */
|
||||
static int atari_read_overruns;
|
||||
#endif
|
||||
|
||||
static int setup_can_queue = -1;
|
||||
|
|
@ -386,10 +358,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy)
|
|||
|
||||
NCR5380_intr(irq, dummy);
|
||||
|
||||
#if 0
|
||||
/* To be sure the int is not masked */
|
||||
atari_enable_irq(IRQ_TT_MFP_SCSI);
|
||||
#endif
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -480,257 +448,35 @@ static void atari_scsi_fetch_restbytes(void)
|
|||
#endif /* REAL_DMA */
|
||||
|
||||
|
||||
static int falcon_got_lock = 0;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(falcon_fairness_wait);
|
||||
static int falcon_trying_lock = 0;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(falcon_try_wait);
|
||||
static int falcon_dont_release = 0;
|
||||
|
||||
/* This function releases the lock on the DMA chip if there is no
|
||||
* connected command and the disconnected queue is empty. On
|
||||
* releasing, instances of falcon_get_lock are awoken, that put
|
||||
* themselves to sleep for fairness. They can now try to get the lock
|
||||
* again (but others waiting longer more probably will win).
|
||||
* connected command and the disconnected queue is empty.
|
||||
*/
|
||||
|
||||
static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
|
||||
static void falcon_release_lock(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (IS_A_TT())
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (falcon_got_lock && !hostdata->disconnected_queue &&
|
||||
!hostdata->issue_queue && !hostdata->connected) {
|
||||
|
||||
if (falcon_dont_release) {
|
||||
#if 0
|
||||
printk("WARNING: Lock release not allowed. Ignored\n");
|
||||
#endif
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
falcon_got_lock = 0;
|
||||
if (stdma_is_locked_by(scsi_falcon_intr))
|
||||
stdma_release();
|
||||
wake_up(&falcon_fairness_wait);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* This function manages the locking of the ST-DMA.
|
||||
* If the DMA isn't locked already for SCSI, it tries to lock it by
|
||||
* calling stdma_lock(). But if the DMA is locked by the SCSI code and
|
||||
* there are other drivers waiting for the chip, we do not issue the
|
||||
* command immediately but wait on 'falcon_fairness_queue'. We will be
|
||||
* waked up when the DMA is unlocked by some SCSI interrupt. After that
|
||||
* we try to get the lock again.
|
||||
* But we must be prepared that more than one instance of
|
||||
* falcon_get_lock() is waiting on the fairness queue. They should not
|
||||
* try all at once to call stdma_lock(), one is enough! For that, the
|
||||
* first one sets 'falcon_trying_lock', others that see that variable
|
||||
* set wait on the queue 'falcon_try_wait'.
|
||||
* Complicated, complicated.... Sigh...
|
||||
* command immediately but tell the SCSI mid-layer to defer.
|
||||
*/
|
||||
|
||||
static void falcon_get_lock(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (IS_A_TT())
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
wait_event_cmd(falcon_fairness_wait,
|
||||
in_interrupt() || !falcon_got_lock || !stdma_others_waiting(),
|
||||
local_irq_restore(flags),
|
||||
local_irq_save(flags));
|
||||
|
||||
while (!falcon_got_lock) {
|
||||
if (in_irq())
|
||||
panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
|
||||
if (!falcon_trying_lock) {
|
||||
falcon_trying_lock = 1;
|
||||
stdma_lock(scsi_falcon_intr, NULL);
|
||||
falcon_got_lock = 1;
|
||||
falcon_trying_lock = 0;
|
||||
wake_up(&falcon_try_wait);
|
||||
} else {
|
||||
wait_event_cmd(falcon_try_wait,
|
||||
falcon_got_lock && !falcon_trying_lock,
|
||||
local_irq_restore(flags),
|
||||
local_irq_save(flags));
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
if (!falcon_got_lock)
|
||||
panic("Falcon SCSI: someone stole the lock :-(\n");
|
||||
}
|
||||
|
||||
|
||||
static int __init atari_scsi_detect(struct scsi_host_template *host)
|
||||
{
|
||||
static int called = 0;
|
||||
struct Scsi_Host *instance;
|
||||
|
||||
if (!MACH_IS_ATARI ||
|
||||
(!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
|
||||
called)
|
||||
return 0;
|
||||
|
||||
host->proc_name = "Atari";
|
||||
|
||||
atari_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read :
|
||||
atari_scsi_falcon_reg_read;
|
||||
atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
|
||||
atari_scsi_falcon_reg_write;
|
||||
|
||||
/* setup variables */
|
||||
host->can_queue =
|
||||
(setup_can_queue > 0) ? setup_can_queue :
|
||||
IS_A_TT() ? ATARI_TT_CAN_QUEUE : ATARI_FALCON_CAN_QUEUE;
|
||||
host->cmd_per_lun =
|
||||
(setup_cmd_per_lun > 0) ? setup_cmd_per_lun :
|
||||
IS_A_TT() ? ATARI_TT_CMD_PER_LUN : ATARI_FALCON_CMD_PER_LUN;
|
||||
/* Force sg_tablesize to 0 on a Falcon! */
|
||||
host->sg_tablesize =
|
||||
!IS_A_TT() ? ATARI_FALCON_SG_TABLESIZE :
|
||||
(setup_sg_tablesize >= 0) ? setup_sg_tablesize : ATARI_TT_SG_TABLESIZE;
|
||||
|
||||
if (setup_hostid >= 0)
|
||||
host->this_id = setup_hostid;
|
||||
else {
|
||||
/* use 7 as default */
|
||||
host->this_id = 7;
|
||||
/* Test if a host id is set in the NVRam */
|
||||
if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
|
||||
unsigned char b = nvram_read_byte( 14 );
|
||||
/* Arbitration enabled? (for TOS) If yes, use configured host ID */
|
||||
if (b & 0x80)
|
||||
host->this_id = b & 7;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
if (setup_use_tagged_queuing < 0)
|
||||
setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
|
||||
#endif
|
||||
#ifdef REAL_DMA
|
||||
/* If running on a Falcon and if there's TT-Ram (i.e., more than one
|
||||
* memory block, since there's always ST-Ram in a Falcon), then allocate a
|
||||
* STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative
|
||||
* Ram.
|
||||
*/
|
||||
if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) &&
|
||||
!ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
|
||||
atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
|
||||
if (!atari_dma_buffer) {
|
||||
printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
|
||||
"double buffer\n");
|
||||
return 0;
|
||||
}
|
||||
atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
|
||||
atari_dma_orig_addr = 0;
|
||||
}
|
||||
#endif
|
||||
instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
|
||||
if (instance == NULL) {
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
atari_dma_buffer = 0;
|
||||
return 0;
|
||||
}
|
||||
atari_scsi_host = instance;
|
||||
/*
|
||||
* Set irq to 0, to avoid that the mid-level code disables our interrupt
|
||||
* during queue_command calls. This is completely unnecessary, and even
|
||||
* worse causes bad problems on the Falcon, where the int is shared with
|
||||
* IDE and floppy!
|
||||
*/
|
||||
instance->irq = 0;
|
||||
|
||||
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
|
||||
atari_scsi_reset_boot();
|
||||
#endif
|
||||
NCR5380_init(instance, 0);
|
||||
|
||||
if (IS_A_TT()) {
|
||||
|
||||
/* This int is actually "pseudo-slow", i.e. it acts like a slow
|
||||
* interrupt after having cleared the pending flag for the DMA
|
||||
* interrupt. */
|
||||
if (request_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW,
|
||||
"SCSI NCR5380", instance)) {
|
||||
printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting",IRQ_TT_MFP_SCSI);
|
||||
scsi_unregister(atari_scsi_host);
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
atari_dma_buffer = 0;
|
||||
return 0;
|
||||
}
|
||||
tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */
|
||||
#ifdef REAL_DMA
|
||||
tt_scsi_dma.dma_ctrl = 0;
|
||||
atari_dma_residual = 0;
|
||||
|
||||
if (MACH_IS_MEDUSA) {
|
||||
/* While the read overruns (described by Drew Eckhardt in
|
||||
* NCR5380.c) never happened on TTs, they do in fact on the Medusa
|
||||
* (This was the cause why SCSI didn't work right for so long
|
||||
* there.) Since handling the overruns slows down a bit, I turned
|
||||
* the #ifdef's into a runtime condition.
|
||||
*
|
||||
* In principle it should be sufficient to do max. 1 byte with
|
||||
* PIO, but there is another problem on the Medusa with the DMA
|
||||
* rest data register. So 'atari_read_overruns' is currently set
|
||||
* to 4 to avoid having transfers that aren't a multiple of 4. If
|
||||
* the rest data bug is fixed, this can be lowered to 1.
|
||||
*/
|
||||
atari_read_overruns = 4;
|
||||
}
|
||||
#endif /*REAL_DMA*/
|
||||
} else { /* ! IS_A_TT */
|
||||
|
||||
/* Nothing to do for the interrupt: the ST-DMA is initialized
|
||||
* already by atari_init_INTS()
|
||||
*/
|
||||
|
||||
#ifdef REAL_DMA
|
||||
atari_dma_residual = 0;
|
||||
atari_dma_active = 0;
|
||||
atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
|
||||
: 0xff000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
|
||||
#ifdef SUPPORT_TAGS
|
||||
"TAGGED-QUEUING=%s "
|
||||
#endif
|
||||
"HOSTID=%d",
|
||||
instance->host_no, instance->hostt->can_queue,
|
||||
instance->hostt->cmd_per_lun,
|
||||
instance->hostt->sg_tablesize,
|
||||
#ifdef SUPPORT_TAGS
|
||||
setup_use_tagged_queuing ? "yes" : "no",
|
||||
#endif
|
||||
instance->hostt->this_id );
|
||||
NCR5380_print_options(instance);
|
||||
printk("\n");
|
||||
|
||||
called = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int atari_scsi_release(struct Scsi_Host *sh)
|
||||
static int falcon_get_lock(struct Scsi_Host *instance)
|
||||
{
|
||||
if (IS_A_TT())
|
||||
free_irq(IRQ_TT_MFP_SCSI, sh);
|
||||
if (atari_dma_buffer)
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
NCR5380_exit(sh);
|
||||
return 1;
|
||||
|
||||
if (in_interrupt())
|
||||
return stdma_try_lock(scsi_falcon_intr, instance);
|
||||
|
||||
stdma_lock(scsi_falcon_intr, instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -739,7 +485,7 @@ static int __init atari_scsi_setup(char *str)
|
|||
{
|
||||
/* Format of atascsi parameter is:
|
||||
* atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
|
||||
* Defaults depend on TT or Falcon, hostid determined at run time.
|
||||
* Defaults depend on TT or Falcon, determined at run time.
|
||||
* Negative values mean don't change.
|
||||
*/
|
||||
int ints[6];
|
||||
|
|
@ -750,36 +496,17 @@ static int __init atari_scsi_setup(char *str)
|
|||
printk("atari_scsi_setup: no arguments!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ints[0] >= 1) {
|
||||
if (ints[1] > 0)
|
||||
/* no limits on this, just > 0 */
|
||||
setup_can_queue = ints[1];
|
||||
}
|
||||
if (ints[0] >= 2) {
|
||||
if (ints[2] > 0)
|
||||
setup_cmd_per_lun = ints[2];
|
||||
}
|
||||
if (ints[0] >= 3) {
|
||||
if (ints[3] >= 0) {
|
||||
setup_sg_tablesize = ints[3];
|
||||
/* Must be <= SG_ALL (255) */
|
||||
if (setup_sg_tablesize > SG_ALL)
|
||||
setup_sg_tablesize = SG_ALL;
|
||||
}
|
||||
}
|
||||
if (ints[0] >= 4) {
|
||||
/* Must be between 0 and 7 */
|
||||
if (ints[4] >= 0 && ints[4] <= 7)
|
||||
setup_hostid = ints[4];
|
||||
else if (ints[4] > 7)
|
||||
printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
|
||||
}
|
||||
if (ints[0] >= 1)
|
||||
setup_can_queue = ints[1];
|
||||
if (ints[0] >= 2)
|
||||
setup_cmd_per_lun = ints[2];
|
||||
if (ints[0] >= 3)
|
||||
setup_sg_tablesize = ints[3];
|
||||
if (ints[0] >= 4)
|
||||
setup_hostid = ints[4];
|
||||
#ifdef SUPPORT_TAGS
|
||||
if (ints[0] >= 5) {
|
||||
if (ints[5] >= 0)
|
||||
setup_use_tagged_queuing = !!ints[5];
|
||||
}
|
||||
if (ints[0] >= 5)
|
||||
setup_use_tagged_queuing = ints[5];
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
|
@ -788,45 +515,6 @@ static int __init atari_scsi_setup(char *str)
|
|||
__setup("atascsi=", atari_scsi_setup);
|
||||
#endif /* !MODULE */
|
||||
|
||||
static int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
|
||||
{
|
||||
int rv;
|
||||
struct NCR5380_hostdata *hostdata =
|
||||
(struct NCR5380_hostdata *)cmd->device->host->hostdata;
|
||||
|
||||
/* For doing the reset, SCSI interrupts must be disabled first,
|
||||
* since the 5380 raises its IRQ line while _RST is active and we
|
||||
* can't disable interrupts completely, since we need the timer.
|
||||
*/
|
||||
/* And abort a maybe active DMA transfer */
|
||||
if (IS_A_TT()) {
|
||||
atari_turnoff_irq(IRQ_TT_MFP_SCSI);
|
||||
#ifdef REAL_DMA
|
||||
tt_scsi_dma.dma_ctrl = 0;
|
||||
#endif /* REAL_DMA */
|
||||
} else {
|
||||
atari_turnoff_irq(IRQ_MFP_FSCSI);
|
||||
#ifdef REAL_DMA
|
||||
st_dma.dma_mode_status = 0x90;
|
||||
atari_dma_active = 0;
|
||||
atari_dma_orig_addr = NULL;
|
||||
#endif /* REAL_DMA */
|
||||
}
|
||||
|
||||
rv = NCR5380_bus_reset(cmd);
|
||||
|
||||
/* Re-enable ints */
|
||||
if (IS_A_TT()) {
|
||||
atari_turnon_irq(IRQ_TT_MFP_SCSI);
|
||||
} else {
|
||||
atari_turnon_irq(IRQ_MFP_FSCSI);
|
||||
}
|
||||
if (rv == SUCCESS)
|
||||
falcon_release_lock_if_possible(hostdata);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
|
||||
static void __init atari_scsi_reset_boot(void)
|
||||
|
|
@ -860,15 +548,6 @@ static void __init atari_scsi_reset_boot(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const char *atari_scsi_info(struct Scsi_Host *host)
|
||||
{
|
||||
/* atari_scsi_detect() is verbose enough... */
|
||||
static const char string[] = "Atari native SCSI";
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
#if defined(REAL_DMA)
|
||||
|
||||
static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance,
|
||||
|
|
@ -949,7 +628,7 @@ static long atari_scsi_dma_residual(struct Scsi_Host *instance)
|
|||
#define CMD_SURELY_BYTE_MODE 1
|
||||
#define CMD_MODE_UNKNOWN 2
|
||||
|
||||
static int falcon_classify_cmd(Scsi_Cmnd *cmd)
|
||||
static int falcon_classify_cmd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
unsigned char opcode = cmd->cmnd[0];
|
||||
|
||||
|
|
@ -981,7 +660,7 @@ static int falcon_classify_cmd(Scsi_Cmnd *cmd)
|
|||
*/
|
||||
|
||||
static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
|
||||
Scsi_Cmnd *cmd, int write_flag)
|
||||
struct scsi_cmnd *cmd, int write_flag)
|
||||
{
|
||||
unsigned long possible_len, limit;
|
||||
|
||||
|
|
@ -1099,23 +778,247 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
|
|||
|
||||
#include "atari_NCR5380.c"
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
static int atari_scsi_bus_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
int rv;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
#ifdef REAL_DMA
|
||||
/* Abort a maybe active DMA transfer */
|
||||
if (IS_A_TT()) {
|
||||
tt_scsi_dma.dma_ctrl = 0;
|
||||
} else {
|
||||
st_dma.dma_mode_status = 0x90;
|
||||
atari_dma_active = 0;
|
||||
atari_dma_orig_addr = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = NCR5380_bus_reset(cmd);
|
||||
|
||||
/* The 5380 raises its IRQ line while _RST is active but the ST DMA
|
||||
* "lock" has been released so this interrupt may end up handled by
|
||||
* floppy or IDE driver (if one of them holds the lock). The NCR5380
|
||||
* interrupt flag has been cleared already.
|
||||
*/
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define DRV_MODULE_NAME "atari_scsi"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
|
||||
static struct scsi_host_template atari_scsi_template = {
|
||||
.module = THIS_MODULE,
|
||||
.proc_name = DRV_MODULE_NAME,
|
||||
.show_info = atari_scsi_show_info,
|
||||
.name = "Atari native SCSI",
|
||||
.detect = atari_scsi_detect,
|
||||
.release = atari_scsi_release,
|
||||
.info = atari_scsi_info,
|
||||
.queuecommand = atari_scsi_queue_command,
|
||||
.eh_abort_handler = atari_scsi_abort,
|
||||
.eh_bus_reset_handler = atari_scsi_bus_reset,
|
||||
.can_queue = 0, /* initialized at run-time */
|
||||
.this_id = 0, /* initialized at run-time */
|
||||
.sg_tablesize = 0, /* initialized at run-time */
|
||||
.cmd_per_lun = 0, /* initialized at run-time */
|
||||
.this_id = 7,
|
||||
.use_clustering = DISABLE_CLUSTERING
|
||||
};
|
||||
|
||||
static int __init atari_scsi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance;
|
||||
int error;
|
||||
struct resource *irq;
|
||||
int host_flags = 0;
|
||||
|
||||
#include "scsi_module.c"
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!irq)
|
||||
return -ENODEV;
|
||||
|
||||
if (ATARIHW_PRESENT(TT_SCSI)) {
|
||||
atari_scsi_reg_read = atari_scsi_tt_reg_read;
|
||||
atari_scsi_reg_write = atari_scsi_tt_reg_write;
|
||||
} else {
|
||||
atari_scsi_reg_read = atari_scsi_falcon_reg_read;
|
||||
atari_scsi_reg_write = atari_scsi_falcon_reg_write;
|
||||
}
|
||||
|
||||
/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary.
|
||||
* Higher values should work, too; try it!
|
||||
* (But cmd_per_lun costs memory!)
|
||||
*
|
||||
* But there seems to be a bug somewhere that requires CAN_QUEUE to be
|
||||
* 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
|
||||
* changed CMD_PER_LUN...
|
||||
*
|
||||
* Note: The Falcon currently uses 8/1 setting due to unsolved problems
|
||||
* with cmd_per_lun != 1
|
||||
*/
|
||||
if (ATARIHW_PRESENT(TT_SCSI)) {
|
||||
atari_scsi_template.can_queue = 16;
|
||||
atari_scsi_template.cmd_per_lun = 8;
|
||||
atari_scsi_template.sg_tablesize = SG_ALL;
|
||||
} else {
|
||||
atari_scsi_template.can_queue = 8;
|
||||
atari_scsi_template.cmd_per_lun = 1;
|
||||
atari_scsi_template.sg_tablesize = SG_NONE;
|
||||
}
|
||||
|
||||
if (setup_can_queue > 0)
|
||||
atari_scsi_template.can_queue = setup_can_queue;
|
||||
|
||||
if (setup_cmd_per_lun > 0)
|
||||
atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
|
||||
|
||||
/* Leave sg_tablesize at 0 on a Falcon! */
|
||||
if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0)
|
||||
atari_scsi_template.sg_tablesize = setup_sg_tablesize;
|
||||
|
||||
if (setup_hostid >= 0) {
|
||||
atari_scsi_template.this_id = setup_hostid & 7;
|
||||
} else {
|
||||
/* Test if a host id is set in the NVRam */
|
||||
if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
|
||||
unsigned char b = nvram_read_byte(14);
|
||||
|
||||
/* Arbitration enabled? (for TOS)
|
||||
* If yes, use configured host ID
|
||||
*/
|
||||
if (b & 0x80)
|
||||
atari_scsi_template.this_id = b & 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef REAL_DMA
|
||||
/* If running on a Falcon and if there's TT-Ram (i.e., more than one
|
||||
* memory block, since there's always ST-Ram in a Falcon), then
|
||||
* allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers
|
||||
* from/to alternative Ram.
|
||||
*/
|
||||
if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) &&
|
||||
m68k_num_memory > 1) {
|
||||
atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
|
||||
if (!atari_dma_buffer) {
|
||||
pr_err(PFX "can't allocate ST-RAM double buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
|
||||
atari_dma_orig_addr = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
instance = scsi_host_alloc(&atari_scsi_template,
|
||||
sizeof(struct NCR5380_hostdata));
|
||||
if (!instance) {
|
||||
error = -ENOMEM;
|
||||
goto fail_alloc;
|
||||
}
|
||||
atari_scsi_host = instance;
|
||||
|
||||
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
|
||||
atari_scsi_reset_boot();
|
||||
#endif
|
||||
|
||||
instance->irq = irq->start;
|
||||
|
||||
host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
|
||||
#endif
|
||||
|
||||
NCR5380_init(instance, host_flags);
|
||||
|
||||
if (IS_A_TT()) {
|
||||
error = request_irq(instance->irq, scsi_tt_intr, 0,
|
||||
"NCR5380", instance);
|
||||
if (error) {
|
||||
pr_err(PFX "request irq %d failed, aborting\n",
|
||||
instance->irq);
|
||||
goto fail_irq;
|
||||
}
|
||||
tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */
|
||||
#ifdef REAL_DMA
|
||||
tt_scsi_dma.dma_ctrl = 0;
|
||||
atari_dma_residual = 0;
|
||||
|
||||
/* While the read overruns (described by Drew Eckhardt in
|
||||
* NCR5380.c) never happened on TTs, they do in fact on the
|
||||
* Medusa (This was the cause why SCSI didn't work right for
|
||||
* so long there.) Since handling the overruns slows down
|
||||
* a bit, I turned the #ifdef's into a runtime condition.
|
||||
*
|
||||
* In principle it should be sufficient to do max. 1 byte with
|
||||
* PIO, but there is another problem on the Medusa with the DMA
|
||||
* rest data register. So read_overruns is currently set
|
||||
* to 4 to avoid having transfers that aren't a multiple of 4.
|
||||
* If the rest data bug is fixed, this can be lowered to 1.
|
||||
*/
|
||||
if (MACH_IS_MEDUSA) {
|
||||
struct NCR5380_hostdata *hostdata =
|
||||
shost_priv(instance);
|
||||
|
||||
hostdata->read_overruns = 4;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* Nothing to do for the interrupt: the ST-DMA is initialized
|
||||
* already.
|
||||
*/
|
||||
#ifdef REAL_DMA
|
||||
atari_dma_residual = 0;
|
||||
atari_dma_active = 0;
|
||||
atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
|
||||
: 0xff000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
error = scsi_add_host(instance, NULL);
|
||||
if (error)
|
||||
goto fail_host;
|
||||
|
||||
platform_set_drvdata(pdev, instance);
|
||||
|
||||
scsi_scan_host(instance);
|
||||
return 0;
|
||||
|
||||
fail_host:
|
||||
if (IS_A_TT())
|
||||
free_irq(instance->irq, instance);
|
||||
fail_irq:
|
||||
NCR5380_exit(instance);
|
||||
scsi_host_put(instance);
|
||||
fail_alloc:
|
||||
if (atari_dma_buffer)
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit atari_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
|
||||
scsi_remove_host(instance);
|
||||
if (IS_A_TT())
|
||||
free_irq(instance->irq, instance);
|
||||
NCR5380_exit(instance);
|
||||
scsi_host_put(instance);
|
||||
if (atari_dma_buffer)
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver atari_scsi_driver = {
|
||||
.remove = __exit_p(atari_scsi_remove),
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe);
|
||||
|
||||
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* atari_scsi.h -- Header file for the Atari native SCSI driver
|
||||
*
|
||||
* Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
|
||||
*
|
||||
* (Loosely based on the work of Robert De Vries' team)
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATARI_SCSI_H
|
||||
#define ATARI_SCSI_H
|
||||
|
||||
/* (I_HAVE_OVERRUNS stuff removed) */
|
||||
|
||||
#ifndef ASM
|
||||
/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
|
||||
* values should work, too; try it! (but cmd_per_lun costs memory!) */
|
||||
|
||||
/* But there seems to be a bug somewhere that requires CAN_QUEUE to be
|
||||
* 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
|
||||
* changed CMD_PER_LUN... */
|
||||
|
||||
/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with
|
||||
* cmd_per_lun != 1 */
|
||||
|
||||
#define ATARI_TT_CAN_QUEUE 16
|
||||
#define ATARI_TT_CMD_PER_LUN 8
|
||||
#define ATARI_TT_SG_TABLESIZE SG_ALL
|
||||
|
||||
#define ATARI_FALCON_CAN_QUEUE 8
|
||||
#define ATARI_FALCON_CMD_PER_LUN 1
|
||||
#define ATARI_FALCON_SG_TABLESIZE SG_NONE
|
||||
|
||||
#define DEFAULT_USE_TAGGED_QUEUING 0
|
||||
|
||||
|
||||
#define NCR5380_implementation_fields /* none */
|
||||
|
||||
#define NCR5380_read(reg) atari_scsi_reg_read( reg )
|
||||
#define NCR5380_write(reg, value) atari_scsi_reg_write( reg, value )
|
||||
|
||||
#define NCR5380_intr atari_scsi_intr
|
||||
#define NCR5380_queue_command atari_scsi_queue_command
|
||||
#define NCR5380_abort atari_scsi_abort
|
||||
#define NCR5380_show_info atari_scsi_show_info
|
||||
#define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
|
||||
#define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
|
||||
#define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
|
||||
#define NCR5380_dma_xfer_len(i,cmd,phase) \
|
||||
atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
|
||||
|
||||
#endif /* ndef ASM */
|
||||
#endif /* ATARI_SCSI_H */
|
||||
|
||||
|
||||
|
|
@ -556,7 +556,7 @@ static struct scsi_host_template beiscsi_sht = {
|
|||
.name = "Emulex 10Gbe open-iscsi Initiator Driver",
|
||||
.proc_name = DRV_NAME,
|
||||
.queuecommand = iscsi_queuecommand,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.slave_configure = beiscsi_slave_configure,
|
||||
.target_alloc = iscsi_target_alloc,
|
||||
.eh_abort_handler = beiscsi_eh_abort,
|
||||
|
|
@ -570,7 +570,7 @@ static struct scsi_host_template beiscsi_sht = {
|
|||
.cmd_per_lun = BEISCSI_CMD_PER_LUN,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
|
||||
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct scsi_transport_template *beiscsi_scsi_transport;
|
||||
|
|
|
|||
|
|
@ -260,18 +260,9 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
|
|||
unsigned long flags;
|
||||
void *kern_buf;
|
||||
|
||||
kern_buf = kzalloc(nbytes, GFP_KERNEL);
|
||||
|
||||
if (!kern_buf) {
|
||||
printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
|
||||
bfad->inst_no);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
|
||||
kfree(kern_buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kern_buf = memdup_user(buf, nbytes);
|
||||
if (IS_ERR(kern_buf))
|
||||
return PTR_ERR(kern_buf);
|
||||
|
||||
rc = sscanf(kern_buf, "%x:%x", &addr, &len);
|
||||
if (rc < 2) {
|
||||
|
|
@ -336,18 +327,9 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
|
|||
unsigned long flags;
|
||||
void *kern_buf;
|
||||
|
||||
kern_buf = kzalloc(nbytes, GFP_KERNEL);
|
||||
|
||||
if (!kern_buf) {
|
||||
printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
|
||||
bfad->inst_no);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
|
||||
kfree(kern_buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kern_buf = memdup_user(buf, nbytes);
|
||||
if (IS_ERR(kern_buf))
|
||||
return PTR_ERR(kern_buf);
|
||||
|
||||
rc = sscanf(kern_buf, "%x:%x", &addr, &val);
|
||||
if (rc < 2) {
|
||||
|
|
|
|||
|
|
@ -776,7 +776,7 @@ bfad_thread_workq(struct bfad_s *bfad)
|
|||
static int
|
||||
bfad_im_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
scsi_adjust_queue_depth(sdev, bfa_lun_queue_depth);
|
||||
scsi_change_queue_depth(sdev, bfa_lun_queue_depth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -866,7 +866,7 @@ bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
|
|||
if (bfa_lun_queue_depth > tmp_sdev->queue_depth) {
|
||||
if (tmp_sdev->id != sdev->id)
|
||||
continue;
|
||||
scsi_adjust_queue_depth(tmp_sdev,
|
||||
scsi_change_queue_depth(tmp_sdev,
|
||||
tmp_sdev->queue_depth + 1);
|
||||
|
||||
itnim->last_ramp_up_time = jiffies;
|
||||
|
|
|
|||
|
|
@ -1088,7 +1088,7 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
|
|||
mutex_unlock(&bnx2fc_dev_lock);
|
||||
rtnl_unlock();
|
||||
|
||||
if (IS_ERR(vn_port)) {
|
||||
if (!vn_port) {
|
||||
printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
|
||||
netdev->name);
|
||||
return -EIO;
|
||||
|
|
@ -2202,6 +2202,7 @@ static int _bnx2fc_create(struct net_device *netdev,
|
|||
interface = bnx2fc_interface_create(hba, netdev, fip_mode);
|
||||
if (!interface) {
|
||||
printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
|
||||
rc = -ENOMEM;
|
||||
goto ifput_err;
|
||||
}
|
||||
|
||||
|
|
@ -2790,7 +2791,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
|
|||
.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
|
||||
.eh_host_reset_handler = fc_eh_host_reset,
|
||||
.slave_alloc = fc_slave_alloc,
|
||||
.change_queue_depth = fc_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.this_id = -1,
|
||||
.cmd_per_lun = 3,
|
||||
|
|
@ -2798,6 +2799,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
|
|||
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
|
||||
.max_sectors = 1024,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
|
||||
|
|
|
|||
|
|
@ -2259,7 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = {
|
|||
.eh_abort_handler = iscsi_eh_abort,
|
||||
.eh_device_reset_handler = iscsi_eh_device_reset,
|
||||
.eh_target_reset_handler = iscsi_eh_recover_target,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.target_alloc = iscsi_target_alloc,
|
||||
.can_queue = 2048,
|
||||
.max_sectors = 127,
|
||||
|
|
@ -2268,6 +2268,7 @@ static struct scsi_host_template bnx2i_host_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.sg_tablesize = ISCSI_MAX_BDS_PER_CMD,
|
||||
.shost_attrs = bnx2i_dev_attributes,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
struct iscsi_transport bnx2i_iscsi_transport = {
|
||||
|
|
|
|||
|
|
@ -2241,7 +2241,7 @@ csio_slave_alloc(struct scsi_device *sdev)
|
|||
static int
|
||||
csio_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
scsi_adjust_queue_depth(sdev, csio_lun_qdepth);
|
||||
scsi_change_queue_depth(sdev, csio_lun_qdepth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ static struct scsi_host_template cxgb3i_host_template = {
|
|||
.proc_name = DRV_MODULE_NAME,
|
||||
.can_queue = CXGB3I_SCSI_HOST_QDEPTH,
|
||||
.queuecommand = iscsi_queuecommand,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.max_sectors = 0xFFFF,
|
||||
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
|
||||
|
|
@ -96,6 +96,7 @@ static struct scsi_host_template cxgb3i_host_template = {
|
|||
.target_alloc = iscsi_target_alloc,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
.this_id = -1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct iscsi_transport cxgb3i_iscsi_transport = {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static struct scsi_host_template cxgb4i_host_template = {
|
|||
.proc_name = DRV_MODULE_NAME,
|
||||
.can_queue = CXGB4I_SCSI_HOST_QDEPTH,
|
||||
.queuecommand = iscsi_queuecommand,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.max_sectors = 0xFFFF,
|
||||
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
|
||||
|
|
@ -99,6 +99,7 @@ static struct scsi_host_template cxgb4i_host_template = {
|
|||
.target_alloc = iscsi_target_alloc,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
.this_id = -1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct iscsi_transport cxgb4i_iscsi_transport = {
|
||||
|
|
|
|||
|
|
@ -33,20 +33,20 @@
|
|||
/*
|
||||
* Definitions for the generic 5380 driver.
|
||||
*/
|
||||
#define AUTOSENSE
|
||||
|
||||
#define DONT_USE_INTR
|
||||
|
||||
#define NCR5380_read(reg) inb(port + reg)
|
||||
#define NCR5380_write(reg, value) outb(value, port + reg)
|
||||
|
||||
#define NCR5380_implementation_fields unsigned int port
|
||||
#define NCR5380_local_declare() NCR5380_implementation_fields
|
||||
#define NCR5380_implementation_fields /* none */
|
||||
#define NCR5380_local_declare() unsigned int port
|
||||
#define NCR5380_setup(instance) port = instance->io_port
|
||||
|
||||
/*
|
||||
* Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h)
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include "scsi.h"
|
||||
|
||||
#include "NCR5380.h"
|
||||
#include "NCR5380.c"
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
static struct scsi_host_template dmx3191d_driver_template = {
|
||||
.proc_name = DMX3191D_DRIVER_NAME,
|
||||
.name = "Domex DMX3191D",
|
||||
.info = NCR5380_info,
|
||||
.queuecommand = NCR5380_queue_command,
|
||||
.eh_abort_handler = NCR5380_abort,
|
||||
.eh_bus_reset_handler = NCR5380_bus_reset,
|
||||
|
|
@ -90,31 +91,23 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
|
|||
if (!shost)
|
||||
goto out_release_region;
|
||||
shost->io_port = io;
|
||||
shost->irq = pdev->irq;
|
||||
|
||||
/* This card does not seem to raise an interrupt on pdev->irq.
|
||||
* Steam-powered SCSI controllers run without an IRQ anyway.
|
||||
*/
|
||||
shost->irq = NO_IRQ;
|
||||
|
||||
NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
|
||||
|
||||
if (request_irq(pdev->irq, NCR5380_intr, IRQF_SHARED,
|
||||
DMX3191D_DRIVER_NAME, shost)) {
|
||||
/*
|
||||
* Steam powered scsi controllers run without an IRQ anyway
|
||||
*/
|
||||
printk(KERN_WARNING "dmx3191: IRQ %d not available - "
|
||||
"switching to polled mode.\n", pdev->irq);
|
||||
shost->irq = SCSI_IRQ_NONE;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, shost);
|
||||
|
||||
error = scsi_add_host(shost, &pdev->dev);
|
||||
if (error)
|
||||
goto out_free_irq;
|
||||
goto out_release_region;
|
||||
|
||||
scsi_scan_host(shost);
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
free_irq(shost->irq, shost);
|
||||
out_release_region:
|
||||
release_region(io, DMX3191D_REGION_LEN);
|
||||
out_disable_device:
|
||||
|
|
@ -131,8 +124,6 @@ static void dmx3191d_remove_one(struct pci_dev *pdev)
|
|||
|
||||
NCR5380_exit(shost);
|
||||
|
||||
if (shost->irq != SCSI_IRQ_NONE)
|
||||
free_irq(shost->irq, shost);
|
||||
release_region(shost->io_port, DMX3191D_REGION_LEN);
|
||||
pci_disable_device(pdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ static int adpt_slave_configure(struct scsi_device * device)
|
|||
pHba = (adpt_hba *) host->hostdata[0];
|
||||
|
||||
if (host->can_queue && device->tagged_supported) {
|
||||
scsi_adjust_queue_depth(device,
|
||||
scsi_change_queue_depth(device,
|
||||
host->can_queue - 1);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
#define AUTOSENSE
|
||||
#define PSEUDO_DMA
|
||||
#define DONT_USE_INTR
|
||||
#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
|
||||
|
|
@ -18,29 +17,9 @@
|
|||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 440-4894
|
||||
*
|
||||
* DISTRIBUTION RELEASE 1.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Options :
|
||||
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
|
||||
* for commands that return with a CHECK CONDITION status.
|
||||
*
|
||||
* PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
|
||||
* increase compared to polled I/O.
|
||||
*
|
||||
* PARITY - enable parity checking. Not supported.
|
||||
*
|
||||
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers.
|
||||
* You probably want this.
|
||||
*
|
||||
* The card is detected and initialized in one of several ways :
|
||||
* 1. Autoprobe (default) - since the board is memory mapped,
|
||||
* a BIOS signature is scanned for to locate the registers.
|
||||
|
|
@ -79,15 +58,11 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "dtc.h"
|
||||
#define AUTOPROBE_IRQ
|
||||
#include "NCR5380.h"
|
||||
|
||||
|
||||
#define DTC_PUBLIC_RELEASE 2
|
||||
|
||||
/*
|
||||
* The DTC3180 & 3280 boards are memory mapped.
|
||||
*
|
||||
|
|
@ -173,10 +148,13 @@ static const struct signature {
|
|||
*
|
||||
*/
|
||||
|
||||
static void __init dtc_setup(char *str, int *ints)
|
||||
static int __init dtc_setup(char *str)
|
||||
{
|
||||
static int commandline_current = 0;
|
||||
int i;
|
||||
int ints[10];
|
||||
|
||||
get_options(str, ARRAY_SIZE(ints), ints);
|
||||
if (ints[0] != 2)
|
||||
printk("dtc_setup: usage dtc=address,irq\n");
|
||||
else if (commandline_current < NO_OVERRIDES) {
|
||||
|
|
@ -189,7 +167,10 @@ static void __init dtc_setup(char *str, int *ints)
|
|||
}
|
||||
++commandline_current;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("dtc=", dtc_setup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -213,10 +194,6 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
|
|||
void __iomem *base;
|
||||
int sig, count;
|
||||
|
||||
tpnt->proc_name = "dtc3x80";
|
||||
tpnt->show_info = dtc_show_info;
|
||||
tpnt->write_info = dtc_write_info;
|
||||
|
||||
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
|
||||
addr = 0;
|
||||
base = NULL;
|
||||
|
|
@ -271,38 +248,33 @@ found:
|
|||
else
|
||||
instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
|
||||
|
||||
/* Compatibility with documented NCR5380 kernel parameters */
|
||||
if (instance->irq == 255)
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
#ifndef DONT_USE_INTR
|
||||
/* With interrupts enabled, it will sometimes hang when doing heavy
|
||||
* reads. So better not enable them until I finger it out. */
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
if (instance->irq != NO_IRQ)
|
||||
if (request_irq(instance->irq, dtc_intr, 0,
|
||||
"dtc", instance)) {
|
||||
printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
|
||||
instance->irq = SCSI_IRQ_NONE;
|
||||
instance->irq = NO_IRQ;
|
||||
}
|
||||
|
||||
if (instance->irq == SCSI_IRQ_NONE) {
|
||||
if (instance->irq == NO_IRQ) {
|
||||
printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
|
||||
printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
|
||||
}
|
||||
#else
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
if (instance->irq != NO_IRQ)
|
||||
printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
|
||||
instance->irq = SCSI_IRQ_NONE;
|
||||
instance->irq = NO_IRQ;
|
||||
#endif
|
||||
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
|
||||
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
printk(" interrupts disabled");
|
||||
else
|
||||
printk(" irq %d", instance->irq);
|
||||
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
|
||||
NCR5380_print_options(instance);
|
||||
printk("\n");
|
||||
|
||||
++current_override;
|
||||
++count;
|
||||
}
|
||||
|
|
@ -354,20 +326,18 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
|
|||
* timeout.
|
||||
*/
|
||||
|
||||
static int dtc_maxi = 0;
|
||||
static int dtc_wmaxi = 0;
|
||||
|
||||
static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
|
||||
{
|
||||
unsigned char *d = dst;
|
||||
int i; /* For counting time spent in the poll-loop */
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
i = 0;
|
||||
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
|
||||
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
if (instance->irq == NO_IRQ)
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
|
||||
else
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
|
||||
|
|
@ -391,8 +361,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
|
|||
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
|
||||
rtrc(0);
|
||||
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
|
||||
if (i > dtc_maxi)
|
||||
dtc_maxi = i;
|
||||
if (i > hostdata->spin_max_r)
|
||||
hostdata->spin_max_r = i;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -412,13 +382,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
|
|||
static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
|
||||
{
|
||||
int i;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
|
||||
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
|
||||
/* set direction (write) */
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
if (instance->irq == NO_IRQ)
|
||||
NCR5380_write(DTC_CONTROL_REG, 0);
|
||||
else
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
|
||||
|
|
@ -444,8 +415,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
|
|||
/* Check for parity error here. fixme. */
|
||||
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
|
||||
rtrc(0);
|
||||
if (i > dtc_wmaxi)
|
||||
dtc_wmaxi = i;
|
||||
if (i > hostdata->spin_max_w)
|
||||
hostdata->spin_max_w = i;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -457,7 +428,7 @@ static int dtc_release(struct Scsi_Host *shost)
|
|||
{
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(shost);
|
||||
if (shost->irq)
|
||||
if (shost->irq != NO_IRQ)
|
||||
free_irq(shost->irq, shost);
|
||||
NCR5380_exit(shost);
|
||||
if (shost->io_port && shost->n_io_port)
|
||||
|
|
@ -471,6 +442,10 @@ static struct scsi_host_template driver_template = {
|
|||
.name = "DTC 3180/3280 ",
|
||||
.detect = dtc_detect,
|
||||
.release = dtc_release,
|
||||
.proc_name = "dtc3x80",
|
||||
.show_info = dtc_show_info,
|
||||
.write_info = dtc_write_info,
|
||||
.info = dtc_info,
|
||||
.queuecommand = dtc_queue_command,
|
||||
.eh_abort_handler = dtc_abort,
|
||||
.eh_bus_reset_handler = dtc_bus_reset,
|
||||
|
|
|
|||
|
|
@ -5,24 +5,6 @@
|
|||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 440-4894
|
||||
*
|
||||
* DISTRIBUTION RELEASE 2.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
*
|
||||
*
|
||||
* and
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
#ifndef DTC3280_H
|
||||
|
|
@ -32,13 +14,6 @@
|
|||
#define DTCDEBUG_INIT 0x1
|
||||
#define DTCDEBUG_TRANSFER 0x2
|
||||
|
||||
static int dtc_abort(Scsi_Cmnd *);
|
||||
static int dtc_biosparam(struct scsi_device *, struct block_device *,
|
||||
sector_t, int*);
|
||||
static int dtc_detect(struct scsi_host_template *);
|
||||
static int dtc_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int dtc_bus_reset(Scsi_Cmnd *);
|
||||
|
||||
#ifndef CMD_PER_LUN
|
||||
#define CMD_PER_LUN 2
|
||||
#endif
|
||||
|
|
@ -88,6 +63,7 @@ static int dtc_bus_reset(Scsi_Cmnd *);
|
|||
#define NCR5380_queue_command dtc_queue_command
|
||||
#define NCR5380_abort dtc_abort
|
||||
#define NCR5380_bus_reset dtc_bus_reset
|
||||
#define NCR5380_info dtc_info
|
||||
#define NCR5380_show_info dtc_show_info
|
||||
#define NCR5380_write_info dtc_write_info
|
||||
|
||||
|
|
|
|||
|
|
@ -952,12 +952,12 @@ static int eata2x_slave_configure(struct scsi_device *dev)
|
|||
} else {
|
||||
tag_suffix = ", no tags";
|
||||
}
|
||||
scsi_adjust_queue_depth(dev, tqd);
|
||||
scsi_change_queue_depth(dev, tqd);
|
||||
} else if (TLDEV(dev->type) && linked_comm) {
|
||||
scsi_adjust_queue_depth(dev, tqd);
|
||||
scsi_change_queue_depth(dev, tqd);
|
||||
tag_suffix = ", untagged";
|
||||
} else {
|
||||
scsi_adjust_queue_depth(dev, utqd);
|
||||
scsi_change_queue_depth(dev, utqd);
|
||||
tag_suffix = "";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -972,7 +972,6 @@ u8 handle_hba_ioctl(struct esas2r_adapter *a,
|
|||
struct atto_ioctl *ioctl_hba);
|
||||
int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd);
|
||||
int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh);
|
||||
int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason);
|
||||
long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* SCSI error handler (eh) functions */
|
||||
|
|
|
|||
|
|
@ -117,9 +117,8 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
|
|||
|
||||
rq = esas2r_alloc_request(a);
|
||||
if (rq == NULL) {
|
||||
up(&a->fm_api_semaphore);
|
||||
fi->status = FI_STAT_BUSY;
|
||||
return;
|
||||
goto free_sem;
|
||||
}
|
||||
|
||||
if (fi == &a->firmware.header) {
|
||||
|
|
@ -135,7 +134,7 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
|
|||
if (a->firmware.header_buff == NULL) {
|
||||
esas2r_debug("failed to allocate header buffer!");
|
||||
fi->status = FI_STAT_BUSY;
|
||||
return;
|
||||
goto free_req;
|
||||
}
|
||||
|
||||
memcpy(a->firmware.header_buff, fi,
|
||||
|
|
@ -171,9 +170,10 @@ all_done:
|
|||
a->firmware.header_buff,
|
||||
(dma_addr_t)a->firmware.header_buff_phys);
|
||||
}
|
||||
|
||||
up(&a->fm_api_semaphore);
|
||||
free_req:
|
||||
esas2r_free_request(a, (struct esas2r_request *)rq);
|
||||
free_sem:
|
||||
up(&a->fm_api_semaphore);
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
@ -1420,9 +1420,10 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg)
|
|||
|
||||
rq = esas2r_alloc_request(a);
|
||||
if (rq == NULL) {
|
||||
up(&a->nvram_semaphore);
|
||||
ioctl->data.prw.code = 0;
|
||||
break;
|
||||
kfree(ioctl);
|
||||
esas2r_log(ESAS2R_LOG_WARN,
|
||||
"could not allocate an internal request");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
code = esas2r_write_params(a, rq,
|
||||
|
|
@ -1523,9 +1524,12 @@ ioctl_done:
|
|||
case -EINVAL:
|
||||
ioctl->header.return_code = IOCTL_INVALID_PARAM;
|
||||
break;
|
||||
|
||||
default:
|
||||
ioctl->header.return_code = IOCTL_GENERAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ioctl->header.return_code = IOCTL_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* Always copy the buffer back, if only to pick up the status */
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static struct scsi_host_template driver_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.emulated = 0,
|
||||
.proc_name = ESAS2R_DRVR_NAME,
|
||||
.change_queue_depth = esas2r_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.max_sectors = 0xFFFF,
|
||||
.use_blk_tags = 1,
|
||||
|
|
@ -1257,15 +1257,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd)
|
|||
return esas2r_dev_targ_reset(cmd, true);
|
||||
}
|
||||
|
||||
int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason)
|
||||
{
|
||||
esas2r_log(ESAS2R_LOG_INFO, "change_queue_depth %p, %d", dev, depth);
|
||||
|
||||
scsi_adjust_queue_depth(dev, depth);
|
||||
|
||||
return dev->queue_depth;
|
||||
}
|
||||
|
||||
void esas2r_log_request_failure(struct esas2r_adapter *a,
|
||||
struct esas2r_request *rq)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,55 +49,67 @@ static u32 esp_debug;
|
|||
#define ESP_DEBUG_DATADONE 0x00000100
|
||||
#define ESP_DEBUG_RECONNECT 0x00000200
|
||||
#define ESP_DEBUG_AUTOSENSE 0x00000400
|
||||
#define ESP_DEBUG_EVENT 0x00000800
|
||||
#define ESP_DEBUG_COMMAND 0x00001000
|
||||
|
||||
#define esp_log_intr(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_INTR) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_reset(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_RESET) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_msgin(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_MSGIN) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_msgout(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_MSGOUT) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_cmddone(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_CMDDONE) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_disconnect(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_DISCONNECT) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_datastart(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_DATASTART) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_datadone(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_DATADONE) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_reconnect(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_RECONNECT) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_autosense(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \
|
||||
printk(f, ## a); \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_event(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_EVENT) \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_log_command(f, a...) \
|
||||
do { if (esp_debug & ESP_DEBUG_COMMAND) \
|
||||
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
|
||||
} while (0)
|
||||
|
||||
#define esp_read8(REG) esp->ops->esp_read8(esp, REG)
|
||||
|
|
@ -126,10 +138,29 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
|
|||
|
||||
esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
|
||||
|
||||
esp_log_command("cmd[%02x]\n", val);
|
||||
esp_write8(val, ESP_CMD);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_esp_cmd);
|
||||
|
||||
static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
|
||||
{
|
||||
if (esp->flags & ESP_FLAG_USE_FIFO) {
|
||||
int i;
|
||||
|
||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||
for (i = 0; i < len; i++)
|
||||
esp_write8(esp->command_block[i], ESP_FDATA);
|
||||
scsi_esp_cmd(esp, cmd);
|
||||
} else {
|
||||
if (esp->rev == FASHME)
|
||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||
cmd |= ESP_CMD_DMA;
|
||||
esp->ops->send_dma_cmd(esp, esp->command_block_dma,
|
||||
len, max_len, 0, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_event(struct esp *esp, u8 val)
|
||||
{
|
||||
struct esp_event_ent *p;
|
||||
|
|
@ -150,19 +181,17 @@ static void esp_dump_cmd_log(struct esp *esp)
|
|||
int idx = esp->esp_event_cur;
|
||||
int stop = idx;
|
||||
|
||||
printk(KERN_INFO PFX "esp%d: Dumping command log\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_INFO, esp->host, "Dumping command log\n");
|
||||
do {
|
||||
struct esp_event_ent *p = &esp->esp_event_log[idx];
|
||||
|
||||
printk(KERN_INFO PFX "esp%d: ent[%d] %s ",
|
||||
esp->host->unique_id, idx,
|
||||
p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT");
|
||||
|
||||
printk("val[%02x] sreg[%02x] seqreg[%02x] "
|
||||
"sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
|
||||
p->val, p->sreg, p->seqreg,
|
||||
p->sreg2, p->ireg, p->select_state, p->event);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] "
|
||||
"sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
|
||||
idx,
|
||||
p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT",
|
||||
p->val, p->sreg, p->seqreg,
|
||||
p->sreg2, p->ireg, p->select_state, p->event);
|
||||
|
||||
idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
|
||||
} while (idx != stop);
|
||||
|
|
@ -176,9 +205,8 @@ static void esp_flush_fifo(struct esp *esp)
|
|||
|
||||
while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) {
|
||||
if (--lim == 0) {
|
||||
printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES "
|
||||
"will not clear!\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ALERT, esp->host,
|
||||
"ESP_FF_BYTES will not clear!\n");
|
||||
break;
|
||||
}
|
||||
udelay(1);
|
||||
|
|
@ -240,6 +268,19 @@ static void esp_reset_esp(struct esp *esp)
|
|||
} else {
|
||||
esp->min_period = ((5 * esp->ccycle) / 1000);
|
||||
}
|
||||
if (esp->rev == FAS236) {
|
||||
/*
|
||||
* The AM53c974 chip returns the same ID as FAS236;
|
||||
* try to configure glitch eater.
|
||||
*/
|
||||
u8 config4 = ESP_CONFIG4_GE1;
|
||||
esp_write8(config4, ESP_CFG4);
|
||||
config4 = esp_read8(ESP_CFG4);
|
||||
if (config4 & ESP_CONFIG4_GE1) {
|
||||
esp->rev = PCSCSI;
|
||||
esp_write8(esp->config4, ESP_CFG4);
|
||||
}
|
||||
}
|
||||
esp->max_period = (esp->max_period + 3)>>2;
|
||||
esp->min_period = (esp->min_period + 3)>>2;
|
||||
|
||||
|
|
@ -265,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)
|
|||
/* fallthrough... */
|
||||
|
||||
case FAS236:
|
||||
/* Fast 236 or HME */
|
||||
case PCSCSI:
|
||||
/* Fast 236, AM53c974 or HME */
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
if (esp->rev == FASHME) {
|
||||
u8 cfg3 = esp->target[0].esp_config3;
|
||||
|
|
@ -383,12 +425,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
|
|||
p->cur_residue -= len;
|
||||
p->tot_residue -= len;
|
||||
if (p->cur_residue < 0 || p->tot_residue < 0) {
|
||||
printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
|
||||
esp->host->unique_id);
|
||||
printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
|
||||
"len[%u]\n",
|
||||
esp->host->unique_id,
|
||||
p->cur_residue, p->tot_residue, len);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Data transfer overflow.\n");
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"cur_residue[%d] tot_residue[%d] len[%u]\n",
|
||||
p->cur_residue, p->tot_residue, len);
|
||||
p->cur_residue = 0;
|
||||
p->tot_residue = 0;
|
||||
}
|
||||
|
|
@ -604,9 +645,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
|
|||
|
||||
|
||||
if (!ent->sense_ptr) {
|
||||
esp_log_autosense("esp%d: Doing auto-sense for "
|
||||
"tgt[%d] lun[%d]\n",
|
||||
esp->host->unique_id, tgt, lun);
|
||||
esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n",
|
||||
tgt, lun);
|
||||
|
||||
ent->sense_ptr = cmd->sense_buffer;
|
||||
ent->sense_dma = esp->ops->map_single(esp,
|
||||
|
|
@ -642,10 +682,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
|
|||
|
||||
val = (p - esp->command_block);
|
||||
|
||||
if (esp->rev == FASHME)
|
||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||
esp->ops->send_dma_cmd(esp, esp->command_block_dma,
|
||||
val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
|
||||
esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
|
||||
}
|
||||
|
||||
static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
|
||||
|
|
@ -781,12 +818,12 @@ build_identify:
|
|||
}
|
||||
|
||||
if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
|
||||
start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
|
||||
start_cmd = ESP_CMD_SELA;
|
||||
if (ent->tag[0]) {
|
||||
*p++ = ent->tag[0];
|
||||
*p++ = ent->tag[1];
|
||||
|
||||
start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
|
||||
start_cmd = ESP_CMD_SA3;
|
||||
}
|
||||
|
||||
for (i = 0; i < cmd->cmd_len; i++)
|
||||
|
|
@ -806,7 +843,7 @@ build_identify:
|
|||
esp->msg_out_len += 2;
|
||||
}
|
||||
|
||||
start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
|
||||
start_cmd = ESP_CMD_SELAS;
|
||||
esp->select_state = ESP_SELECT_MSGOUT;
|
||||
}
|
||||
val = tgt;
|
||||
|
|
@ -826,10 +863,7 @@ build_identify:
|
|||
printk("]\n");
|
||||
}
|
||||
|
||||
if (esp->rev == FASHME)
|
||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||
esp->ops->send_dma_cmd(esp, esp->command_block_dma,
|
||||
val, 16, 0, start_cmd);
|
||||
esp_send_dma_cmd(esp, val, 16, start_cmd);
|
||||
}
|
||||
|
||||
static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
|
||||
|
|
@ -953,8 +987,8 @@ static int esp_check_gross_error(struct esp *esp)
|
|||
* - DMA programmed with wrong direction
|
||||
* - improper phase change
|
||||
*/
|
||||
printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n",
|
||||
esp->host->unique_id, esp->sreg);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Gross error sreg[%02x]\n", esp->sreg);
|
||||
/* XXX Reset the chip. XXX */
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -974,7 +1008,6 @@ static int esp_check_spur_intr(struct esp *esp)
|
|||
|
||||
default:
|
||||
if (!(esp->sreg & ESP_STAT_INTR)) {
|
||||
esp->ireg = esp_read8(ESP_INTRPT);
|
||||
if (esp->ireg & ESP_INTR_SR)
|
||||
return 1;
|
||||
|
||||
|
|
@ -982,14 +1015,13 @@ static int esp_check_spur_intr(struct esp *esp)
|
|||
* ESP is not, the only possibility is a DMA error.
|
||||
*/
|
||||
if (!esp->ops->dma_error(esp)) {
|
||||
printk(KERN_ERR PFX "esp%d: Spurious irq, "
|
||||
"sreg=%02x.\n",
|
||||
esp->host->unique_id, esp->sreg);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Spurious irq, sreg=%02x.\n",
|
||||
esp->sreg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk(KERN_ERR PFX "esp%d: DMA error\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ERR, esp->host, "DMA error\n");
|
||||
|
||||
/* XXX Reset the chip. XXX */
|
||||
return -1;
|
||||
|
|
@ -1002,7 +1034,7 @@ static int esp_check_spur_intr(struct esp *esp)
|
|||
|
||||
static void esp_schedule_reset(struct esp *esp)
|
||||
{
|
||||
esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
|
||||
esp_log_reset("esp_schedule_reset() from %pf\n",
|
||||
__builtin_return_address(0));
|
||||
esp->flags |= ESP_FLAG_RESETTING;
|
||||
esp_event(esp, ESP_EVENT_RESET);
|
||||
|
|
@ -1019,20 +1051,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
|
|||
int i;
|
||||
|
||||
if (!lp->num_tagged) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect w/num_tagged==0\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_log_reconnect("ESP: reconnect tag, ");
|
||||
esp_log_reconnect("reconnect tag, ");
|
||||
|
||||
for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) {
|
||||
if (esp->ops->irq_pending(esp))
|
||||
break;
|
||||
}
|
||||
if (i == ESP_QUICKIRQ_LIMIT) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect IRQ1 timeout\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1043,14 +1075,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
|
|||
i, esp->ireg, esp->sreg);
|
||||
|
||||
if (esp->ireg & ESP_INTR_DC) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect, got disconnect.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n",
|
||||
esp->host->unique_id, esp->sreg);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect, not MIP sreg[%02x].\n", esp->sreg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1073,8 +1105,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
|
|||
udelay(1);
|
||||
}
|
||||
if (i == ESP_RESELECT_TAG_LIMIT) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n",
|
||||
esp->host->unique_id);
|
||||
shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n");
|
||||
return NULL;
|
||||
}
|
||||
esp->ops->dma_drain(esp);
|
||||
|
|
@ -1087,17 +1118,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
|
|||
|
||||
if (esp->command_block[0] < SIMPLE_QUEUE_TAG ||
|
||||
esp->command_block[0] > ORDERED_QUEUE_TAG) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect, bad tag "
|
||||
"type %02x.\n",
|
||||
esp->host->unique_id, esp->command_block[0]);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect, bad tag type %02x.\n",
|
||||
esp->command_block[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ent = lp->tagged_cmds[esp->command_block[1]];
|
||||
if (!ent) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect, no entry for "
|
||||
"tag %02x.\n",
|
||||
esp->host->unique_id, esp->command_block[1]);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect, no entry for tag %02x.\n",
|
||||
esp->command_block[1]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1163,9 +1194,9 @@ static int esp_reconnect(struct esp *esp)
|
|||
tp = &esp->target[target];
|
||||
dev = __scsi_device_lookup_by_target(tp->starget, lun);
|
||||
if (!dev) {
|
||||
printk(KERN_ERR PFX "esp%d: Reconnect, no lp "
|
||||
"tgt[%u] lun[%u]\n",
|
||||
esp->host->unique_id, target, lun);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Reconnect, no lp tgt[%u] lun[%u]\n",
|
||||
target, lun);
|
||||
goto do_reset;
|
||||
}
|
||||
lp = dev->hostdata;
|
||||
|
|
@ -1291,8 +1322,8 @@ static int esp_finish_select(struct esp *esp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
printk("ESP: Unexpected selection completion ireg[%x].\n",
|
||||
esp->ireg);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected selection completion ireg[%x]\n", esp->ireg);
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1312,11 +1343,42 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
|
|||
(((unsigned int)esp_read8(ESP_TCMED)) << 8));
|
||||
if (esp->rev == FASHME)
|
||||
ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
|
||||
if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
|
||||
ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
|
||||
}
|
||||
|
||||
bytes_sent = esp->data_dma_len;
|
||||
bytes_sent -= ecount;
|
||||
|
||||
/*
|
||||
* The am53c974 has a DMA 'pecularity'. The doc states:
|
||||
* In some odd byte conditions, one residual byte will
|
||||
* be left in the SCSI FIFO, and the FIFO Flags will
|
||||
* never count to '0 '. When this happens, the residual
|
||||
* byte should be retrieved via PIO following completion
|
||||
* of the BLAST operation.
|
||||
*/
|
||||
if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
|
||||
size_t count = 1;
|
||||
size_t offset = bytes_sent;
|
||||
u8 bval = esp_read8(ESP_FDATA);
|
||||
|
||||
if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
|
||||
ent->sense_ptr[bytes_sent] = bval;
|
||||
else {
|
||||
struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
|
||||
u8 *ptr;
|
||||
|
||||
ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
|
||||
&offset, &count);
|
||||
if (likely(ptr)) {
|
||||
*(ptr + offset) = bval;
|
||||
scsi_kunmap_atomic_sg(ptr);
|
||||
}
|
||||
}
|
||||
bytes_sent += fifo_cnt;
|
||||
ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
|
||||
}
|
||||
if (!(ent->flags & ESP_CMD_FLAG_WRITE))
|
||||
bytes_sent -= fifo_cnt;
|
||||
|
||||
|
|
@ -1556,8 +1618,8 @@ static void esp_msgin_extended(struct esp *esp)
|
|||
return;
|
||||
}
|
||||
|
||||
printk("ESP: Unexpected extended msg type %x\n",
|
||||
esp->msg_in[2]);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected extended msg type %x\n", esp->msg_in[2]);
|
||||
|
||||
esp->msg_out[0] = ABORT_TASK_SET;
|
||||
esp->msg_out_len = 1;
|
||||
|
|
@ -1574,7 +1636,8 @@ static int esp_msgin_process(struct esp *esp)
|
|||
|
||||
if (msg0 & 0x80) {
|
||||
/* Identify */
|
||||
printk("ESP: Unexpected msgin identify\n");
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected msgin identify\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1640,10 +1703,12 @@ static int esp_msgin_process(struct esp *esp)
|
|||
|
||||
static int esp_process_event(struct esp *esp)
|
||||
{
|
||||
int write;
|
||||
int write, i;
|
||||
|
||||
again:
|
||||
write = 0;
|
||||
esp_log_event("process event %d phase %x\n",
|
||||
esp->event, esp->sreg & ESP_STAT_PMASK);
|
||||
switch (esp->event) {
|
||||
case ESP_EVENT_CHECK_PHASE:
|
||||
switch (esp->sreg & ESP_STAT_PMASK) {
|
||||
|
|
@ -1673,8 +1738,9 @@ again:
|
|||
break;
|
||||
|
||||
default:
|
||||
printk("ESP: Unexpected phase, sreg=%02x\n",
|
||||
esp->sreg);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected phase, sreg=%02x\n",
|
||||
esp->sreg);
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1708,18 +1774,17 @@ again:
|
|||
esp->data_dma_len = dma_len;
|
||||
|
||||
if (!dma_len) {
|
||||
printk(KERN_ERR PFX "esp%d: DMA length is zero!\n",
|
||||
esp->host->unique_id);
|
||||
printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n",
|
||||
esp->host->unique_id,
|
||||
(unsigned long long)esp_cur_dma_addr(ent, cmd),
|
||||
esp_cur_dma_len(ent, cmd));
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"DMA length is zero!\n");
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"cur adr[%08llx] len[%08x]\n",
|
||||
(unsigned long long)esp_cur_dma_addr(ent, cmd),
|
||||
esp_cur_dma_len(ent, cmd));
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_log_datastart("ESP: start data addr[%08llx] len[%u] "
|
||||
"write(%d)\n",
|
||||
esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n",
|
||||
(unsigned long long)dma_addr, dma_len, write);
|
||||
|
||||
esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
|
||||
|
|
@ -1733,7 +1798,8 @@ again:
|
|||
int bytes_sent;
|
||||
|
||||
if (esp->ops->dma_error(esp)) {
|
||||
printk("ESP: data done, DMA error, resetting\n");
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"data done, DMA error, resetting\n");
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1749,14 +1815,15 @@ again:
|
|||
/* We should always see exactly a bus-service
|
||||
* interrupt at the end of a successful transfer.
|
||||
*/
|
||||
printk("ESP: data done, not BSERV, resetting\n");
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"data done, not BSERV, resetting\n");
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes_sent = esp_data_bytes_sent(esp, ent, cmd);
|
||||
|
||||
esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n",
|
||||
esp_log_datadone("data done flgs[%x] sent[%d]\n",
|
||||
ent->flags, bytes_sent);
|
||||
|
||||
if (bytes_sent < 0) {
|
||||
|
|
@ -1785,8 +1852,9 @@ again:
|
|||
}
|
||||
|
||||
if (ent->message != COMMAND_COMPLETE) {
|
||||
printk("ESP: Unexpected message %x in status\n",
|
||||
ent->message);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected message %x in status\n",
|
||||
ent->message);
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1804,8 +1872,7 @@ again:
|
|||
scsi_esp_cmd(esp, ESP_CMD_ESEL);
|
||||
|
||||
if (ent->message == COMMAND_COMPLETE) {
|
||||
esp_log_cmddone("ESP: Command done status[%x] "
|
||||
"message[%x]\n",
|
||||
esp_log_cmddone("Command done status[%x] message[%x]\n",
|
||||
ent->status, ent->message);
|
||||
if (ent->status == SAM_STAT_TASK_SET_FULL)
|
||||
esp_event_queue_full(esp, ent);
|
||||
|
|
@ -1821,16 +1888,16 @@ again:
|
|||
DID_OK));
|
||||
}
|
||||
} else if (ent->message == DISCONNECT) {
|
||||
esp_log_disconnect("ESP: Disconnecting tgt[%d] "
|
||||
"tag[%x:%x]\n",
|
||||
esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n",
|
||||
cmd->device->id,
|
||||
ent->tag[0], ent->tag[1]);
|
||||
|
||||
esp->active_cmd = NULL;
|
||||
esp_maybe_execute_command(esp);
|
||||
} else {
|
||||
printk("ESP: Unexpected message %x in freebus\n",
|
||||
ent->message);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected message %x in freebus\n",
|
||||
ent->message);
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1862,6 +1929,10 @@ again:
|
|||
if (esp->msg_out_len == 1) {
|
||||
esp_write8(esp->msg_out[0], ESP_FDATA);
|
||||
scsi_esp_cmd(esp, ESP_CMD_TI);
|
||||
} else if (esp->flags & ESP_FLAG_USE_FIFO) {
|
||||
for (i = 0; i < esp->msg_out_len; i++)
|
||||
esp_write8(esp->msg_out[i], ESP_FDATA);
|
||||
scsi_esp_cmd(esp, ESP_CMD_TI);
|
||||
} else {
|
||||
/* Use DMA. */
|
||||
memcpy(esp->command_block,
|
||||
|
|
@ -1917,7 +1988,7 @@ again:
|
|||
val = esp_read8(ESP_FDATA);
|
||||
esp->msg_in[esp->msg_in_len++] = val;
|
||||
|
||||
esp_log_msgin("ESP: Got msgin byte %x\n", val);
|
||||
esp_log_msgin("Got msgin byte %x\n", val);
|
||||
|
||||
if (!esp_msgin_process(esp))
|
||||
esp->msg_in_len = 0;
|
||||
|
|
@ -1930,7 +2001,8 @@ again:
|
|||
if (esp->event != ESP_EVENT_FREE_BUS)
|
||||
esp_event(esp, ESP_EVENT_CHECK_PHASE);
|
||||
} else {
|
||||
printk("ESP: MSGIN neither BSERV not FDON, resetting");
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"MSGIN neither BSERV not FDON, resetting");
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1938,11 +2010,7 @@ again:
|
|||
case ESP_EVENT_CMD_START:
|
||||
memcpy(esp->command_block, esp->cmd_bytes_ptr,
|
||||
esp->cmd_bytes_left);
|
||||
if (esp->rev == FASHME)
|
||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||
esp->ops->send_dma_cmd(esp, esp->command_block_dma,
|
||||
esp->cmd_bytes_left, 16, 0,
|
||||
ESP_CMD_DMA | ESP_CMD_TI);
|
||||
esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
|
||||
esp_event(esp, ESP_EVENT_CMD_DONE);
|
||||
esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
|
||||
break;
|
||||
|
|
@ -1961,8 +2029,8 @@ again:
|
|||
break;
|
||||
|
||||
default:
|
||||
printk("ESP: Unexpected event %x, resetting\n",
|
||||
esp->event);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"Unexpected event %x, resetting\n", esp->event);
|
||||
esp_schedule_reset(esp);
|
||||
return 0;
|
||||
break;
|
||||
|
|
@ -2044,7 +2112,12 @@ static void __esp_interrupt(struct esp *esp)
|
|||
int finish_reset, intr_done;
|
||||
u8 phase;
|
||||
|
||||
/*
|
||||
* Once INTRPT is read STATUS and SSTEP are cleared.
|
||||
*/
|
||||
esp->sreg = esp_read8(ESP_STATUS);
|
||||
esp->seqreg = esp_read8(ESP_SSTEP);
|
||||
esp->ireg = esp_read8(ESP_INTRPT);
|
||||
|
||||
if (esp->flags & ESP_FLAG_RESETTING) {
|
||||
finish_reset = 1;
|
||||
|
|
@ -2057,8 +2130,6 @@ static void __esp_interrupt(struct esp *esp)
|
|||
return;
|
||||
}
|
||||
|
||||
esp->ireg = esp_read8(ESP_INTRPT);
|
||||
|
||||
if (esp->ireg & ESP_INTR_SR)
|
||||
finish_reset = 1;
|
||||
|
||||
|
|
@ -2085,14 +2156,15 @@ static void __esp_interrupt(struct esp *esp)
|
|||
}
|
||||
}
|
||||
|
||||
esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] "
|
||||
esp_log_intr("intr sreg[%02x] seqreg[%02x] "
|
||||
"sreg2[%02x] ireg[%02x]\n",
|
||||
esp->sreg, esp->seqreg, esp->sreg2, esp->ireg);
|
||||
|
||||
intr_done = 0;
|
||||
|
||||
if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) {
|
||||
printk("ESP: unexpected IREG %02x\n", esp->ireg);
|
||||
shost_printk(KERN_INFO, esp->host,
|
||||
"unexpected IREG %02x\n", esp->ireg);
|
||||
if (esp->ireg & ESP_INTR_IC)
|
||||
esp_dump_cmd_log(esp);
|
||||
|
||||
|
|
@ -2149,46 +2221,50 @@ static void esp_get_revision(struct esp *esp)
|
|||
u8 val;
|
||||
|
||||
esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
|
||||
esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
|
||||
val = esp_read8(ESP_CFG2);
|
||||
val &= ~ESP_CONFIG2_MAGIC;
|
||||
if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
|
||||
/* If what we write to cfg2 does not come back, cfg2 is not
|
||||
* implemented, therefore this must be a plain esp100.
|
||||
*/
|
||||
esp->rev = ESP100;
|
||||
} else {
|
||||
esp->config2 = 0;
|
||||
esp_set_all_config3(esp, 5);
|
||||
esp->prev_cfg3 = 5;
|
||||
if (esp->config2 == 0) {
|
||||
esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
esp_write8(0, ESP_CFG3);
|
||||
|
||||
val = esp_read8(ESP_CFG2);
|
||||
val &= ~ESP_CONFIG2_MAGIC;
|
||||
|
||||
esp->config2 = 0;
|
||||
if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
|
||||
/*
|
||||
* If what we write to cfg2 does not come back,
|
||||
* cfg2 is not implemented.
|
||||
* Therefore this must be a plain esp100.
|
||||
*/
|
||||
esp->rev = ESP100;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
esp_set_all_config3(esp, 5);
|
||||
esp->prev_cfg3 = 5;
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
esp_write8(0, ESP_CFG3);
|
||||
esp_write8(esp->prev_cfg3, ESP_CFG3);
|
||||
|
||||
val = esp_read8(ESP_CFG3);
|
||||
if (val != 5) {
|
||||
/* The cfg2 register is implemented, however
|
||||
* cfg3 is not, must be esp100a.
|
||||
*/
|
||||
esp->rev = ESP100A;
|
||||
} else {
|
||||
esp_set_all_config3(esp, 0);
|
||||
esp->prev_cfg3 = 0;
|
||||
esp_write8(esp->prev_cfg3, ESP_CFG3);
|
||||
|
||||
val = esp_read8(ESP_CFG3);
|
||||
if (val != 5) {
|
||||
/* The cfg2 register is implemented, however
|
||||
* cfg3 is not, must be esp100a.
|
||||
*/
|
||||
esp->rev = ESP100A;
|
||||
/* All of cfg{1,2,3} implemented, must be one of
|
||||
* the fas variants, figure out which one.
|
||||
*/
|
||||
if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
|
||||
esp->rev = FAST;
|
||||
esp->sync_defp = SYNC_DEFP_FAST;
|
||||
} else {
|
||||
esp_set_all_config3(esp, 0);
|
||||
esp->prev_cfg3 = 0;
|
||||
esp_write8(esp->prev_cfg3, ESP_CFG3);
|
||||
|
||||
/* All of cfg{1,2,3} implemented, must be one of
|
||||
* the fas variants, figure out which one.
|
||||
*/
|
||||
if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
|
||||
esp->rev = FAST;
|
||||
esp->sync_defp = SYNC_DEFP_FAST;
|
||||
} else {
|
||||
esp->rev = ESP236;
|
||||
}
|
||||
esp->config2 = 0;
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
esp->rev = ESP236;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2308,6 +2384,7 @@ static const char *esp_chip_names[] = {
|
|||
"FAS100A",
|
||||
"FAST",
|
||||
"FASHME",
|
||||
"AM53C974",
|
||||
};
|
||||
|
||||
static struct scsi_transport_template *esp_transport_template;
|
||||
|
|
@ -2317,6 +2394,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
|
|||
static int instance;
|
||||
int err;
|
||||
|
||||
if (!esp->num_tags)
|
||||
esp->num_tags = ESP_DEFAULT_TAGS;
|
||||
else if (esp->num_tags >= ESP_MAX_TAG)
|
||||
esp->num_tags = ESP_MAX_TAG - 1;
|
||||
esp->host->transportt = esp_transport_template;
|
||||
esp->host->max_lun = ESP_MAX_LUN;
|
||||
esp->host->cmd_per_lun = 2;
|
||||
|
|
@ -2330,12 +2411,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
|
|||
|
||||
esp_bootup_reset(esp);
|
||||
|
||||
printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n",
|
||||
esp->host->unique_id, esp->regs, esp->dma_regs,
|
||||
esp->host->irq);
|
||||
printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
|
||||
esp->host->unique_id, esp_chip_names[esp->rev],
|
||||
esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
|
||||
dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n",
|
||||
esp->host->unique_id, esp->regs, esp->dma_regs,
|
||||
esp->host->irq);
|
||||
dev_printk(KERN_INFO, dev,
|
||||
"esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
|
||||
esp->host->unique_id, esp_chip_names[esp->rev],
|
||||
esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
|
||||
|
||||
/* Let the SCSI bus reset settle. */
|
||||
ssleep(esp_bus_reset_settle);
|
||||
|
|
@ -2403,12 +2485,8 @@ static int esp_slave_configure(struct scsi_device *dev)
|
|||
struct esp *esp = shost_priv(dev->host);
|
||||
struct esp_target_data *tp = &esp->target[dev->id];
|
||||
|
||||
if (dev->tagged_supported) {
|
||||
/* XXX make this configurable somehow XXX */
|
||||
int goal_tags = min(ESP_DEFAULT_TAGS, ESP_MAX_TAG);
|
||||
|
||||
scsi_adjust_queue_depth(dev, goal_tags);
|
||||
}
|
||||
if (dev->tagged_supported)
|
||||
scsi_change_queue_depth(dev, esp->num_tags);
|
||||
|
||||
tp->flags |= ESP_TGT_DISCONNECT;
|
||||
|
||||
|
|
@ -2437,19 +2515,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
* XXX much for the final driver.
|
||||
*/
|
||||
spin_lock_irqsave(esp->host->host_lock, flags);
|
||||
printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n",
|
||||
esp->host->unique_id, cmd, cmd->cmnd[0]);
|
||||
shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n",
|
||||
cmd, cmd->cmnd[0]);
|
||||
ent = esp->active_cmd;
|
||||
if (ent)
|
||||
printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n",
|
||||
esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
|
||||
shost_printk(KERN_ERR, esp->host,
|
||||
"Current command [%p:%02x]\n",
|
||||
ent->cmd, ent->cmd->cmnd[0]);
|
||||
list_for_each_entry(ent, &esp->queued_cmds, list) {
|
||||
printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n",
|
||||
esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
|
||||
shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n",
|
||||
ent->cmd, ent->cmd->cmnd[0]);
|
||||
}
|
||||
list_for_each_entry(ent, &esp->active_cmds, list) {
|
||||
printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n",
|
||||
esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
|
||||
shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n",
|
||||
ent->cmd, ent->cmd->cmnd[0]);
|
||||
}
|
||||
esp_dump_cmd_log(esp);
|
||||
spin_unlock_irqrestore(esp->host->host_lock, flags);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* esp_scsi.h: Defines and structures for the ESP drier.
|
||||
/* esp_scsi.h: Defines and structures for the ESP driver.
|
||||
*
|
||||
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
#define ESP_CTEST 0x0aUL /* wo Chip test register 0x28 */
|
||||
#define ESP_CFG2 0x0bUL /* rw Second cfg register 0x2c */
|
||||
#define ESP_CFG3 0x0cUL /* rw Third cfg register 0x30 */
|
||||
#define ESP_CFG4 0x0dUL /* rw Fourth cfg register 0x34 */
|
||||
#define ESP_TCHI 0x0eUL /* rw High bits transf count 0x38 */
|
||||
#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
|
||||
#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
|
||||
|
|
@ -76,6 +77,18 @@
|
|||
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
|
||||
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
|
||||
|
||||
/* ESP config register 4 read-write, found only on am53c974 chips */
|
||||
#define ESP_CONFIG4_RADE 0x04 /* Active negation */
|
||||
#define ESP_CONFIG4_RAE 0x08 /* Active negation on REQ and ACK */
|
||||
#define ESP_CONFIG4_PWD 0x20 /* Reduced power feature */
|
||||
#define ESP_CONFIG4_GE0 0x40 /* Glitch eater bit 0 */
|
||||
#define ESP_CONFIG4_GE1 0x80 /* Glitch eater bit 1 */
|
||||
|
||||
#define ESP_CONFIG_GE_12NS (0)
|
||||
#define ESP_CONFIG_GE_25NS (ESP_CONFIG_GE1)
|
||||
#define ESP_CONFIG_GE_35NS (ESP_CONFIG_GE0)
|
||||
#define ESP_CONFIG_GE_0NS (ESP_CONFIG_GE0 | ESP_CONFIG_GE1)
|
||||
|
||||
/* ESP command register read-write */
|
||||
/* Group 1 commands: These may be sent at any point in time to the ESP
|
||||
* chip. None of them can generate interrupts 'cept
|
||||
|
|
@ -254,6 +267,7 @@ enum esp_rev {
|
|||
FAS100A = 0x04,
|
||||
FAST = 0x05,
|
||||
FASHME = 0x06,
|
||||
PCSCSI = 0x07, /* AM53c974 */
|
||||
};
|
||||
|
||||
struct esp_cmd_entry {
|
||||
|
|
@ -269,6 +283,7 @@ struct esp_cmd_entry {
|
|||
#define ESP_CMD_FLAG_WRITE 0x01 /* DMA is a write */
|
||||
#define ESP_CMD_FLAG_ABORT 0x02 /* being aborted */
|
||||
#define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */
|
||||
#define ESP_CMD_FLAG_RESIDUAL 0x08 /* AM53c974 BLAST residual */
|
||||
|
||||
u8 tag[2];
|
||||
u8 orig_tag[2];
|
||||
|
|
@ -283,7 +298,6 @@ struct esp_cmd_entry {
|
|||
struct completion *eh_done;
|
||||
};
|
||||
|
||||
/* XXX make this configurable somehow XXX */
|
||||
#define ESP_DEFAULT_TAGS 16
|
||||
|
||||
#define ESP_MAX_TARGET 16
|
||||
|
|
@ -445,7 +459,7 @@ struct esp {
|
|||
u8 prev_soff;
|
||||
u8 prev_stp;
|
||||
u8 prev_cfg3;
|
||||
u8 __pad;
|
||||
u8 num_tags;
|
||||
|
||||
struct list_head esp_cmd_pool;
|
||||
|
||||
|
|
@ -466,6 +480,7 @@ struct esp {
|
|||
u8 bursts;
|
||||
u8 config1;
|
||||
u8 config2;
|
||||
u8 config4;
|
||||
|
||||
u8 scsi_id;
|
||||
u32 scsi_id_mask;
|
||||
|
|
@ -479,6 +494,7 @@ struct esp {
|
|||
#define ESP_FLAG_WIDE_CAPABLE 0x00000008
|
||||
#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
|
||||
#define ESP_FLAG_DISABLE_SYNC 0x00000020
|
||||
#define ESP_FLAG_USE_FIFO 0x00000040
|
||||
|
||||
u8 select_state;
|
||||
#define ESP_SELECT_NONE 0x00 /* Not selecting */
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ static struct scsi_host_template fcoe_shost_template = {
|
|||
.eh_device_reset_handler = fc_eh_device_reset,
|
||||
.eh_host_reset_handler = fc_eh_host_reset,
|
||||
.slave_alloc = fc_slave_alloc,
|
||||
.change_queue_depth = fc_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.this_id = -1,
|
||||
.cmd_per_lun = 3,
|
||||
|
|
@ -289,6 +289,7 @@ static struct scsi_host_template fcoe_shost_template = {
|
|||
.sg_tablesize = SG_ALL,
|
||||
.max_sectors = 0xffff,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#define DRV_NAME "fnic"
|
||||
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
||||
#define DRV_VERSION "1.6.0.11"
|
||||
#define DRV_VERSION "1.6.0.16"
|
||||
#define PFX DRV_NAME ": "
|
||||
#define DFX DRV_NAME "%d: "
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,11 @@ void fnic_handle_link(struct work_struct *work)
|
|||
fnic->lport->host->host_no, FNIC_FC_LE,
|
||||
"Link Status: UP_DOWN",
|
||||
strlen("Link Status: UP_DOWN"));
|
||||
if (fnic->config.flags & VFCF_FIP_CAPABLE) {
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"deleting fip-timer during link-down\n");
|
||||
del_timer_sync(&fnic->fip_timer);
|
||||
}
|
||||
fcoe_ctlr_link_down(&fnic->ctlr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev)
|
|||
if (!rport || fc_remote_port_chkready(rport))
|
||||
return -ENXIO;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, fnic_max_qdepth);
|
||||
scsi_change_queue_depth(sdev, fnic_max_qdepth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ static struct scsi_host_template fnic_host_template = {
|
|||
.eh_device_reset_handler = fnic_device_reset,
|
||||
.eh_host_reset_handler = fnic_host_reset,
|
||||
.slave_alloc = fnic_slave_alloc,
|
||||
.change_queue_depth = fc_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.this_id = -1,
|
||||
.cmd_per_lun = 3,
|
||||
|
|
@ -120,6 +120,7 @@ static struct scsi_host_template fnic_host_template = {
|
|||
.max_sectors = 0xffff,
|
||||
.shost_attrs = fnic_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -437,21 +438,30 @@ static int fnic_dev_wait(struct vnic_dev *vdev,
|
|||
unsigned long time;
|
||||
int done;
|
||||
int err;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
|
||||
err = start(vdev, arg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Wait for func to complete...2 seconds max */
|
||||
/* Wait for func to complete.
|
||||
* Sometime schedule_timeout_uninterruptible take long time
|
||||
* to wake up so we do not retry as we are only waiting for
|
||||
* 2 seconds in while loop. By adding count, we make sure
|
||||
* we try atleast three times before returning -ETIMEDOUT
|
||||
*/
|
||||
time = jiffies + (HZ * 2);
|
||||
do {
|
||||
err = finished(vdev, &done);
|
||||
count++;
|
||||
if (err)
|
||||
return err;
|
||||
if (done)
|
||||
return 0;
|
||||
schedule_timeout_uninterruptible(HZ / 10);
|
||||
} while (time_after(time, jiffies));
|
||||
} while (time_after(time, jiffies) || (count < 3));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -421,8 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
|
|||
int ret;
|
||||
u64 cmd_trace;
|
||||
int sg_count = 0;
|
||||
unsigned long flags;
|
||||
unsigned long flags = 0;
|
||||
unsigned long ptr;
|
||||
struct fc_rport_priv *rdata;
|
||||
spinlock_t *io_lock = NULL;
|
||||
|
||||
if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
|
@ -436,6 +438,16 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
|
|||
return 0;
|
||||
}
|
||||
|
||||
rdata = lp->tt.rport_lookup(lp, rport->port_id);
|
||||
if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) {
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"returning IO as rport is removed\n");
|
||||
atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
|
||||
sc->result = DID_NO_CONNECT;
|
||||
done(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lp->state != LPORT_ST_READY || !(lp->link_up))
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
|
|
@ -498,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Will acquire lock defore setting to IO initialized.
|
||||
*/
|
||||
|
||||
io_lock = fnic_io_lock_hash(fnic, sc);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
|
||||
/* initialize rest of io_req */
|
||||
io_req->port_id = rport->port_id;
|
||||
io_req->start_time = jiffies;
|
||||
|
|
@ -514,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
|
|||
* In case another thread cancelled the request,
|
||||
* refetch the pointer under the lock.
|
||||
*/
|
||||
spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
|
||||
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
|
||||
sc->request->tag, sc, 0, 0, 0,
|
||||
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
CMD_SP(sc) = NULL;
|
||||
CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
|
||||
|
|
@ -527,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
|
|||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||
mempool_free(io_req, fnic->io_req_pool);
|
||||
}
|
||||
atomic_dec(&fnic->in_flight);
|
||||
/* acquire host lock before returning to SCSI */
|
||||
spin_lock(lp->host->host_lock);
|
||||
return ret;
|
||||
} else {
|
||||
atomic64_inc(&fnic_stats->io_stats.active_ios);
|
||||
atomic64_inc(&fnic_stats->io_stats.num_ios);
|
||||
|
|
@ -548,6 +569,11 @@ out:
|
|||
sc->request->tag, sc, io_req,
|
||||
sg_count, cmd_trace,
|
||||
(((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
|
||||
|
||||
/* if only we issued IO, will we have the io lock */
|
||||
if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
atomic_dec(&fnic->in_flight);
|
||||
/* acquire host lock before returning to SCSI */
|
||||
spin_lock(lp->host->host_lock);
|
||||
|
|
|
|||
|
|
@ -624,12 +624,12 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
|
|||
if (frame_type == FNIC_FC_RECV) {
|
||||
eth_fcoe_hdr_len = sizeof(struct ethhdr) +
|
||||
sizeof(struct fcoe_hdr);
|
||||
fc_trc_frame_len = fc_trc_frame_len + eth_fcoe_hdr_len;
|
||||
memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
|
||||
/* Copy the rest of data frame */
|
||||
memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
|
||||
min_t(u8, fc_trc_frame_len,
|
||||
(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
|
||||
(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
|
||||
- eth_fcoe_hdr_len)));
|
||||
} else {
|
||||
memcpy((char *)fc_trace, (void *)frame,
|
||||
min_t(u8, fc_trc_frame_len,
|
||||
|
|
|
|||
|
|
@ -18,20 +18,6 @@
|
|||
*
|
||||
* Added ISAPNP support for DTC436 adapters,
|
||||
* Thomas Sailer, sailer@ife.ee.ethz.ch
|
||||
*
|
||||
* ALPHA RELEASE 1.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -40,14 +26,6 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Options :
|
||||
*
|
||||
* PARITY - enable parity checking. Not supported.
|
||||
*
|
||||
* SCSI2 - enable support for SCSI-II tagged queueing. Untested.
|
||||
*
|
||||
* USLEEP - enable support for devices that don't disconnect. Untested.
|
||||
*
|
||||
* The card is detected and initialized in one of several ways :
|
||||
* 1. With command line overrides - NCR5380=port,irq may be
|
||||
* used on the LILO command line to override the defaults.
|
||||
|
|
@ -79,27 +57,21 @@
|
|||
*/
|
||||
|
||||
/* settings for DTC3181E card with only Mustek scanner attached */
|
||||
#define USLEEP
|
||||
#define USLEEP_POLL 1
|
||||
#define USLEEP_SLEEP 20
|
||||
#define USLEEP_WAITLONG 500
|
||||
|
||||
#define AUTOPROBE_IRQ
|
||||
#define AUTOSENSE
|
||||
|
||||
|
||||
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
|
||||
#define NCR53C400_PSEUDO_DMA 1
|
||||
#define PSEUDO_DMA
|
||||
#define NCR53C400
|
||||
#define NCR5380_STATS
|
||||
#undef NCR5380_STAT_LIMIT
|
||||
#endif
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "g_NCR5380.h"
|
||||
#include "NCR5380.h"
|
||||
|
|
@ -277,7 +249,7 @@ static int __init do_DTC3181E_setup(char *str)
|
|||
* Locks: none
|
||||
*/
|
||||
|
||||
int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
|
||||
static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
static int current_override = 0;
|
||||
int count;
|
||||
|
|
@ -335,7 +307,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
|
|||
if (pnp_irq_valid(dev, 0))
|
||||
overrides[count].irq = pnp_irq(dev, 0);
|
||||
else
|
||||
overrides[count].irq = SCSI_IRQ_NONE;
|
||||
overrides[count].irq = NO_IRQ;
|
||||
if (pnp_dma_valid(dev, 0))
|
||||
overrides[count].dma = pnp_dma(dev, 0);
|
||||
else
|
||||
|
|
@ -455,46 +427,28 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
|
|||
else
|
||||
instance->irq = NCR5380_probe_irq(instance, 0xffff);
|
||||
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
/* Compatibility with documented NCR5380 kernel parameters */
|
||||
if (instance->irq == 255)
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
if (instance->irq != NO_IRQ)
|
||||
if (request_irq(instance->irq, generic_NCR5380_intr,
|
||||
0, "NCR5380", instance)) {
|
||||
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
|
||||
instance->irq = SCSI_IRQ_NONE;
|
||||
instance->irq = NO_IRQ;
|
||||
}
|
||||
|
||||
if (instance->irq == SCSI_IRQ_NONE) {
|
||||
if (instance->irq == NO_IRQ) {
|
||||
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
|
||||
printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int) instance->NCR5380_instance_name);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
printk(" interrupts disabled");
|
||||
else
|
||||
printk(" irq %d", instance->irq);
|
||||
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
|
||||
NCR5380_print_options(instance);
|
||||
printk("\n");
|
||||
|
||||
++current_override;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* generic_NCR5380_info - reporting string
|
||||
* @host: NCR5380 to report on
|
||||
*
|
||||
* Report driver information for the NCR5380
|
||||
*/
|
||||
|
||||
const char *generic_NCR5380_info(struct Scsi_Host *host)
|
||||
{
|
||||
static const char string[] = "Generic NCR5380/53C400 Driver";
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* generic_NCR5380_release_resources - free resources
|
||||
* @instance: host adapter to clean up
|
||||
|
|
@ -504,12 +458,12 @@ const char *generic_NCR5380_info(struct Scsi_Host *host)
|
|||
* Locks: none
|
||||
*/
|
||||
|
||||
int generic_NCR5380_release_resources(struct Scsi_Host *instance)
|
||||
static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
|
||||
{
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
if (instance->irq != NO_IRQ)
|
||||
free_irq(instance->irq, instance);
|
||||
NCR5380_exit(instance);
|
||||
|
||||
|
|
@ -741,163 +695,9 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
|
|||
|
||||
#include "NCR5380.c"
|
||||
|
||||
#define PRINTP(x) seq_printf(m, x)
|
||||
#define ANDP ,
|
||||
|
||||
static void sprint_opcode(struct seq_file *m, int opcode)
|
||||
{
|
||||
PRINTP("0x%02x " ANDP opcode);
|
||||
}
|
||||
|
||||
static void sprint_command(struct seq_file *m, unsigned char *command)
|
||||
{
|
||||
int i, s;
|
||||
sprint_opcode(m, command[0]);
|
||||
for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
|
||||
PRINTP("%02x " ANDP command[i]);
|
||||
PRINTP("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* sprintf_Scsi_Cmnd - print a scsi command
|
||||
* @m: seq_fil to print into
|
||||
* @cmd: SCSI command block
|
||||
*
|
||||
* Print out the target and command data in hex
|
||||
*/
|
||||
|
||||
static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
|
||||
{
|
||||
PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
|
||||
PRINTP(" command = ");
|
||||
sprint_command(m, cmd->cmnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* generic_NCR5380_proc_info - /proc for NCR5380 driver
|
||||
* @buffer: buffer to print into
|
||||
* @start: start position
|
||||
* @offset: offset into buffer
|
||||
* @len: length
|
||||
* @hostno: instance to affect
|
||||
* @inout: read/write
|
||||
*
|
||||
* Provide the procfs information for the 5380 controller. We fill
|
||||
* this with useful debugging information including the commands
|
||||
* being executed, disconnected command queue and the statistical
|
||||
* data
|
||||
*
|
||||
* Locks: global cli/lock for queue walk
|
||||
*/
|
||||
|
||||
static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
|
||||
{
|
||||
NCR5380_local_declare();
|
||||
unsigned long flags;
|
||||
unsigned char status;
|
||||
int i;
|
||||
Scsi_Cmnd *ptr;
|
||||
struct NCR5380_hostdata *hostdata;
|
||||
#ifdef NCR5380_STATS
|
||||
struct scsi_device *dev;
|
||||
#endif
|
||||
|
||||
NCR5380_setup(scsi_ptr);
|
||||
hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
|
||||
|
||||
spin_lock_irqsave(scsi_ptr->host_lock, flags);
|
||||
PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
|
||||
PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
|
||||
PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
|
||||
#ifdef NCR53C400
|
||||
PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
|
||||
PRINTP("NCR53C400 card%s detected\n" ANDP(((struct NCR5380_hostdata *) scsi_ptr->hostdata)->flags & FLAG_NCR53C400) ? "" : " not");
|
||||
# if NCR53C400_PSEUDO_DMA
|
||||
PRINTP("NCR53C400 pseudo DMA used\n");
|
||||
# endif
|
||||
#else
|
||||
PRINTP("NO NCR53C400 driver extensions\n");
|
||||
#endif
|
||||
PRINTP("Using %s mapping at %s 0x%lx, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
|
||||
if (scsi_ptr->irq == SCSI_IRQ_NONE)
|
||||
PRINTP("no interrupt\n");
|
||||
else
|
||||
PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
|
||||
|
||||
#ifdef NCR5380_STATS
|
||||
if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
|
||||
PRINTP("There are commands pending, transfer rates may be crud\n");
|
||||
if (hostdata->pendingr)
|
||||
PRINTP(" %d pending reads" ANDP hostdata->pendingr);
|
||||
if (hostdata->pendingw)
|
||||
PRINTP(" %d pending writes" ANDP hostdata->pendingw);
|
||||
if (hostdata->pendingr || hostdata->pendingw)
|
||||
PRINTP("\n");
|
||||
shost_for_each_device(dev, scsi_ptr) {
|
||||
unsigned long br = hostdata->bytes_read[dev->id];
|
||||
unsigned long bw = hostdata->bytes_write[dev->id];
|
||||
long tr = hostdata->time_read[dev->id] / HZ;
|
||||
long tw = hostdata->time_write[dev->id] / HZ;
|
||||
|
||||
PRINTP(" T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
|
||||
for (i = 0; i < 8; i++)
|
||||
if (dev->vendor[i] >= 0x20)
|
||||
seq_putc(m, dev->vendor[i]);
|
||||
seq_putc(m, ' ');
|
||||
for (i = 0; i < 16; i++)
|
||||
if (dev->model[i] >= 0x20)
|
||||
seq_putc(m, dev->model[i]);
|
||||
seq_putc(m, ' ');
|
||||
for (i = 0; i < 4; i++)
|
||||
if (dev->rev[i] >= 0x20)
|
||||
seq_putc(m, dev->rev[i]);
|
||||
seq_putc(m, ' ');
|
||||
|
||||
PRINTP("\n%10ld kb read in %5ld secs" ANDP br / 1024 ANDP tr);
|
||||
if (tr)
|
||||
PRINTP(" @ %5ld bps" ANDP br / tr);
|
||||
|
||||
PRINTP("\n%10ld kb written in %5ld secs" ANDP bw / 1024 ANDP tw);
|
||||
if (tw)
|
||||
PRINTP(" @ %5ld bps" ANDP bw / tw);
|
||||
PRINTP("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
status = NCR5380_read(STATUS_REG);
|
||||
if (!(status & SR_REQ))
|
||||
PRINTP("REQ not asserted, phase unknown.\n");
|
||||
else {
|
||||
for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
|
||||
PRINTP("Phase %s\n" ANDP phases[i].name);
|
||||
}
|
||||
|
||||
if (!hostdata->connected) {
|
||||
PRINTP("No currently connected command\n");
|
||||
} else {
|
||||
sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
|
||||
}
|
||||
|
||||
PRINTP("issue_queue\n");
|
||||
|
||||
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
|
||||
sprint_Scsi_Cmnd(m, ptr);
|
||||
|
||||
PRINTP("disconnected_queue\n");
|
||||
|
||||
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
|
||||
sprint_Scsi_Cmnd(m, ptr);
|
||||
|
||||
spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef PRINTP
|
||||
#undef ANDP
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.show_info = generic_NCR5380_show_info,
|
||||
.name = "Generic NCR5380/NCR53C400 Scsi Driver",
|
||||
.name = "Generic NCR5380/NCR53C400 SCSI",
|
||||
.detect = generic_NCR5380_detect,
|
||||
.release = generic_NCR5380_release_resources,
|
||||
.info = generic_NCR5380_info,
|
||||
|
|
|
|||
|
|
@ -9,28 +9,11 @@
|
|||
*
|
||||
* NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
|
||||
* K.Lentin@cs.monash.edu.au
|
||||
*
|
||||
* ALPHA RELEASE 1.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
#ifndef GENERIC_NCR5380_H
|
||||
#define GENERIC_NCR5380_H
|
||||
|
||||
|
||||
#define GENERIC_NCR5380_PUBLIC_RELEASE 1
|
||||
|
||||
#ifdef NCR53C400
|
||||
#define BIOSPARAM
|
||||
#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
|
||||
|
|
@ -39,12 +22,6 @@
|
|||
#endif
|
||||
|
||||
#ifndef ASM
|
||||
static int generic_NCR5380_abort(Scsi_Cmnd *);
|
||||
static int generic_NCR5380_detect(struct scsi_host_template *);
|
||||
static int generic_NCR5380_release_resources(struct Scsi_Host *);
|
||||
static int generic_NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
|
||||
static const char* generic_NCR5380_info(struct Scsi_Host *);
|
||||
|
||||
#ifndef CMD_PER_LUN
|
||||
#define CMD_PER_LUN 2
|
||||
|
|
@ -118,7 +95,8 @@ static const char* generic_NCR5380_info(struct Scsi_Host *);
|
|||
#define NCR5380_bus_reset generic_NCR5380_bus_reset
|
||||
#define NCR5380_pread generic_NCR5380_pread
|
||||
#define NCR5380_pwrite generic_NCR5380_pwrite
|
||||
#define NCR5380_proc_info notyet_generic_proc_info
|
||||
#define NCR5380_info generic_NCR5380_info
|
||||
#define NCR5380_show_info generic_NCR5380_show_info
|
||||
|
||||
#define BOARD_NCR5380 0
|
||||
#define BOARD_NCR53C400 1
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -118,7 +118,7 @@ struct ctlr_info {
|
|||
struct CfgTable __iomem *cfgtable;
|
||||
int interrupts_enabled;
|
||||
int max_commands;
|
||||
int commands_outstanding;
|
||||
atomic_t commands_outstanding;
|
||||
# define PERF_MODE_INT 0
|
||||
# define DOORBELL_INT 1
|
||||
# define SIMPLE_MODE_INT 2
|
||||
|
|
@ -164,7 +164,7 @@ struct ctlr_info {
|
|||
*/
|
||||
u32 trans_support;
|
||||
u32 trans_offset;
|
||||
struct TransTable_struct *transtable;
|
||||
struct TransTable_struct __iomem *transtable;
|
||||
unsigned long transMethod;
|
||||
|
||||
/* cap concurrent passthrus at some reasonable maximum */
|
||||
|
|
@ -181,7 +181,7 @@ struct ctlr_info {
|
|||
u32 *blockFetchTable;
|
||||
u32 *ioaccel1_blockFetchTable;
|
||||
u32 *ioaccel2_blockFetchTable;
|
||||
u32 *ioaccel2_bft2_regs;
|
||||
u32 __iomem *ioaccel2_bft2_regs;
|
||||
unsigned char *hba_inquiry_data;
|
||||
u32 driver_support;
|
||||
u32 fw_support;
|
||||
|
|
@ -192,7 +192,7 @@ struct ctlr_info {
|
|||
u64 last_heartbeat_timestamp;
|
||||
u32 heartbeat_sample_interval;
|
||||
atomic_t firmware_flash_in_progress;
|
||||
u32 *lockup_detected;
|
||||
u32 __percpu *lockup_detected;
|
||||
struct delayed_work monitor_ctlr_work;
|
||||
int remove_in_progress;
|
||||
u32 fifo_recently_full;
|
||||
|
|
@ -395,7 +395,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
|
|||
static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
|
||||
{
|
||||
struct reply_queue_buffer *rq = &h->reply_queue[q];
|
||||
unsigned long flags, register_value = FIFO_EMPTY;
|
||||
unsigned long register_value = FIFO_EMPTY;
|
||||
|
||||
/* msi auto clears the interrupt pending bit. */
|
||||
if (!(h->msi_vector || h->msix_vector)) {
|
||||
|
|
@ -413,9 +413,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
|
|||
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
|
||||
register_value = rq->head[rq->current_entry];
|
||||
rq->current_entry++;
|
||||
spin_lock_irqsave(&h->lock, flags);
|
||||
h->commands_outstanding--;
|
||||
spin_unlock_irqrestore(&h->lock, flags);
|
||||
atomic_dec(&h->commands_outstanding);
|
||||
} else {
|
||||
register_value = FIFO_EMPTY;
|
||||
}
|
||||
|
|
@ -433,11 +431,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
|
|||
*/
|
||||
static unsigned long SA5_fifo_full(struct ctlr_info *h)
|
||||
{
|
||||
if (h->commands_outstanding >= h->max_commands)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return atomic_read(&h->commands_outstanding) >= h->max_commands;
|
||||
}
|
||||
/*
|
||||
* returns value read from hardware.
|
||||
|
|
@ -448,13 +442,9 @@ static unsigned long SA5_completed(struct ctlr_info *h,
|
|||
{
|
||||
unsigned long register_value
|
||||
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
|
||||
unsigned long flags;
|
||||
|
||||
if (register_value != FIFO_EMPTY) {
|
||||
spin_lock_irqsave(&h->lock, flags);
|
||||
h->commands_outstanding--;
|
||||
spin_unlock_irqrestore(&h->lock, flags);
|
||||
}
|
||||
if (register_value != FIFO_EMPTY)
|
||||
atomic_dec(&h->commands_outstanding);
|
||||
|
||||
#ifdef HPSA_DEBUG
|
||||
if (register_value != FIFO_EMPTY)
|
||||
|
|
@ -510,7 +500,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
|
|||
{
|
||||
u64 register_value;
|
||||
struct reply_queue_buffer *rq = &h->reply_queue[q];
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(q >= h->nreply_queues);
|
||||
|
||||
|
|
@ -528,9 +517,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
|
|||
wmb();
|
||||
writel((q << 24) | rq->current_entry, h->vaddr +
|
||||
IOACCEL_MODE1_CONSUMER_INDEX);
|
||||
spin_lock_irqsave(&h->lock, flags);
|
||||
h->commands_outstanding--;
|
||||
spin_unlock_irqrestore(&h->lock, flags);
|
||||
atomic_dec(&h->commands_outstanding);
|
||||
}
|
||||
return (unsigned long) register_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ struct ReportExtendedLUNdata {
|
|||
u8 LUNListLength[4];
|
||||
u8 extended_response_flag;
|
||||
u8 reserved[3];
|
||||
struct ext_report_lun_entry LUN[HPSA_MAX_LUN];
|
||||
struct ext_report_lun_entry LUN[HPSA_MAX_PHYS_LUN];
|
||||
};
|
||||
|
||||
struct SenseSubsystem_info {
|
||||
|
|
@ -314,28 +314,36 @@ struct CommandListHeader {
|
|||
u8 ReplyQueue;
|
||||
u8 SGList;
|
||||
u16 SGTotal;
|
||||
struct vals32 Tag;
|
||||
u64 tag;
|
||||
union LUNAddr LUN;
|
||||
};
|
||||
|
||||
struct RequestBlock {
|
||||
u8 CDBLen;
|
||||
struct {
|
||||
u8 Type:3;
|
||||
u8 Attribute:3;
|
||||
u8 Direction:2;
|
||||
} Type;
|
||||
/*
|
||||
* type_attr_dir:
|
||||
* type: low 3 bits
|
||||
* attr: middle 3 bits
|
||||
* dir: high 2 bits
|
||||
*/
|
||||
u8 type_attr_dir;
|
||||
#define TYPE_ATTR_DIR(t, a, d) ((((d) & 0x03) << 6) |\
|
||||
(((a) & 0x07) << 3) |\
|
||||
((t) & 0x07))
|
||||
#define GET_TYPE(tad) ((tad) & 0x07)
|
||||
#define GET_ATTR(tad) (((tad) >> 3) & 0x07)
|
||||
#define GET_DIR(tad) (((tad) >> 6) & 0x03)
|
||||
u16 Timeout;
|
||||
u8 CDB[16];
|
||||
};
|
||||
|
||||
struct ErrDescriptor {
|
||||
struct vals32 Addr;
|
||||
u64 Addr;
|
||||
u32 Len;
|
||||
};
|
||||
|
||||
struct SGDescriptor {
|
||||
struct vals32 Addr;
|
||||
u64 Addr;
|
||||
u32 Len;
|
||||
u32 Ext;
|
||||
};
|
||||
|
|
@ -434,8 +442,8 @@ struct io_accel1_cmd {
|
|||
u16 timeout_sec; /* 0x62 - 0x63 */
|
||||
u8 ReplyQueue; /* 0x64 */
|
||||
u8 reserved9[3]; /* 0x65 - 0x67 */
|
||||
struct vals32 Tag; /* 0x68 - 0x6F */
|
||||
struct vals32 host_addr; /* 0x70 - 0x77 */
|
||||
u64 tag; /* 0x68 - 0x6F */
|
||||
u64 host_addr; /* 0x70 - 0x77 */
|
||||
u8 CISS_LUN[8]; /* 0x78 - 0x7F */
|
||||
struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES];
|
||||
} __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT);
|
||||
|
|
@ -555,8 +563,8 @@ struct hpsa_tmf_struct {
|
|||
u8 reserved1; /* byte 3 Reserved */
|
||||
u32 it_nexus; /* SCSI I-T Nexus */
|
||||
u8 lun_id[8]; /* LUN ID for TMF request */
|
||||
struct vals32 Tag; /* cciss tag associated w/ request */
|
||||
struct vals32 abort_tag;/* cciss tag of SCSI cmd or task to abort */
|
||||
u64 tag; /* cciss tag associated w/ request */
|
||||
u64 abort_tag; /* cciss tag of SCSI cmd or task to abort */
|
||||
u64 error_ptr; /* Error Pointer */
|
||||
u32 error_len; /* Error Length */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1118,17 +1118,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
|
|||
}
|
||||
|
||||
static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
|
||||
int queue_depth, int reason)
|
||||
int queue_depth)
|
||||
{
|
||||
struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
|
||||
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > hba->max_requests)
|
||||
queue_depth = hba->max_requests;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
return queue_depth;
|
||||
return scsi_change_queue_depth(sdev, queue_depth);
|
||||
}
|
||||
|
||||
static ssize_t hptiop_show_version(struct device *dev,
|
||||
|
|
|
|||
|
|
@ -2900,17 +2900,12 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
|
|||
* Return value:
|
||||
* actual depth set
|
||||
**/
|
||||
static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason)
|
||||
static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (qdepth > IBMVFC_MAX_CMDS_PER_LUN)
|
||||
qdepth = IBMVFC_MAX_CMDS_PER_LUN;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
return sdev->queue_depth;
|
||||
return scsi_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
static ssize_t ibmvfc_show_host_partition_name(struct device *dev,
|
||||
|
|
@ -3103,6 +3098,7 @@ static struct scsi_host_template driver_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = ibmvfc_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1941,17 +1941,11 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
|
|||
* Return value:
|
||||
* actual depth set
|
||||
**/
|
||||
static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason)
|
||||
static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
|
||||
qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
return sdev->queue_depth;
|
||||
return scsi_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -3942,8 +3942,9 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
sglist->num_dma_sg = pci_map_sg(ioa_cfg->pdev, sglist->scatterlist,
|
||||
sglist->num_sg, DMA_TO_DEVICE);
|
||||
sglist->num_dma_sg = dma_map_sg(&ioa_cfg->pdev->dev,
|
||||
sglist->scatterlist, sglist->num_sg,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (!sglist->num_dma_sg) {
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
|
@ -4327,16 +4328,12 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
|
|||
* Return value:
|
||||
* actual depth set
|
||||
**/
|
||||
static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason)
|
||||
static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
|
||||
struct ipr_resource_entry *res;
|
||||
unsigned long lock_flags = 0;
|
||||
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
res = (struct ipr_resource_entry *)sdev->hostdata;
|
||||
|
||||
|
|
@ -4344,7 +4341,7 @@ static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
|||
qdepth = IPR_MAX_CMD_PER_ATA_LUN;
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
scsi_change_queue_depth(sdev, qdepth);
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
|
|
@ -4751,7 +4748,7 @@ static int ipr_slave_configure(struct scsi_device *sdev)
|
|||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
||||
if (ap) {
|
||||
scsi_adjust_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN);
|
||||
scsi_change_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN);
|
||||
ata_sas_slave_configure(sdev, ap);
|
||||
}
|
||||
|
||||
|
|
@ -5571,7 +5568,7 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
|
|||
nseg = scsi_dma_map(scsi_cmd);
|
||||
if (nseg < 0) {
|
||||
if (printk_ratelimit())
|
||||
dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
|
||||
dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -5622,7 +5619,7 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
|
|||
|
||||
nseg = scsi_dma_map(scsi_cmd);
|
||||
if (nseg < 0) {
|
||||
dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
|
||||
dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -8392,7 +8389,7 @@ static int ipr_reset_ucode_download_done(struct ipr_cmnd *ipr_cmd)
|
|||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct ipr_sglist *sglist = ioa_cfg->ucode_sglist;
|
||||
|
||||
pci_unmap_sg(ioa_cfg->pdev, sglist->scatterlist,
|
||||
dma_unmap_sg(&ioa_cfg->pdev->dev, sglist->scatterlist,
|
||||
sglist->num_sg, DMA_TO_DEVICE);
|
||||
|
||||
ipr_cmd->job_step = ipr_reset_alert;
|
||||
|
|
@ -8832,7 +8829,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
|
|||
|
||||
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
|
||||
if (ioa_cfg->ipr_cmnd_list[i])
|
||||
pci_pool_free(ioa_cfg->ipr_cmd_pool,
|
||||
dma_pool_free(ioa_cfg->ipr_cmd_pool,
|
||||
ioa_cfg->ipr_cmnd_list[i],
|
||||
ioa_cfg->ipr_cmnd_list_dma[i]);
|
||||
|
||||
|
|
@ -8840,7 +8837,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
|
|||
}
|
||||
|
||||
if (ioa_cfg->ipr_cmd_pool)
|
||||
pci_pool_destroy(ioa_cfg->ipr_cmd_pool);
|
||||
dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
|
||||
|
||||
kfree(ioa_cfg->ipr_cmnd_list);
|
||||
kfree(ioa_cfg->ipr_cmnd_list_dma);
|
||||
|
|
@ -8861,25 +8858,24 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
|
|||
int i;
|
||||
|
||||
kfree(ioa_cfg->res_entries);
|
||||
pci_free_consistent(ioa_cfg->pdev, sizeof(struct ipr_misc_cbs),
|
||||
ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev, sizeof(struct ipr_misc_cbs),
|
||||
ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
|
||||
ipr_free_cmd_blks(ioa_cfg);
|
||||
|
||||
for (i = 0; i < ioa_cfg->hrrq_num; i++)
|
||||
pci_free_consistent(ioa_cfg->pdev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
ioa_cfg->hrrq[i].host_rrq,
|
||||
ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
ioa_cfg->hrrq[i].host_rrq,
|
||||
ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
|
||||
pci_free_consistent(ioa_cfg->pdev, ioa_cfg->cfg_table_size,
|
||||
ioa_cfg->u.cfg_table,
|
||||
ioa_cfg->cfg_table_dma);
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size,
|
||||
ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
|
||||
|
||||
for (i = 0; i < IPR_NUM_HCAMS; i++) {
|
||||
pci_free_consistent(ioa_cfg->pdev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
ioa_cfg->hostrcb[i],
|
||||
ioa_cfg->hostrcb_dma[i]);
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
ioa_cfg->hostrcb[i],
|
||||
ioa_cfg->hostrcb_dma[i]);
|
||||
}
|
||||
|
||||
ipr_free_dump(ioa_cfg);
|
||||
|
|
@ -8940,7 +8936,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
|
|||
dma_addr_t dma_addr;
|
||||
int i, entries_each_hrrq, hrrq_id = 0;
|
||||
|
||||
ioa_cfg->ipr_cmd_pool = pci_pool_create(IPR_NAME, ioa_cfg->pdev,
|
||||
ioa_cfg->ipr_cmd_pool = dma_pool_create(IPR_NAME, &ioa_cfg->pdev->dev,
|
||||
sizeof(struct ipr_cmnd), 512, 0);
|
||||
|
||||
if (!ioa_cfg->ipr_cmd_pool)
|
||||
|
|
@ -8990,7 +8986,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
|
|||
}
|
||||
|
||||
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
|
||||
ipr_cmd = pci_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
|
||||
ipr_cmd = dma_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
|
||||
|
||||
if (!ipr_cmd) {
|
||||
ipr_free_cmd_blks(ioa_cfg);
|
||||
|
|
@ -9061,9 +9057,10 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
|
|||
ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg;
|
||||
}
|
||||
|
||||
ioa_cfg->vpd_cbs = pci_alloc_consistent(ioa_cfg->pdev,
|
||||
sizeof(struct ipr_misc_cbs),
|
||||
&ioa_cfg->vpd_cbs_dma);
|
||||
ioa_cfg->vpd_cbs = dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct ipr_misc_cbs),
|
||||
&ioa_cfg->vpd_cbs_dma,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ioa_cfg->vpd_cbs)
|
||||
goto out_free_res_entries;
|
||||
|
|
@ -9072,13 +9069,14 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
|
|||
goto out_free_vpd_cbs;
|
||||
|
||||
for (i = 0; i < ioa_cfg->hrrq_num; i++) {
|
||||
ioa_cfg->hrrq[i].host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
|
||||
ioa_cfg->hrrq[i].host_rrq = dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
&ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
&ioa_cfg->hrrq[i].host_rrq_dma,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ioa_cfg->hrrq[i].host_rrq) {
|
||||
while (--i > 0)
|
||||
pci_free_consistent(pdev,
|
||||
dma_free_coherent(&pdev->dev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
ioa_cfg->hrrq[i].host_rrq,
|
||||
ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
|
|
@ -9087,17 +9085,19 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
|
|||
ioa_cfg->hrrq[i].ioa_cfg = ioa_cfg;
|
||||
}
|
||||
|
||||
ioa_cfg->u.cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
|
||||
ioa_cfg->cfg_table_size,
|
||||
&ioa_cfg->cfg_table_dma);
|
||||
ioa_cfg->u.cfg_table = dma_alloc_coherent(&pdev->dev,
|
||||
ioa_cfg->cfg_table_size,
|
||||
&ioa_cfg->cfg_table_dma,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ioa_cfg->u.cfg_table)
|
||||
goto out_free_host_rrq;
|
||||
|
||||
for (i = 0; i < IPR_NUM_HCAMS; i++) {
|
||||
ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
&ioa_cfg->hostrcb_dma[i]);
|
||||
ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
&ioa_cfg->hostrcb_dma[i],
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ioa_cfg->hostrcb[i])
|
||||
goto out_free_hostrcb_dma;
|
||||
|
|
@ -9121,25 +9121,24 @@ out:
|
|||
|
||||
out_free_hostrcb_dma:
|
||||
while (i-- > 0) {
|
||||
pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
|
||||
ioa_cfg->hostrcb[i],
|
||||
ioa_cfg->hostrcb_dma[i]);
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct ipr_hostrcb),
|
||||
ioa_cfg->hostrcb[i],
|
||||
ioa_cfg->hostrcb_dma[i]);
|
||||
}
|
||||
pci_free_consistent(pdev, ioa_cfg->cfg_table_size,
|
||||
ioa_cfg->u.cfg_table,
|
||||
ioa_cfg->cfg_table_dma);
|
||||
dma_free_coherent(&pdev->dev, ioa_cfg->cfg_table_size,
|
||||
ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
|
||||
out_free_host_rrq:
|
||||
for (i = 0; i < ioa_cfg->hrrq_num; i++) {
|
||||
pci_free_consistent(pdev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
ioa_cfg->hrrq[i].host_rrq,
|
||||
ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
dma_free_coherent(&pdev->dev,
|
||||
sizeof(u32) * ioa_cfg->hrrq[i].size,
|
||||
ioa_cfg->hrrq[i].host_rrq,
|
||||
ioa_cfg->hrrq[i].host_rrq_dma);
|
||||
}
|
||||
out_ipr_free_cmd_blocks:
|
||||
ipr_free_cmd_blks(ioa_cfg);
|
||||
out_free_vpd_cbs:
|
||||
pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
|
||||
ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct ipr_misc_cbs),
|
||||
ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
|
||||
out_free_res_entries:
|
||||
kfree(ioa_cfg->res_entries);
|
||||
goto out;
|
||||
|
|
@ -9579,16 +9578,17 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
|
|||
ipr_init_regs(ioa_cfg);
|
||||
|
||||
if (ioa_cfg->sis64) {
|
||||
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
|
||||
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (rc < 0) {
|
||||
dev_dbg(&pdev->dev, "Failed to set 64 bit PCI DMA mask\n");
|
||||
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
dev_dbg(&pdev->dev, "Failed to set 64 bit DMA mask\n");
|
||||
rc = dma_set_mask_and_coherent(&pdev->dev,
|
||||
DMA_BIT_MASK(32));
|
||||
}
|
||||
} else
|
||||
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
|
||||
dev_err(&pdev->dev, "Failed to set DMA mask\n");
|
||||
goto cleanup_nomem;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1549,7 +1549,7 @@ struct ipr_ioa_cfg {
|
|||
struct ipr_misc_cbs *vpd_cbs;
|
||||
dma_addr_t vpd_cbs_dma;
|
||||
|
||||
struct pci_pool *ipr_cmd_pool;
|
||||
struct dma_pool *ipr_cmd_pool;
|
||||
|
||||
struct ipr_cmnd *reset_cmd;
|
||||
int (*reset) (struct ipr_cmnd *);
|
||||
|
|
|
|||
|
|
@ -1210,7 +1210,7 @@ ips_slave_configure(struct scsi_device * SDptr)
|
|||
min = ha->max_cmds / 2;
|
||||
if (ha->enq->ucLogDriveCount <= 2)
|
||||
min = ha->max_cmds - 1;
|
||||
scsi_adjust_queue_depth(SDptr, min);
|
||||
scsi_change_queue_depth(SDptr, min);
|
||||
}
|
||||
|
||||
SDptr->skip_ms_page_8 = 1;
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ static struct scsi_host_template isci_sht = {
|
|||
.ioctl = sas_ioctl,
|
||||
.shost_attrs = isci_host_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct sas_domain_function_template isci_transport_ops = {
|
||||
|
|
@ -259,8 +260,6 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
|
|||
sas_ha->sas_port = sas_ports;
|
||||
sas_ha->num_phys = SCI_MAX_PHYS;
|
||||
|
||||
sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
|
||||
sas_ha->lldd_max_execute_num = 1;
|
||||
sas_ha->strict_wide_ports = 1;
|
||||
|
||||
sas_register_ha(sas_ha);
|
||||
|
|
|
|||
|
|
@ -117,104 +117,97 @@ static inline int isci_device_io_ready(struct isci_remote_device *idev,
|
|||
* functions. This function is called by libsas to send a task down to
|
||||
* hardware.
|
||||
* @task: This parameter specifies the SAS task to send.
|
||||
* @num: This parameter specifies the number of tasks to queue.
|
||||
* @gfp_flags: This parameter specifies the context of this call.
|
||||
*
|
||||
* status, zero indicates success.
|
||||
*/
|
||||
int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
|
||||
int isci_task_execute_task(struct sas_task *task, gfp_t gfp_flags)
|
||||
{
|
||||
struct isci_host *ihost = dev_to_ihost(task->dev);
|
||||
struct isci_remote_device *idev;
|
||||
unsigned long flags;
|
||||
enum sci_status status = SCI_FAILURE;
|
||||
bool io_ready;
|
||||
u16 tag;
|
||||
|
||||
dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
idev = isci_lookup_device(task->dev);
|
||||
io_ready = isci_device_io_ready(idev, task);
|
||||
tag = isci_alloc_tag(ihost);
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
|
||||
for_each_sas_task(num, task) {
|
||||
enum sci_status status = SCI_FAILURE;
|
||||
dev_dbg(&ihost->pdev->dev,
|
||||
"task: %p, dev: %p idev: %p:%#lx cmd = %p\n",
|
||||
task, task->dev, idev, idev ? idev->flags : 0,
|
||||
task->uldd_task);
|
||||
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
idev = isci_lookup_device(task->dev);
|
||||
io_ready = isci_device_io_ready(idev, task);
|
||||
tag = isci_alloc_tag(ihost);
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
if (!idev) {
|
||||
isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
|
||||
SAS_DEVICE_UNKNOWN);
|
||||
} else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
|
||||
/* Indicate QUEUE_FULL so that the scsi midlayer
|
||||
* retries.
|
||||
*/
|
||||
isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
|
||||
SAS_QUEUE_FULL);
|
||||
} else {
|
||||
/* There is a device and it's ready for I/O. */
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
|
||||
dev_dbg(&ihost->pdev->dev,
|
||||
"task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n",
|
||||
task, num, task->dev, idev, idev ? idev->flags : 0,
|
||||
task->uldd_task);
|
||||
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
|
||||
/* The I/O was aborted. */
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
if (!idev) {
|
||||
isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
|
||||
SAS_DEVICE_UNKNOWN);
|
||||
} else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
|
||||
/* Indicate QUEUE_FULL so that the scsi midlayer
|
||||
* retries.
|
||||
*/
|
||||
isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
|
||||
SAS_QUEUE_FULL);
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_UNDELIVERED,
|
||||
SAM_STAT_TASK_ABORTED);
|
||||
} else {
|
||||
/* There is a device and it's ready for I/O. */
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
|
||||
/* The I/O was aborted. */
|
||||
spin_unlock_irqrestore(&task->task_state_lock,
|
||||
flags);
|
||||
/* build and send the request. */
|
||||
status = isci_request_execute(ihost, idev, task, tag);
|
||||
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_UNDELIVERED,
|
||||
SAM_STAT_TASK_ABORTED);
|
||||
} else {
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
if (status != SCI_SUCCESS) {
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
/* Did not really start this command. */
|
||||
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
/* build and send the request. */
|
||||
status = isci_request_execute(ihost, idev, task, tag);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
/* Did not really start this command. */
|
||||
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
if (test_bit(IDEV_GONE, &idev->flags)) {
|
||||
|
||||
/* Indicate that the device
|
||||
* is gone.
|
||||
*/
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_UNDELIVERED,
|
||||
SAS_DEVICE_UNKNOWN);
|
||||
} else {
|
||||
/* Indicate QUEUE_FULL so that
|
||||
* the scsi midlayer retries.
|
||||
* If the request failed for
|
||||
* remote device reasons, it
|
||||
* gets returned as
|
||||
* SAS_TASK_UNDELIVERED next
|
||||
* time through.
|
||||
*/
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_COMPLETE,
|
||||
SAS_QUEUE_FULL);
|
||||
}
|
||||
if (test_bit(IDEV_GONE, &idev->flags)) {
|
||||
/* Indicate that the device
|
||||
* is gone.
|
||||
*/
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_UNDELIVERED,
|
||||
SAS_DEVICE_UNKNOWN);
|
||||
} else {
|
||||
/* Indicate QUEUE_FULL so that
|
||||
* the scsi midlayer retries.
|
||||
* If the request failed for
|
||||
* remote device reasons, it
|
||||
* gets returned as
|
||||
* SAS_TASK_UNDELIVERED next
|
||||
* time through.
|
||||
*/
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_COMPLETE,
|
||||
SAS_QUEUE_FULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
/* command never hit the device, so just free
|
||||
* the tci and skip the sequence increment
|
||||
*/
|
||||
isci_tci_free(ihost, ISCI_TAG_TCI(tag));
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
}
|
||||
isci_put_device(idev);
|
||||
}
|
||||
|
||||
if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
/* command never hit the device, so just free
|
||||
* the tci and skip the sequence increment
|
||||
*/
|
||||
isci_tci_free(ihost, ISCI_TAG_TCI(tag));
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
}
|
||||
|
||||
isci_put_device(idev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,6 @@ static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
|
|||
|
||||
int isci_task_execute_task(
|
||||
struct sas_task *task,
|
||||
int num,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
int isci_task_abort_task(
|
||||
|
|
|
|||
|
|
@ -952,7 +952,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
|
|||
.module = THIS_MODULE,
|
||||
.name = "iSCSI Initiator over TCP/IP",
|
||||
.queuecommand = iscsi_queuecommand,
|
||||
.change_queue_depth = iscsi_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1,
|
||||
.sg_tablesize = 4096,
|
||||
.max_sectors = 0xFFFF,
|
||||
|
|
@ -966,6 +966,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
|
|||
.target_alloc = iscsi_target_alloc,
|
||||
.proc_name = "iscsi_tcp",
|
||||
.this_id = -1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct iscsi_transport iscsi_sw_tcp_transport = {
|
||||
|
|
|
|||
|
|
@ -2160,36 +2160,11 @@ int fc_slave_alloc(struct scsi_device *sdev)
|
|||
if (!rport || fc_remote_port_chkready(rport))
|
||||
return -ENXIO;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
|
||||
scsi_change_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fc_slave_alloc);
|
||||
|
||||
/**
|
||||
* fc_change_queue_depth() - Change a device's queue depth
|
||||
* @sdev: The SCSI device whose queue depth is to change
|
||||
* @qdepth: The new queue depth
|
||||
* @reason: The resason for the change
|
||||
*/
|
||||
int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case SCSI_QDEPTH_DEFAULT:
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
break;
|
||||
case SCSI_QDEPTH_QFULL:
|
||||
scsi_track_queue_full(sdev, qdepth);
|
||||
break;
|
||||
case SCSI_QDEPTH_RAMP_UP:
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
EXPORT_SYMBOL(fc_change_queue_depth);
|
||||
|
||||
/**
|
||||
* fc_fcp_destory() - Tear down the FCP layer for a given local port
|
||||
* @lport: The local port that no longer needs the FCP layer
|
||||
|
|
|
|||
|
|
@ -1771,25 +1771,6 @@ fault:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_queuecommand);
|
||||
|
||||
int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case SCSI_QDEPTH_DEFAULT:
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
break;
|
||||
case SCSI_QDEPTH_QFULL:
|
||||
scsi_track_queue_full(sdev, depth);
|
||||
break;
|
||||
case SCSI_QDEPTH_RAMP_UP:
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
|
||||
|
||||
int iscsi_target_alloc(struct scsi_target *starget)
|
||||
{
|
||||
struct iscsi_cls_session *cls_session = starget_to_session(starget);
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ static void sas_ata_task_done(struct sas_task *task)
|
|||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
qc_already_gone:
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
}
|
||||
|
||||
|
|
@ -244,12 +243,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||
if (qc->scsicmd)
|
||||
ASSIGN_SAS_TASK(qc->scsicmd, task);
|
||||
|
||||
if (sas_ha->lldd_max_execute_num < 2)
|
||||
ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
|
||||
else
|
||||
ret = sas_queue_up(task);
|
||||
|
||||
/* Examine */
|
||||
ret = i->dft->lldd_execute_task(task, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
SAS_DPRINTK("lldd_execute_task returned: %d\n", ret);
|
||||
|
||||
|
|
@ -485,7 +479,6 @@ static void sas_ata_internal_abort(struct sas_task *task)
|
|||
|
||||
return;
|
||||
out:
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
|
|||
task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);
|
||||
res = i->dft->lldd_execute_task(task, GFP_KERNEL);
|
||||
|
||||
if (res) {
|
||||
del_timer(&task->slow_task->timer);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ struct sas_task *sas_alloc_task(gfp_t flags)
|
|||
struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
|
||||
|
||||
if (task) {
|
||||
INIT_LIST_HEAD(&task->list);
|
||||
spin_lock_init(&task->task_state_lock);
|
||||
task->task_state_flags = SAS_TASK_STATE_PENDING;
|
||||
}
|
||||
|
|
@ -77,7 +76,6 @@ EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
|
|||
void sas_free_task(struct sas_task *task)
|
||||
{
|
||||
if (task) {
|
||||
BUG_ON(!list_empty(&task->list));
|
||||
kfree(task->slow_task);
|
||||
kmem_cache_free(sas_task_cache, task);
|
||||
}
|
||||
|
|
@ -127,11 +125,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
|
|||
spin_lock_init(&sas_ha->phy_port_lock);
|
||||
sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
|
||||
|
||||
if (sas_ha->lldd_queue_size == 0)
|
||||
sas_ha->lldd_queue_size = 1;
|
||||
else if (sas_ha->lldd_queue_size == -1)
|
||||
sas_ha->lldd_queue_size = 128; /* Sanity */
|
||||
|
||||
set_bit(SAS_HA_REGISTERED, &sas_ha->state);
|
||||
spin_lock_init(&sas_ha->lock);
|
||||
mutex_init(&sas_ha->drain_mutex);
|
||||
|
|
@ -157,15 +150,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
|
|||
goto Undo_ports;
|
||||
}
|
||||
|
||||
if (sas_ha->lldd_max_execute_num > 1) {
|
||||
error = sas_init_queue(sas_ha);
|
||||
if (error) {
|
||||
printk(KERN_NOTICE "couldn't start queue thread:%d, "
|
||||
"running in direct mode\n", error);
|
||||
sas_ha->lldd_max_execute_num = 1;
|
||||
}
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sas_ha->eh_done_q);
|
||||
INIT_LIST_HEAD(&sas_ha->eh_ata_q);
|
||||
|
||||
|
|
@ -201,11 +185,6 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
|
|||
__sas_drain_work(sas_ha);
|
||||
mutex_unlock(&sas_ha->drain_mutex);
|
||||
|
||||
if (sas_ha->lldd_max_execute_num > 1) {
|
||||
sas_shutdown_queue(sas_ha);
|
||||
sas_ha->lldd_max_execute_num = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,9 +66,7 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha);
|
|||
|
||||
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
|
||||
|
||||
int sas_init_queue(struct sas_ha_struct *sas_ha);
|
||||
int sas_init_events(struct sas_ha_struct *sas_ha);
|
||||
void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
|
||||
void sas_disable_revalidation(struct sas_ha_struct *ha);
|
||||
void sas_enable_revalidation(struct sas_ha_struct *ha);
|
||||
void __sas_drain_work(struct sas_ha_struct *ha);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task)
|
|||
|
||||
sc->result = (hs << 16) | stat;
|
||||
ASSIGN_SAS_TASK(sc, NULL);
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +137,6 @@ static void sas_scsi_task_done(struct sas_task *task)
|
|||
|
||||
if (unlikely(!sc)) {
|
||||
SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
return;
|
||||
}
|
||||
|
|
@ -179,31 +177,10 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
|
|||
return task;
|
||||
}
|
||||
|
||||
int sas_queue_up(struct sas_task *task)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = task->dev->port->ha;
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(list);
|
||||
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
if (sas_ha->lldd_queue_size < core->task_queue_size + 1) {
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
return -SAS_QUEUE_FULL;
|
||||
}
|
||||
list_add_tail(&task->list, &core->task_queue);
|
||||
core->task_queue_size += 1;
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
wake_up_process(core->queue_thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct sas_internal *i = to_sas_internal(host->transportt);
|
||||
struct domain_device *dev = cmd_to_domain_dev(cmd);
|
||||
struct sas_ha_struct *sas_ha = dev->port->ha;
|
||||
struct sas_task *task;
|
||||
int res = 0;
|
||||
|
||||
|
|
@ -224,12 +201,7 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|||
if (!task)
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
/* Queue up, Direct Mode or Task Collector Mode. */
|
||||
if (sas_ha->lldd_max_execute_num < 2)
|
||||
res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
|
||||
else
|
||||
res = sas_queue_up(task);
|
||||
|
||||
res = i->dft->lldd_execute_task(task, GFP_ATOMIC);
|
||||
if (res)
|
||||
goto out_free_task;
|
||||
return 0;
|
||||
|
|
@ -323,37 +295,17 @@ enum task_disposition {
|
|||
TASK_IS_DONE,
|
||||
TASK_IS_ABORTED,
|
||||
TASK_IS_AT_LU,
|
||||
TASK_IS_NOT_AT_HA,
|
||||
TASK_IS_NOT_AT_LU,
|
||||
TASK_ABORT_FAILED,
|
||||
};
|
||||
|
||||
static enum task_disposition sas_scsi_find_task(struct sas_task *task)
|
||||
{
|
||||
struct sas_ha_struct *ha = task->dev->port->ha;
|
||||
unsigned long flags;
|
||||
int i, res;
|
||||
struct sas_internal *si =
|
||||
to_sas_internal(task->dev->port->ha->core.shost->transportt);
|
||||
|
||||
if (ha->lldd_max_execute_num > 1) {
|
||||
struct scsi_core *core = &ha->core;
|
||||
struct sas_task *t, *n;
|
||||
|
||||
mutex_lock(&core->task_queue_flush);
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
list_for_each_entry_safe(t, n, &core->task_queue, list)
|
||||
if (task == t) {
|
||||
list_del_init(&t->list);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
mutex_unlock(&core->task_queue_flush);
|
||||
|
||||
if (task == t)
|
||||
return TASK_IS_NOT_AT_HA;
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
SAS_DPRINTK("%s: aborting task 0x%p\n", __func__, task);
|
||||
res = si->dft->lldd_abort_task(task);
|
||||
|
|
@ -667,14 +619,6 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|||
cmd->eh_eflags = 0;
|
||||
|
||||
switch (res) {
|
||||
case TASK_IS_NOT_AT_HA:
|
||||
SAS_DPRINTK("%s: task 0x%p is not at ha: %s\n",
|
||||
__func__, task,
|
||||
cmd->retries ? "retry" : "aborted");
|
||||
if (cmd->retries)
|
||||
cmd->retries--;
|
||||
sas_eh_finish_cmd(cmd);
|
||||
continue;
|
||||
case TASK_IS_DONE:
|
||||
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
|
||||
task);
|
||||
|
|
@ -836,9 +780,6 @@ retry:
|
|||
scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
|
||||
|
||||
out:
|
||||
if (ha->lldd_max_execute_num > 1)
|
||||
wake_up_process(ha->core.queue_thread);
|
||||
|
||||
sas_eh_handle_resets(shost);
|
||||
|
||||
/* now link into libata eh --- if we have any ata devices */
|
||||
|
|
@ -940,12 +881,12 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
|
|||
sas_read_port_mode_page(scsi_dev);
|
||||
|
||||
if (scsi_dev->tagged_supported) {
|
||||
scsi_adjust_queue_depth(scsi_dev, SAS_DEF_QD);
|
||||
scsi_change_queue_depth(scsi_dev, SAS_DEF_QD);
|
||||
} else {
|
||||
SAS_DPRINTK("device %llx, LUN %llx doesn't support "
|
||||
"TCQ\n", SAS_ADDR(dev->sas_addr),
|
||||
scsi_dev->lun);
|
||||
scsi_adjust_queue_depth(scsi_dev, 1);
|
||||
scsi_change_queue_depth(scsi_dev, 1);
|
||||
}
|
||||
|
||||
scsi_dev->allow_restart = 1;
|
||||
|
|
@ -953,29 +894,16 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
|
||||
int sas_change_queue_depth(struct scsi_device *sdev, int depth)
|
||||
{
|
||||
struct domain_device *dev = sdev_to_domain_dev(sdev);
|
||||
|
||||
if (dev_is_sata(dev))
|
||||
return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
|
||||
reason);
|
||||
return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
|
||||
|
||||
switch (reason) {
|
||||
case SCSI_QDEPTH_DEFAULT:
|
||||
case SCSI_QDEPTH_RAMP_UP:
|
||||
if (!sdev->tagged_supported)
|
||||
depth = 1;
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
break;
|
||||
case SCSI_QDEPTH_QFULL:
|
||||
scsi_track_queue_full(sdev, depth);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return depth;
|
||||
if (!sdev->tagged_supported)
|
||||
depth = 1;
|
||||
return scsi_change_queue_depth(sdev, depth);
|
||||
}
|
||||
|
||||
int sas_change_queue_type(struct scsi_device *scsi_dev, int type)
|
||||
|
|
@ -997,121 +925,6 @@ int sas_bios_param(struct scsi_device *scsi_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- Task Collector Thread implementation ---------- */
|
||||
|
||||
static void sas_queue(struct sas_ha_struct *sas_ha)
|
||||
{
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(q);
|
||||
int can_queue;
|
||||
int res;
|
||||
struct sas_internal *i = to_sas_internal(core->shost->transportt);
|
||||
|
||||
mutex_lock(&core->task_queue_flush);
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
while (!kthread_should_stop() &&
|
||||
!list_empty(&core->task_queue) &&
|
||||
!test_bit(SAS_HA_FROZEN, &sas_ha->state)) {
|
||||
|
||||
can_queue = sas_ha->lldd_queue_size - core->task_queue_size;
|
||||
if (can_queue >= 0) {
|
||||
can_queue = core->task_queue_size;
|
||||
list_splice_init(&core->task_queue, &q);
|
||||
} else {
|
||||
struct list_head *a, *n;
|
||||
|
||||
can_queue = sas_ha->lldd_queue_size;
|
||||
list_for_each_safe(a, n, &core->task_queue) {
|
||||
list_move_tail(a, &q);
|
||||
if (--can_queue == 0)
|
||||
break;
|
||||
}
|
||||
can_queue = sas_ha->lldd_queue_size;
|
||||
}
|
||||
core->task_queue_size -= can_queue;
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
{
|
||||
struct sas_task *task = list_entry(q.next,
|
||||
struct sas_task,
|
||||
list);
|
||||
list_del_init(&q);
|
||||
res = i->dft->lldd_execute_task(task, can_queue,
|
||||
GFP_KERNEL);
|
||||
if (unlikely(res))
|
||||
__list_add(&q, task->list.prev, &task->list);
|
||||
}
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
if (res) {
|
||||
list_splice_init(&q, &core->task_queue); /*at head*/
|
||||
core->task_queue_size += can_queue;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
mutex_unlock(&core->task_queue_flush);
|
||||
}
|
||||
|
||||
/**
|
||||
* sas_queue_thread -- The Task Collector thread
|
||||
* @_sas_ha: pointer to struct sas_ha
|
||||
*/
|
||||
static int sas_queue_thread(void *_sas_ha)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = _sas_ha;
|
||||
|
||||
while (1) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
sas_queue(sas_ha);
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sas_init_queue(struct sas_ha_struct *sas_ha)
|
||||
{
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
|
||||
spin_lock_init(&core->task_queue_lock);
|
||||
mutex_init(&core->task_queue_flush);
|
||||
core->task_queue_size = 0;
|
||||
INIT_LIST_HEAD(&core->task_queue);
|
||||
|
||||
core->queue_thread = kthread_run(sas_queue_thread, sas_ha,
|
||||
"sas_queue_%d", core->shost->host_no);
|
||||
if (IS_ERR(core->queue_thread))
|
||||
return PTR_ERR(core->queue_thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
struct sas_task *task, *n;
|
||||
|
||||
kthread_stop(core->queue_thread);
|
||||
|
||||
if (!list_empty(&core->task_queue))
|
||||
SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n",
|
||||
SAS_ADDR(sas_ha->sas_addr));
|
||||
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
list_for_each_entry_safe(task, n, &core->task_queue, list) {
|
||||
struct scsi_cmnd *cmd = task->uldd_task;
|
||||
|
||||
list_del_init(&task->list);
|
||||
|
||||
ASSIGN_SAS_TASK(cmd, NULL);
|
||||
sas_free_task(task);
|
||||
cmd->result = DID_ABORT << 16;
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell an upper layer that it needs to initiate an abort for a given task.
|
||||
* This should only ever be called by an LLDD.
|
||||
|
|
|
|||
|
|
@ -242,108 +242,6 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
|||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event
|
||||
* @phba: Pointer to HBA context object.
|
||||
* @vport: Pointer to vport object.
|
||||
* @ndlp: Pointer to FC node associated with the target.
|
||||
* @lun: Lun number of the scsi device.
|
||||
* @old_val: Old value of the queue depth.
|
||||
* @new_val: New value of the queue depth.
|
||||
*
|
||||
* This function sends an event to the mgmt application indicating
|
||||
* there is a change in the scsi device queue depth.
|
||||
**/
|
||||
static void
|
||||
lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
|
||||
struct lpfc_vport *vport,
|
||||
struct lpfc_nodelist *ndlp,
|
||||
uint64_t lun,
|
||||
uint32_t old_val,
|
||||
uint32_t new_val)
|
||||
{
|
||||
struct lpfc_fast_path_event *fast_path_evt;
|
||||
unsigned long flags;
|
||||
|
||||
fast_path_evt = lpfc_alloc_fast_evt(phba);
|
||||
if (!fast_path_evt)
|
||||
return;
|
||||
|
||||
fast_path_evt->un.queue_depth_evt.scsi_event.event_type =
|
||||
FC_REG_SCSI_EVENT;
|
||||
fast_path_evt->un.queue_depth_evt.scsi_event.subcategory =
|
||||
LPFC_EVENT_VARQUEDEPTH;
|
||||
|
||||
/* Report all luns with change in queue depth */
|
||||
fast_path_evt->un.queue_depth_evt.scsi_event.lun = lun;
|
||||
if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
|
||||
memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwpn,
|
||||
&ndlp->nlp_portname, sizeof(struct lpfc_name));
|
||||
memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwnn,
|
||||
&ndlp->nlp_nodename, sizeof(struct lpfc_name));
|
||||
}
|
||||
|
||||
fast_path_evt->un.queue_depth_evt.oldval = old_val;
|
||||
fast_path_evt->un.queue_depth_evt.newval = new_val;
|
||||
fast_path_evt->vport = vport;
|
||||
|
||||
fast_path_evt->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
|
||||
spin_lock_irqsave(&phba->hbalock, flags);
|
||||
list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
|
||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||
lpfc_worker_wake_up(phba);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_change_queue_depth - Alter scsi device queue depth
|
||||
* @sdev: Pointer the scsi device on which to change the queue depth.
|
||||
* @qdepth: New queue depth to set the sdev to.
|
||||
* @reason: The reason for the queue depth change.
|
||||
*
|
||||
* This function is called by the midlayer and the LLD to alter the queue
|
||||
* depth for a scsi device. This function sets the queue depth to the new
|
||||
* value and sends an event out to log the queue depth change.
|
||||
**/
|
||||
static int
|
||||
lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
||||
{
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_rport_data *rdata;
|
||||
unsigned long new_queue_depth, old_queue_depth;
|
||||
|
||||
old_queue_depth = sdev->queue_depth;
|
||||
|
||||
switch (reason) {
|
||||
case SCSI_QDEPTH_DEFAULT:
|
||||
/* change request from sysfs, fall through */
|
||||
case SCSI_QDEPTH_RAMP_UP:
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
break;
|
||||
case SCSI_QDEPTH_QFULL:
|
||||
if (scsi_track_queue_full(sdev, qdepth) == 0)
|
||||
return sdev->queue_depth;
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
|
||||
"0711 detected queue full - lun queue "
|
||||
"depth adjusted to %d.\n", sdev->queue_depth);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
new_queue_depth = sdev->queue_depth;
|
||||
rdata = lpfc_rport_data_from_scsi_device(sdev);
|
||||
if (rdata)
|
||||
lpfc_send_sdev_queuedepth_change_event(phba, vport,
|
||||
rdata->pnode, sdev->lun,
|
||||
old_queue_depth,
|
||||
new_queue_depth);
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
|
|
@ -429,8 +327,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
|
|||
else
|
||||
new_queue_depth = sdev->queue_depth -
|
||||
new_queue_depth;
|
||||
lpfc_change_queue_depth(sdev, new_queue_depth,
|
||||
SCSI_QDEPTH_DEFAULT);
|
||||
scsi_change_queue_depth(sdev, new_queue_depth);
|
||||
}
|
||||
}
|
||||
lpfc_destroy_vport_work_array(phba, vports);
|
||||
|
|
@ -5598,7 +5495,7 @@ lpfc_slave_configure(struct scsi_device *sdev)
|
|||
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, vport->cfg_lun_queue_depth);
|
||||
scsi_change_queue_depth(sdev, vport->cfg_lun_queue_depth);
|
||||
|
||||
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
|
||||
lpfc_sli_handle_fast_ring_event(phba,
|
||||
|
|
@ -5981,9 +5878,10 @@ struct scsi_host_template lpfc_template = {
|
|||
.shost_attrs = lpfc_hba_attrs,
|
||||
.max_sectors = 0xFFFF,
|
||||
.vendor_id = LPFC_NL_VENDOR_ID,
|
||||
.change_queue_depth = lpfc_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
struct scsi_host_template lpfc_vport_template = {
|
||||
|
|
@ -6005,7 +5903,8 @@ struct scsi_host_template lpfc_vport_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = lpfc_vport_attrs,
|
||||
.max_sectors = 0xFFFF,
|
||||
.change_queue_depth = lpfc_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,69 +9,62 @@
|
|||
* Generic Generic NCR5380 driver
|
||||
*
|
||||
* Copyright 1995, Russell King
|
||||
*
|
||||
* ALPHA RELEASE 1.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/hwtest.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/macintosh.h>
|
||||
#include <asm/macints.h>
|
||||
#include <asm/mac_via.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "mac_scsi.h"
|
||||
|
||||
/* These control the behaviour of the generic 5380 core */
|
||||
#define AUTOSENSE
|
||||
/* Definitions for the core NCR5380 driver. */
|
||||
|
||||
#define PSEUDO_DMA
|
||||
|
||||
#define NCR5380_implementation_fields unsigned char *pdma_base
|
||||
#define NCR5380_local_declare() struct Scsi_Host *_instance
|
||||
#define NCR5380_setup(instance) _instance = instance
|
||||
|
||||
#define NCR5380_read(reg) macscsi_read(_instance, reg)
|
||||
#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
|
||||
|
||||
#define NCR5380_pread macscsi_pread
|
||||
#define NCR5380_pwrite macscsi_pwrite
|
||||
|
||||
#define NCR5380_intr macscsi_intr
|
||||
#define NCR5380_queue_command macscsi_queue_command
|
||||
#define NCR5380_abort macscsi_abort
|
||||
#define NCR5380_bus_reset macscsi_bus_reset
|
||||
#define NCR5380_info macscsi_info
|
||||
#define NCR5380_show_info macscsi_show_info
|
||||
#define NCR5380_write_info macscsi_write_info
|
||||
|
||||
#include "NCR5380.h"
|
||||
|
||||
#define RESET_BOOT
|
||||
#define DRIVER_SETUP
|
||||
|
||||
extern void via_scsi_clear(void);
|
||||
|
||||
#ifdef RESET_BOOT
|
||||
static void mac_scsi_reset_boot(struct Scsi_Host *instance);
|
||||
#endif
|
||||
|
||||
static int setup_called = 0;
|
||||
static int setup_can_queue = -1;
|
||||
module_param(setup_can_queue, int, 0);
|
||||
static int setup_cmd_per_lun = -1;
|
||||
module_param(setup_cmd_per_lun, int, 0);
|
||||
static int setup_sg_tablesize = -1;
|
||||
module_param(setup_sg_tablesize, int, 0);
|
||||
static int setup_use_pdma = -1;
|
||||
#ifdef SUPPORT_TAGS
|
||||
module_param(setup_use_pdma, int, 0);
|
||||
static int setup_use_tagged_queuing = -1;
|
||||
#endif
|
||||
module_param(setup_use_tagged_queuing, int, 0);
|
||||
static int setup_hostid = -1;
|
||||
module_param(setup_hostid, int, 0);
|
||||
|
||||
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
|
||||
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
|
||||
|
|
@ -84,232 +77,48 @@ static int setup_hostid = -1;
|
|||
#define AFTER_RESET_DELAY (HZ/2)
|
||||
#endif
|
||||
|
||||
static volatile unsigned char *mac_scsi_regp = NULL;
|
||||
static volatile unsigned char *mac_scsi_drq = NULL;
|
||||
static volatile unsigned char *mac_scsi_nodrq = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* NCR 5380 register access functions
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* Debug versions */
|
||||
#define CTRL(p,v) (*ctrl = (v))
|
||||
|
||||
static char macscsi_read(struct Scsi_Host *instance, int reg)
|
||||
static inline char macscsi_read(struct Scsi_Host *instance, int reg)
|
||||
{
|
||||
int iobase = instance->io_port;
|
||||
int i;
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
|
||||
CTRL(iobase, 0);
|
||||
i = in_8(iobase + (reg<<4));
|
||||
CTRL(iobase, 0x40);
|
||||
|
||||
return i;
|
||||
return in_8(instance->base + (reg << 4));
|
||||
}
|
||||
|
||||
static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
|
||||
static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value)
|
||||
{
|
||||
int iobase = instance->io_port;
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
|
||||
CTRL(iobase, 0);
|
||||
out_8(iobase + (reg<<4), value);
|
||||
CTRL(iobase, 0x40);
|
||||
}
|
||||
#else
|
||||
|
||||
/* Fast versions */
|
||||
static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
|
||||
{
|
||||
return in_8(instance->io_port + (reg<<4));
|
||||
out_8(instance->base + (reg << 4), value);
|
||||
}
|
||||
|
||||
static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
|
||||
#ifndef MODULE
|
||||
static int __init mac_scsi_setup(char *str)
|
||||
{
|
||||
out_8(instance->io_port + (reg<<4), value);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Function : mac_scsi_setup(char *str)
|
||||
*
|
||||
* Purpose : booter command line initialization of the overrides array,
|
||||
*
|
||||
* Inputs : str - comma delimited list of options
|
||||
*
|
||||
*/
|
||||
|
||||
static int __init mac_scsi_setup(char *str) {
|
||||
#ifdef DRIVER_SETUP
|
||||
int ints[7];
|
||||
|
||||
(void)get_options( str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
|
||||
printk(KERN_WARNING "scsi: <mac5380>"
|
||||
" Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
|
||||
printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
|
||||
return 0;
|
||||
|
||||
(void)get_options(str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
if (ints[0] < 1 || ints[0] > 6) {
|
||||
pr_err("Usage: mac5380=<can_queue>[,<cmd_per_lun>[,<sg_tablesize>[,<hostid>[,<use_tags>[,<use_pdma>]]]]]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ints[0] >= 1) {
|
||||
if (ints[1] > 0)
|
||||
/* no limits on this, just > 0 */
|
||||
setup_can_queue = ints[1];
|
||||
}
|
||||
if (ints[0] >= 2) {
|
||||
if (ints[2] > 0)
|
||||
setup_cmd_per_lun = ints[2];
|
||||
}
|
||||
if (ints[0] >= 3) {
|
||||
if (ints[3] >= 0) {
|
||||
setup_sg_tablesize = ints[3];
|
||||
/* Must be <= SG_ALL (255) */
|
||||
if (setup_sg_tablesize > SG_ALL)
|
||||
setup_sg_tablesize = SG_ALL;
|
||||
}
|
||||
}
|
||||
if (ints[0] >= 4) {
|
||||
/* Must be between 0 and 7 */
|
||||
if (ints[4] >= 0 && ints[4] <= 7)
|
||||
setup_hostid = ints[4];
|
||||
else if (ints[4] > 7)
|
||||
printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
|
||||
}
|
||||
#ifdef SUPPORT_TAGS
|
||||
if (ints[0] >= 5) {
|
||||
if (ints[5] >= 0)
|
||||
setup_use_tagged_queuing = !!ints[5];
|
||||
}
|
||||
|
||||
if (ints[0] == 6) {
|
||||
if (ints[6] >= 0)
|
||||
if (ints[0] >= 1)
|
||||
setup_can_queue = ints[1];
|
||||
if (ints[0] >= 2)
|
||||
setup_cmd_per_lun = ints[2];
|
||||
if (ints[0] >= 3)
|
||||
setup_sg_tablesize = ints[3];
|
||||
if (ints[0] >= 4)
|
||||
setup_hostid = ints[4];
|
||||
if (ints[0] >= 5)
|
||||
setup_use_tagged_queuing = ints[5];
|
||||
if (ints[0] >= 6)
|
||||
setup_use_pdma = ints[6];
|
||||
}
|
||||
#else
|
||||
if (ints[0] == 5) {
|
||||
if (ints[5] >= 0)
|
||||
setup_use_pdma = ints[5];
|
||||
}
|
||||
#endif /* SUPPORT_TAGS */
|
||||
|
||||
#endif /* DRIVER_SETUP */
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("mac5380=", mac_scsi_setup);
|
||||
|
||||
/*
|
||||
* Function : int macscsi_detect(struct scsi_host_template * tpnt)
|
||||
*
|
||||
* Purpose : initializes mac NCR5380 driver based on the
|
||||
* command line / compile time port and irq definitions.
|
||||
*
|
||||
* Inputs : tpnt - template for this SCSI adapter.
|
||||
*
|
||||
* Returns : 1 if a host adapter was found, 0 if not.
|
||||
*
|
||||
*/
|
||||
|
||||
int __init macscsi_detect(struct scsi_host_template * tpnt)
|
||||
{
|
||||
static int called = 0;
|
||||
int flags = 0;
|
||||
struct Scsi_Host *instance;
|
||||
|
||||
if (!MACH_IS_MAC || called)
|
||||
return( 0 );
|
||||
|
||||
if (macintosh_config->scsi_type != MAC_SCSI_OLD)
|
||||
return( 0 );
|
||||
|
||||
/* setup variables */
|
||||
tpnt->can_queue =
|
||||
(setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
|
||||
tpnt->cmd_per_lun =
|
||||
(setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
|
||||
tpnt->sg_tablesize =
|
||||
(setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
|
||||
|
||||
if (setup_hostid >= 0)
|
||||
tpnt->this_id = setup_hostid;
|
||||
else {
|
||||
/* use 7 as default */
|
||||
tpnt->this_id = 7;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
if (setup_use_tagged_queuing < 0)
|
||||
setup_use_tagged_queuing = USE_TAGGED_QUEUING;
|
||||
#endif
|
||||
|
||||
/* Once we support multiple 5380s (e.g. DuoDock) we'll do
|
||||
something different here */
|
||||
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if (instance == NULL)
|
||||
return 0;
|
||||
|
||||
if (macintosh_config->ident == MAC_MODEL_IIFX) {
|
||||
mac_scsi_regp = via1+0x8000;
|
||||
mac_scsi_drq = via1+0xE000;
|
||||
mac_scsi_nodrq = via1+0xC000;
|
||||
/* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
|
||||
flags = FLAG_NO_PSEUDO_DMA;
|
||||
} else {
|
||||
mac_scsi_regp = via1+0x10000;
|
||||
mac_scsi_drq = via1+0x6000;
|
||||
mac_scsi_nodrq = via1+0x12000;
|
||||
}
|
||||
|
||||
if (! setup_use_pdma)
|
||||
flags = FLAG_NO_PSEUDO_DMA;
|
||||
|
||||
instance->io_port = (unsigned long) mac_scsi_regp;
|
||||
instance->irq = IRQ_MAC_SCSI;
|
||||
|
||||
#ifdef RESET_BOOT
|
||||
mac_scsi_reset_boot(instance);
|
||||
#endif
|
||||
|
||||
NCR5380_init(instance, flags);
|
||||
|
||||
instance->n_io_port = 255;
|
||||
|
||||
((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
|
||||
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
if (request_irq(instance->irq, NCR5380_intr, 0, "ncr5380", instance)) {
|
||||
printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
|
||||
instance->host_no, instance->irq);
|
||||
instance->irq = SCSI_IRQ_NONE;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
printk (KERN_INFO "s disabled");
|
||||
else
|
||||
printk (KERN_INFO " %d", instance->irq);
|
||||
printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
|
||||
instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
|
||||
printk(KERN_INFO "\nscsi%d:", instance->host_no);
|
||||
NCR5380_print_options(instance);
|
||||
printk("\n");
|
||||
called = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int macscsi_release (struct Scsi_Host *shpnt)
|
||||
{
|
||||
if (shpnt->irq != SCSI_IRQ_NONE)
|
||||
free_irq(shpnt->irq, shpnt);
|
||||
NCR5380_exit(shpnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !MODULE */
|
||||
|
||||
#ifdef RESET_BOOT
|
||||
/*
|
||||
|
|
@ -349,10 +158,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
|
|||
}
|
||||
#endif
|
||||
|
||||
const char * macscsi_info (struct Scsi_Host *spnt) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef PSEUDO_DMA
|
||||
/*
|
||||
Pseudo-DMA: (Ove Edlund)
|
||||
The code attempts to catch bus errors that occur if one for example
|
||||
|
|
@ -422,38 +228,39 @@ __asm__ __volatile__ \
|
|||
: "0"(s), "1"(d), "2"(len) \
|
||||
: "d0")
|
||||
|
||||
|
||||
static int macscsi_pread (struct Scsi_Host *instance,
|
||||
unsigned char *dst, int len)
|
||||
static int macscsi_pread(struct Scsi_Host *instance,
|
||||
unsigned char *dst, int len)
|
||||
{
|
||||
unsigned char *d;
|
||||
volatile unsigned char *s;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
unsigned char *d;
|
||||
unsigned char *s;
|
||||
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
s = mac_scsi_drq+0x60;
|
||||
d = dst;
|
||||
s = hostdata->pdma_base + (INPUT_DATA_REG << 4);
|
||||
d = dst;
|
||||
|
||||
/* These conditions are derived from MacOS */
|
||||
/* These conditions are derived from MacOS */
|
||||
|
||||
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
|
||||
&& !(NCR5380_read(STATUS_REG) & SR_REQ))
|
||||
;
|
||||
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
|
||||
&& (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
|
||||
printk(KERN_ERR "Error in macscsi_pread\n");
|
||||
return -1;
|
||||
}
|
||||
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
|
||||
!(NCR5380_read(STATUS_REG) & SR_REQ))
|
||||
;
|
||||
|
||||
CP_IO_TO_MEM(s, d, len);
|
||||
|
||||
if (len != 0) {
|
||||
printk(KERN_NOTICE "Bus error in macscsi_pread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
|
||||
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
|
||||
pr_err("Error in macscsi_pread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CP_IO_TO_MEM(s, d, len);
|
||||
|
||||
if (len != 0) {
|
||||
pr_notice("Bus error in macscsi_pread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -515,59 +322,172 @@ __asm__ __volatile__ \
|
|||
: "0"(s), "1"(d), "2"(len) \
|
||||
: "d0")
|
||||
|
||||
static int macscsi_pwrite (struct Scsi_Host *instance,
|
||||
unsigned char *src, int len)
|
||||
static int macscsi_pwrite(struct Scsi_Host *instance,
|
||||
unsigned char *src, int len)
|
||||
{
|
||||
unsigned char *s;
|
||||
volatile unsigned char *d;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
unsigned char *s;
|
||||
unsigned char *d;
|
||||
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
s = src;
|
||||
d = mac_scsi_drq;
|
||||
|
||||
/* These conditions are derived from MacOS */
|
||||
s = src;
|
||||
d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4);
|
||||
|
||||
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
|
||||
&& (!(NCR5380_read(STATUS_REG) & SR_REQ)
|
||||
|| (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
|
||||
;
|
||||
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
|
||||
printk(KERN_ERR "Error in macscsi_pwrite\n");
|
||||
return -1;
|
||||
}
|
||||
/* These conditions are derived from MacOS */
|
||||
|
||||
CP_MEM_TO_IO(s, d, len);
|
||||
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
|
||||
(!(NCR5380_read(STATUS_REG) & SR_REQ) ||
|
||||
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
|
||||
;
|
||||
|
||||
if (len != 0) {
|
||||
printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
|
||||
pr_err("Error in macscsi_pwrite\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CP_MEM_TO_IO(s, d, len);
|
||||
|
||||
if (len != 0) {
|
||||
pr_notice("Bus error in macscsi_pwrite\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include "NCR5380.c"
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "Mac5380",
|
||||
#define DRV_MODULE_NAME "mac_scsi"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
|
||||
static struct scsi_host_template mac_scsi_template = {
|
||||
.module = THIS_MODULE,
|
||||
.proc_name = DRV_MODULE_NAME,
|
||||
.show_info = macscsi_show_info,
|
||||
.write_info = macscsi_write_info,
|
||||
.name = "Macintosh NCR5380 SCSI",
|
||||
.detect = macscsi_detect,
|
||||
.release = macscsi_release,
|
||||
.info = macscsi_info,
|
||||
.queuecommand = macscsi_queue_command,
|
||||
.eh_abort_handler = macscsi_abort,
|
||||
.eh_bus_reset_handler = macscsi_bus_reset,
|
||||
.can_queue = CAN_QUEUE,
|
||||
.can_queue = 16,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = CMD_PER_LUN,
|
||||
.cmd_per_lun = 2,
|
||||
.use_clustering = DISABLE_CLUSTERING
|
||||
};
|
||||
|
||||
static int __init mac_scsi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance;
|
||||
int error;
|
||||
int host_flags = 0;
|
||||
struct resource *irq, *pio_mem, *pdma_mem = NULL;
|
||||
|
||||
#include "scsi_module.c"
|
||||
pio_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!pio_mem)
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef PSEUDO_DMA
|
||||
pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
#endif
|
||||
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
|
||||
if (!hwreg_present((unsigned char *)pio_mem->start +
|
||||
(STATUS_REG << 4))) {
|
||||
pr_info(PFX "no device detected at %pap\n", &pio_mem->start);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (setup_can_queue > 0)
|
||||
mac_scsi_template.can_queue = setup_can_queue;
|
||||
if (setup_cmd_per_lun > 0)
|
||||
mac_scsi_template.cmd_per_lun = setup_cmd_per_lun;
|
||||
if (setup_sg_tablesize >= 0)
|
||||
mac_scsi_template.sg_tablesize = setup_sg_tablesize;
|
||||
if (setup_hostid >= 0)
|
||||
mac_scsi_template.this_id = setup_hostid & 7;
|
||||
if (setup_use_pdma < 0)
|
||||
setup_use_pdma = 0;
|
||||
|
||||
instance = scsi_host_alloc(&mac_scsi_template,
|
||||
sizeof(struct NCR5380_hostdata));
|
||||
if (!instance)
|
||||
return -ENOMEM;
|
||||
|
||||
instance->base = pio_mem->start;
|
||||
if (irq)
|
||||
instance->irq = irq->start;
|
||||
else
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
if (pdma_mem && setup_use_pdma) {
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
hostdata->pdma_base = (unsigned char *)pdma_mem->start;
|
||||
} else
|
||||
host_flags |= FLAG_NO_PSEUDO_DMA;
|
||||
|
||||
#ifdef RESET_BOOT
|
||||
mac_scsi_reset_boot(instance);
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
|
||||
#endif
|
||||
|
||||
NCR5380_init(instance, host_flags);
|
||||
|
||||
if (instance->irq != NO_IRQ) {
|
||||
error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED,
|
||||
"NCR5380", instance);
|
||||
if (error)
|
||||
goto fail_irq;
|
||||
}
|
||||
|
||||
error = scsi_add_host(instance, NULL);
|
||||
if (error)
|
||||
goto fail_host;
|
||||
|
||||
platform_set_drvdata(pdev, instance);
|
||||
|
||||
scsi_scan_host(instance);
|
||||
return 0;
|
||||
|
||||
fail_host:
|
||||
if (instance->irq != NO_IRQ)
|
||||
free_irq(instance->irq, instance);
|
||||
fail_irq:
|
||||
NCR5380_exit(instance);
|
||||
scsi_host_put(instance);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __exit mac_scsi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct Scsi_Host *instance = platform_get_drvdata(pdev);
|
||||
|
||||
scsi_remove_host(instance);
|
||||
if (instance->irq != NO_IRQ)
|
||||
free_irq(instance->irq, instance);
|
||||
NCR5380_exit(instance);
|
||||
scsi_host_put(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mac_scsi_driver = {
|
||||
.remove = __exit_p(mac_scsi_remove),
|
||||
.driver = {
|
||||
.name = DRV_MODULE_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(mac_scsi_driver, mac_scsi_probe);
|
||||
|
||||
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Cumana Generic NCR5380 driver defines
|
||||
*
|
||||
* Copyright 1993, Drew Eckhardt
|
||||
* Visionary Computing
|
||||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 440-4894
|
||||
*
|
||||
* ALPHA RELEASE 1.
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
#ifndef MAC_NCR5380_H
|
||||
#define MAC_NCR5380_H
|
||||
|
||||
#define MACSCSI_PUBLIC_RELEASE 2
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
#ifndef CMD_PER_LUN
|
||||
#define CMD_PER_LUN 2
|
||||
#endif
|
||||
|
||||
#ifndef CAN_QUEUE
|
||||
#define CAN_QUEUE 16
|
||||
#endif
|
||||
|
||||
#ifndef SG_TABLESIZE
|
||||
#define SG_TABLESIZE SG_NONE
|
||||
#endif
|
||||
|
||||
#ifndef USE_TAGGED_QUEUING
|
||||
#define USE_TAGGED_QUEUING 0
|
||||
#endif
|
||||
|
||||
#include <scsi/scsicam.h>
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
int port, ctrl
|
||||
|
||||
#define NCR5380_local_declare() \
|
||||
struct Scsi_Host *_instance
|
||||
|
||||
#define NCR5380_setup(instance) \
|
||||
_instance = instance
|
||||
|
||||
#define NCR5380_read(reg) macscsi_read(_instance, reg)
|
||||
#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
|
||||
|
||||
#define NCR5380_pread macscsi_pread
|
||||
#define NCR5380_pwrite macscsi_pwrite
|
||||
|
||||
#define NCR5380_intr macscsi_intr
|
||||
#define NCR5380_queue_command macscsi_queue_command
|
||||
#define NCR5380_abort macscsi_abort
|
||||
#define NCR5380_bus_reset macscsi_bus_reset
|
||||
#define NCR5380_show_info macscsi_show_info
|
||||
#define NCR5380_write_info macscsi_write_info
|
||||
|
||||
#endif /* ndef ASM */
|
||||
#endif /* MAC_NCR5380_H */
|
||||
|
||||
|
|
@ -332,27 +332,6 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* megaraid_change_queue_depth - Change the device's queue depth
|
||||
* @sdev: scsi device struct
|
||||
* @qdepth: depth to set
|
||||
* @reason: calling context
|
||||
*
|
||||
* Return value:
|
||||
* actual depth set
|
||||
*/
|
||||
static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (qdepth > MBOX_MAX_SCSI_CMDS)
|
||||
qdepth = MBOX_MAX_SCSI_CMDS;
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scsi host template for megaraid unified driver
|
||||
*/
|
||||
|
|
@ -365,7 +344,7 @@ static struct scsi_host_template megaraid_template_g = {
|
|||
.eh_device_reset_handler = megaraid_reset_handler,
|
||||
.eh_bus_reset_handler = megaraid_reset_handler,
|
||||
.eh_host_reset_handler = megaraid_reset_handler,
|
||||
.change_queue_depth = megaraid_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.no_write_same = 1,
|
||||
.sdev_attrs = megaraid_sdev_attrs,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Linux MegaRAID driver for SAS based RAID controllers
|
||||
*
|
||||
* Copyright (c) 2003-2012 LSI Corporation.
|
||||
* Copyright (c) 2003-2013 LSI Corporation
|
||||
* Copyright (c) 2013-2014 Avago Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
|
@ -14,17 +15,18 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* FILE: megaraid_sas.h
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Authors: Avago Technologies
|
||||
* Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
* Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
*
|
||||
* Send feedback to: <megaraidlinux@lsi.com>
|
||||
* Send feedback to: megaraidlinux.pdl@avagotech.com
|
||||
*
|
||||
* Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
|
||||
* ATTN: Linuxraid
|
||||
* Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
|
||||
* San Jose, California 95131
|
||||
*/
|
||||
|
||||
#ifndef LSI_MEGARAID_SAS_H
|
||||
|
|
@ -33,9 +35,7 @@
|
|||
/*
|
||||
* MegaRAID SAS Driver meta data
|
||||
*/
|
||||
#define MEGASAS_VERSION "06.805.06.00-rc1"
|
||||
#define MEGASAS_RELDATE "Sep. 4, 2014"
|
||||
#define MEGASAS_EXT_VERSION "Thu. Sep. 4 17:00:00 PDT 2014"
|
||||
#define MEGASAS_VERSION "06.805.06.01-rc1"
|
||||
|
||||
/*
|
||||
* Device IDs
|
||||
|
|
@ -1931,8 +1931,7 @@ u16 get_updated_dev_handle(struct megasas_instance *instance,
|
|||
struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info);
|
||||
void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
|
||||
struct LD_LOAD_BALANCE_INFO *lbInfo);
|
||||
int megasas_get_ctrl_info(struct megasas_instance *instance,
|
||||
struct megasas_ctrl_info *ctrl_info);
|
||||
int megasas_get_ctrl_info(struct megasas_instance *instance);
|
||||
int megasas_set_crash_dump_params(struct megasas_instance *instance,
|
||||
u8 crash_buf_state);
|
||||
void megasas_free_host_crash_buffer(struct megasas_instance *instance);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Linux MegaRAID driver for SAS based RAID controllers
|
||||
*
|
||||
* Copyright (c) 2003-2012 LSI Corporation.
|
||||
* Copyright (c) 2003-2013 LSI Corporation
|
||||
* Copyright (c) 2013-2014 Avago Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
|
@ -14,22 +15,20 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* FILE: megaraid_sas_base.c
|
||||
* Version : 06.805.06.00-rc1
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Authors: Avago Technologies
|
||||
* Sreenivas Bagalkote
|
||||
* Sumant Patro
|
||||
* Bo Yang
|
||||
* Adam Radford <linuxraid@lsi.com>
|
||||
* Adam Radford
|
||||
* Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
* Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
*
|
||||
* Send feedback to: <megaraidlinux@lsi.com>
|
||||
* Send feedback to: megaraidlinux.pdl@avagotech.com
|
||||
*
|
||||
* Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
|
||||
* ATTN: Linuxraid
|
||||
* Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
|
||||
* San Jose, California 95131
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -1008,7 +1007,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
|
|||
cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
|
||||
|
||||
cmd->sync_cmd = 1;
|
||||
cmd->cmd_status = 0xFF;
|
||||
cmd->cmd_status = ENODATA;
|
||||
|
||||
instance->instancet->issue_dcmd(instance, cmd);
|
||||
|
||||
|
|
@ -1572,6 +1571,12 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
|||
instance = (struct megasas_instance *)
|
||||
scmd->device->host->hostdata;
|
||||
|
||||
if (instance->unload == 1) {
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
scmd->scsi_done(scmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (instance->issuepend_done == 0)
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
|
|
@ -2586,19 +2591,6 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
static int megasas_change_queue_depth(struct scsi_device *sdev,
|
||||
int queue_depth, int reason)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (queue_depth > sdev->host->can_queue)
|
||||
queue_depth = sdev->host->can_queue;
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
|
||||
return queue_depth;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
megasas_fw_crash_buffer_store(struct device *cdev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
|
|
@ -2763,7 +2755,7 @@ static struct scsi_host_template megasas_template = {
|
|||
.shost_attrs = megaraid_host_attrs,
|
||||
.bios_param = megasas_bios_param,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.change_queue_depth = megasas_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.no_write_same = 1,
|
||||
};
|
||||
|
||||
|
|
@ -4027,25 +4019,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* megasas_update_ext_vd_details : Update details w.r.t Extended VD
|
||||
* instance : Controller's instance
|
||||
*/
|
||||
static void megasas_update_ext_vd_details(struct megasas_instance *instance)
|
||||
{
|
||||
struct fusion_context *fusion;
|
||||
u32 old_map_sz;
|
||||
u32 new_map_sz;
|
||||
|
||||
fusion = instance->ctrl_context;
|
||||
/* For MFI based controllers return dummy success */
|
||||
if (!fusion)
|
||||
return;
|
||||
|
||||
instance->supportmax256vd =
|
||||
instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
|
||||
/* Below is additional check to address future FW enhancement */
|
||||
if (instance->ctrl_info->max_lds > 64)
|
||||
instance->supportmax256vd = 1;
|
||||
|
||||
instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
|
||||
* MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
|
||||
* MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
if (instance->supportmax256vd) {
|
||||
instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
|
||||
instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
|
||||
} else {
|
||||
instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
|
||||
instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
|
||||
}
|
||||
dev_info(&instance->pdev->dev, "Firmware supports %d VD %d PD\n",
|
||||
instance->fw_supported_vd_count,
|
||||
instance->fw_supported_pd_count);
|
||||
dev_info(&instance->pdev->dev, "Driver supports %d VD %d PD\n",
|
||||
instance->drv_supported_vd_count,
|
||||
instance->drv_supported_pd_count);
|
||||
|
||||
old_map_sz = sizeof(struct MR_FW_RAID_MAP) +
|
||||
(sizeof(struct MR_LD_SPAN_MAP) *
|
||||
(instance->fw_supported_vd_count - 1));
|
||||
new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT);
|
||||
fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP) +
|
||||
(sizeof(struct MR_LD_SPAN_MAP) *
|
||||
(instance->drv_supported_vd_count - 1));
|
||||
|
||||
fusion->max_map_sz = max(old_map_sz, new_map_sz);
|
||||
|
||||
|
||||
if (instance->supportmax256vd)
|
||||
fusion->current_map_sz = new_map_sz;
|
||||
else
|
||||
fusion->current_map_sz = old_map_sz;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_get_controller_info - Returns FW's controller structure
|
||||
* @instance: Adapter soft state
|
||||
* @ctrl_info: Controller information structure
|
||||
*
|
||||
* Issues an internal command (DCMD) to get the FW's controller structure.
|
||||
* This information is mainly used to find out the maximum IO transfer per
|
||||
* command supported by the FW.
|
||||
*/
|
||||
int
|
||||
megasas_get_ctrl_info(struct megasas_instance *instance,
|
||||
struct megasas_ctrl_info *ctrl_info)
|
||||
megasas_get_ctrl_info(struct megasas_instance *instance)
|
||||
{
|
||||
int ret = 0;
|
||||
struct megasas_cmd *cmd;
|
||||
struct megasas_dcmd_frame *dcmd;
|
||||
struct megasas_ctrl_info *ci;
|
||||
struct megasas_ctrl_info *ctrl_info;
|
||||
dma_addr_t ci_h = 0;
|
||||
|
||||
ctrl_info = instance->ctrl_info;
|
||||
|
||||
cmd = megasas_get_cmd(instance);
|
||||
|
||||
if (!cmd) {
|
||||
|
|
@ -4085,8 +4135,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
|
|||
else
|
||||
ret = megasas_issue_polled(instance, cmd);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
|
||||
le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
|
||||
le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
|
||||
le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
|
||||
megasas_update_ext_vd_details(instance);
|
||||
}
|
||||
|
||||
pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
|
||||
ci, ci_h);
|
||||
|
|
@ -4288,7 +4343,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
|
|||
if (megasas_issue_init_mfi(instance))
|
||||
goto fail_fw_init;
|
||||
|
||||
if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
|
||||
if (megasas_get_ctrl_info(instance)) {
|
||||
dev_err(&instance->pdev->dev, "(%d): Could get controller info "
|
||||
"Fail from %s %d\n", instance->unique_id,
|
||||
__func__, __LINE__);
|
||||
|
|
@ -4526,12 +4581,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
dev_info(&instance->pdev->dev,
|
||||
"Controller type: iMR\n");
|
||||
}
|
||||
/* OnOffProperties are converted into CPU arch*/
|
||||
le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
|
||||
instance->disableOnlineCtrlReset =
|
||||
ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
|
||||
/* adapterOperations2 are converted into CPU arch*/
|
||||
le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
|
||||
instance->mpio = ctrl_info->adapterOperations2.mpio;
|
||||
instance->UnevenSpanSupport =
|
||||
ctrl_info->adapterOperations2.supportUnevenSpans;
|
||||
|
|
@ -4561,7 +4612,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
"requestorId %d\n", instance->requestorId);
|
||||
}
|
||||
|
||||
le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
|
||||
instance->crash_dump_fw_support =
|
||||
ctrl_info->adapterOperations3.supportCrashDump;
|
||||
instance->crash_dump_drv_support =
|
||||
|
|
@ -4586,8 +4636,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
|
||||
instance->max_sectors_per_req = tmp_sectors;
|
||||
|
||||
kfree(ctrl_info);
|
||||
|
||||
/* Check for valid throttlequeuedepth module parameter */
|
||||
if (instance->is_imr) {
|
||||
if (throttlequeuedepth > (instance->max_fw_cmds -
|
||||
|
|
@ -4956,10 +5004,6 @@ static int megasas_io_attach(struct megasas_instance *instance)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger SCSI to scan our drives
|
||||
*/
|
||||
scsi_scan_host(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5082,6 +5126,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|||
goto fail_alloc_dma_buf;
|
||||
}
|
||||
fusion = instance->ctrl_context;
|
||||
memset(fusion, 0,
|
||||
((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
|
||||
INIT_LIST_HEAD(&fusion->cmd_pool);
|
||||
spin_lock_init(&fusion->mpt_pool_lock);
|
||||
memset(fusion->load_balance_info, 0,
|
||||
|
|
@ -5287,6 +5333,10 @@ retry_irq_register:
|
|||
goto fail_io_attach;
|
||||
|
||||
instance->unload = 0;
|
||||
/*
|
||||
* Trigger SCSI to scan our drives
|
||||
*/
|
||||
scsi_scan_host(host);
|
||||
|
||||
/*
|
||||
* Initiate AEN (Asynchronous Event Notification)
|
||||
|
|
@ -6050,6 +6100,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
|
|||
megasas_issue_blocked_cmd(instance, cmd, 0);
|
||||
cmd->sync_cmd = 0;
|
||||
|
||||
if (instance->unload == 1) {
|
||||
dev_info(&instance->pdev->dev, "Driver unload is in progress "
|
||||
"don't submit data to application\n");
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* copy out the kernel buffers to user buffers
|
||||
*/
|
||||
|
|
@ -6398,16 +6453,6 @@ static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
|
|||
|
||||
static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
|
||||
|
||||
static ssize_t
|
||||
megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
|
||||
{
|
||||
return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
|
||||
MEGASAS_RELDATE);
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
|
||||
NULL);
|
||||
|
||||
static ssize_t
|
||||
megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
|
||||
{
|
||||
|
|
@ -6711,8 +6756,7 @@ static int __init megasas_init(void)
|
|||
/*
|
||||
* Announce driver version and other information
|
||||
*/
|
||||
printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
|
||||
MEGASAS_EXT_VERSION);
|
||||
pr_info("megasas: %s\n", MEGASAS_VERSION);
|
||||
|
||||
spin_lock_init(&poll_aen_lock);
|
||||
|
||||
|
|
@ -6747,10 +6791,6 @@ static int __init megasas_init(void)
|
|||
&driver_attr_version);
|
||||
if (rval)
|
||||
goto err_dcf_attr_ver;
|
||||
rval = driver_create_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_release_date);
|
||||
if (rval)
|
||||
goto err_dcf_rel_date;
|
||||
|
||||
rval = driver_create_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_support_poll_for_event);
|
||||
|
|
@ -6774,12 +6814,7 @@ err_dcf_support_device_change:
|
|||
err_dcf_dbg_lvl:
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_support_poll_for_event);
|
||||
|
||||
err_dcf_support_poll_for_event:
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_release_date);
|
||||
|
||||
err_dcf_rel_date:
|
||||
driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
|
||||
err_dcf_attr_ver:
|
||||
pci_unregister_driver(&megasas_pci_driver);
|
||||
|
|
@ -6799,8 +6834,6 @@ static void __exit megasas_exit(void)
|
|||
&driver_attr_support_poll_for_event);
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_support_device_change);
|
||||
driver_remove_file(&megasas_pci_driver.driver,
|
||||
&driver_attr_release_date);
|
||||
driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
|
||||
|
||||
pci_unregister_driver(&megasas_pci_driver);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Linux MegaRAID driver for SAS based RAID controllers
|
||||
*
|
||||
* Copyright (c) 2009-2012 LSI Corporation.
|
||||
* Copyright (c) 2009-2013 LSI Corporation
|
||||
* Copyright (c) 2013-2014 Avago Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
|
@ -14,20 +15,21 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* FILE: megaraid_sas_fp.c
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Authors: Avago Technologies
|
||||
* Sumant Patro
|
||||
* Varad Talamacki
|
||||
* Manoj Jose
|
||||
* Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
* Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
*
|
||||
* Send feedback to: <megaraidlinux@lsi.com>
|
||||
* Send feedback to: megaraidlinux.pdl@avagotech.com
|
||||
*
|
||||
* Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
|
||||
* ATTN: Linuxraid
|
||||
* Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
|
||||
* San Jose, California 95131
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -183,14 +185,15 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
|
|||
/* New Raid map will not set totalSize, so keep expected value
|
||||
* for legacy code in ValidateMapInfo
|
||||
*/
|
||||
pDrvRaidMap->totalSize = sizeof(struct MR_FW_RAID_MAP_EXT);
|
||||
pDrvRaidMap->totalSize =
|
||||
cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT));
|
||||
} else {
|
||||
fw_map_old = (struct MR_FW_RAID_MAP_ALL *)
|
||||
fusion->ld_map[(instance->map_id & 1)];
|
||||
pFwRaidMap = &fw_map_old->raidMap;
|
||||
|
||||
#if VD_EXT_DEBUG
|
||||
for (i = 0; i < pFwRaidMap->ldCount; i++) {
|
||||
for (i = 0; i < le16_to_cpu(pFwRaidMap->ldCount); i++) {
|
||||
dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x "
|
||||
"Target Id 0x%x Seq Num 0x%x Size 0/%llx\n",
|
||||
instance->unique_id, i,
|
||||
|
|
@ -202,12 +205,12 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
|
|||
|
||||
memset(drv_map, 0, fusion->drv_map_sz);
|
||||
pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
|
||||
pDrvRaidMap->ldCount = pFwRaidMap->ldCount;
|
||||
pDrvRaidMap->ldCount = (__le16)pFwRaidMap->ldCount;
|
||||
pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec;
|
||||
for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++)
|
||||
pDrvRaidMap->ldTgtIdToLd[i] =
|
||||
(u8)pFwRaidMap->ldTgtIdToLd[i];
|
||||
for (i = 0; i < pDrvRaidMap->ldCount; i++) {
|
||||
for (i = 0; i < le16_to_cpu(pDrvRaidMap->ldCount); i++) {
|
||||
pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i];
|
||||
#if VD_EXT_DEBUG
|
||||
dev_dbg(&instance->pdev->dev,
|
||||
|
|
@ -268,7 +271,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
|
|||
else
|
||||
expected_size =
|
||||
(sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) +
|
||||
(sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pDrvRaidMap->ldCount)));
|
||||
(sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount)));
|
||||
|
||||
if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
|
||||
dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n",
|
||||
|
|
@ -284,7 +287,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
|
|||
|
||||
mr_update_load_balance_params(drv_map, lbInfo);
|
||||
|
||||
num_lds = le32_to_cpu(drv_map->raidMap.ldCount);
|
||||
num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
|
||||
|
||||
/*Convert Raid capability values to CPU arch */
|
||||
for (ldCount = 0; ldCount < num_lds; ldCount++) {
|
||||
|
|
@ -457,7 +460,7 @@ u32 mr_spanset_get_span_block(struct megasas_instance *instance,
|
|||
quad = &map->raidMap.ldSpanMap[ld].
|
||||
spanBlock[span].
|
||||
block_span_info.quad[info];
|
||||
if (le32_to_cpu(quad->diff == 0))
|
||||
if (le32_to_cpu(quad->diff) == 0)
|
||||
return SPAN_INVALID;
|
||||
if (le64_to_cpu(quad->logStart) <= row &&
|
||||
row <= le64_to_cpu(quad->logEnd) &&
|
||||
|
|
@ -520,7 +523,7 @@ static u64 get_row_from_strip(struct megasas_instance *instance,
|
|||
span_set->span_row_data_width) * span_set->diff;
|
||||
for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
|
||||
if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].
|
||||
block_span_info.noElements >= info+1)) {
|
||||
block_span_info.noElements) >= info+1) {
|
||||
if (strip_offset >=
|
||||
span_set->strip_offset[span])
|
||||
span_offset++;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Linux MegaRAID driver for SAS based RAID controllers
|
||||
*
|
||||
* Copyright (c) 2009-2012 LSI Corporation.
|
||||
* Copyright (c) 2009-2013 LSI Corporation
|
||||
* Copyright (c) 2013-2014 Avago Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
|
@ -14,19 +15,20 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* FILE: megaraid_sas_fusion.c
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Authors: Avago Technologies
|
||||
* Sumant Patro
|
||||
* Adam Radford <linuxraid@lsi.com>
|
||||
* Adam Radford
|
||||
* Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
* Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
*
|
||||
* Send feedback to: <megaraidlinux@lsi.com>
|
||||
* Send feedback to: megaraidlinux.pdl@avagotech.com
|
||||
*
|
||||
* Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
|
||||
* ATTN: Linuxraid
|
||||
* Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
|
||||
* San Jose, California 95131
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -880,7 +882,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
|
|||
|
||||
map = fusion->ld_drv_map[instance->map_id & 1];
|
||||
|
||||
num_lds = le32_to_cpu(map->raidMap.ldCount);
|
||||
num_lds = le16_to_cpu(map->raidMap.ldCount);
|
||||
|
||||
dcmd = &cmd->frame->dcmd;
|
||||
|
||||
|
|
@ -1065,48 +1067,16 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
|
|||
goto fail_ioc_init;
|
||||
|
||||
megasas_display_intel_branding(instance);
|
||||
if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
|
||||
if (megasas_get_ctrl_info(instance)) {
|
||||
dev_err(&instance->pdev->dev,
|
||||
"Could not get controller info. Fail from %s %d\n",
|
||||
__func__, __LINE__);
|
||||
goto fail_ioc_init;
|
||||
}
|
||||
|
||||
instance->supportmax256vd =
|
||||
instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
|
||||
/* Below is additional check to address future FW enhancement */
|
||||
if (instance->ctrl_info->max_lds > 64)
|
||||
instance->supportmax256vd = 1;
|
||||
instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
|
||||
* MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
|
||||
* MEGASAS_MAX_DEV_PER_CHANNEL;
|
||||
if (instance->supportmax256vd) {
|
||||
instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
|
||||
instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
|
||||
} else {
|
||||
instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
|
||||
instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
|
||||
}
|
||||
dev_info(&instance->pdev->dev, "Firmware supports %d VDs %d PDs\n"
|
||||
"Driver supports %d VDs %d PDs\n",
|
||||
instance->fw_supported_vd_count,
|
||||
instance->fw_supported_pd_count,
|
||||
instance->drv_supported_vd_count,
|
||||
instance->drv_supported_pd_count);
|
||||
|
||||
instance->flag_ieee = 1;
|
||||
fusion->fast_path_io = 0;
|
||||
|
||||
fusion->old_map_sz =
|
||||
sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
|
||||
(instance->fw_supported_vd_count - 1));
|
||||
fusion->new_map_sz =
|
||||
sizeof(struct MR_FW_RAID_MAP_EXT);
|
||||
fusion->drv_map_sz =
|
||||
sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
|
||||
(instance->drv_supported_vd_count - 1));
|
||||
|
||||
fusion->drv_map_pages = get_order(fusion->drv_map_sz);
|
||||
for (i = 0; i < 2; i++) {
|
||||
fusion->ld_map[i] = NULL;
|
||||
|
|
@ -1121,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
|
|||
fusion->drv_map_pages);
|
||||
goto fail_ioc_init;
|
||||
}
|
||||
memset(fusion->ld_drv_map[i], 0,
|
||||
((1 << PAGE_SHIFT) << fusion->drv_map_pages));
|
||||
}
|
||||
|
||||
fusion->max_map_sz = max(fusion->old_map_sz, fusion->new_map_sz);
|
||||
|
||||
if (instance->supportmax256vd)
|
||||
fusion->current_map_sz = fusion->new_map_sz;
|
||||
else
|
||||
fusion->current_map_sz = fusion->old_map_sz;
|
||||
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
|
||||
fusion->max_map_sz,
|
||||
|
|
@ -1173,9 +1137,10 @@ megasas_fire_cmd_fusion(struct megasas_instance *instance,
|
|||
struct megasas_register_set __iomem *regs)
|
||||
{
|
||||
#if defined(writeq) && defined(CONFIG_64BIT)
|
||||
u64 req_data = (((u64)req_desc_hi << 32) | (u32)req_desc_lo);
|
||||
u64 req_data = (((u64)le32_to_cpu(req_desc_hi) << 32) |
|
||||
le32_to_cpu(req_desc_lo));
|
||||
|
||||
writeq(le64_to_cpu(req_data), &(regs)->inbound_low_queue_port);
|
||||
writeq(req_data, &(regs)->inbound_low_queue_port);
|
||||
#else
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -1373,7 +1338,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
|
|||
/* Logical block reference tag */
|
||||
io_request->CDB.EEDP32.PrimaryReferenceTag =
|
||||
cpu_to_be32(ref_tag);
|
||||
io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
|
||||
io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
|
||||
io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
|
||||
|
||||
/* Transfer length */
|
||||
|
|
@ -1769,7 +1734,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
|
|||
|
||||
/* set RAID context values */
|
||||
pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ;
|
||||
pRAID_Context->timeoutValue = raid->fpIoTimeoutForLd;
|
||||
pRAID_Context->timeoutValue = cpu_to_le16(raid->fpIoTimeoutForLd);
|
||||
pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
|
||||
pRAID_Context->regLockRowLBA = 0;
|
||||
pRAID_Context->regLockLength = 0;
|
||||
|
|
@ -2254,7 +2219,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
|
|||
* megasas_complete_cmd
|
||||
*/
|
||||
|
||||
if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
|
||||
if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
|
||||
cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
|
||||
|
||||
fusion = instance->ctrl_context;
|
||||
|
|
@ -2385,6 +2350,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
|
|||
"memory allocation failed at index %d\n", i);
|
||||
break;
|
||||
}
|
||||
memset(instance->crash_buf[i], 0,
|
||||
((1 << PAGE_SHIFT) << instance->crash_buf_pages));
|
||||
}
|
||||
instance->drv_buf_alloc = i;
|
||||
}
|
||||
|
|
@ -2837,11 +2804,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
|
|||
}
|
||||
}
|
||||
|
||||
clear_bit(MEGASAS_FUSION_IN_RESET,
|
||||
&instance->reset_flags);
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
|
||||
|
||||
if (megasas_get_ctrl_info(instance)) {
|
||||
dev_info(&instance->pdev->dev,
|
||||
"Failed from %s %d\n",
|
||||
__func__, __LINE__);
|
||||
instance->adprecovery =
|
||||
MEGASAS_HW_CRITICAL_ERROR;
|
||||
megaraid_sas_kill_hba(instance);
|
||||
retval = FAILED;
|
||||
}
|
||||
/* Reset load balance info */
|
||||
memset(fusion->load_balance_info, 0,
|
||||
sizeof(struct LD_LOAD_BALANCE_INFO)
|
||||
|
|
@ -2850,6 +2821,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
|
|||
if (!megasas_get_map_info(instance))
|
||||
megasas_sync_map_info(instance);
|
||||
|
||||
clear_bit(MEGASAS_FUSION_IN_RESET,
|
||||
&instance->reset_flags);
|
||||
instance->instancet->enable_intr(instance);
|
||||
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
|
||||
|
||||
/* Restart SR-IOV heartbeat */
|
||||
if (instance->requestorId) {
|
||||
if (!megasas_sriov_start_heartbeat(instance, 0))
|
||||
|
|
@ -2866,14 +2842,14 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
|
|||
"successful for scsi%d.\n",
|
||||
instance->host->host_no);
|
||||
|
||||
if (instance->crash_dump_drv_support) {
|
||||
if (instance->crash_dump_app_support)
|
||||
megasas_set_crash_dump_params(instance,
|
||||
MR_CRASH_BUF_TURN_ON);
|
||||
else
|
||||
megasas_set_crash_dump_params(instance,
|
||||
MR_CRASH_BUF_TURN_OFF);
|
||||
}
|
||||
if (instance->crash_dump_drv_support &&
|
||||
instance->crash_dump_app_support)
|
||||
megasas_set_crash_dump_params(instance,
|
||||
MR_CRASH_BUF_TURN_ON);
|
||||
else
|
||||
megasas_set_crash_dump_params(instance,
|
||||
MR_CRASH_BUF_TURN_OFF);
|
||||
|
||||
retval = SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Linux MegaRAID driver for SAS based RAID controllers
|
||||
*
|
||||
* Copyright (c) 2009-2012 LSI Corporation.
|
||||
* Copyright (c) 2009-2013 LSI Corporation
|
||||
* Copyright (c) 2013-2014 Avago Technologies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
|
@ -14,19 +15,20 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* FILE: megaraid_sas_fusion.h
|
||||
*
|
||||
* Authors: LSI Corporation
|
||||
* Authors: Avago Technologies
|
||||
* Manoj Jose
|
||||
* Sumant Patro
|
||||
* Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
* Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
*
|
||||
* Send feedback to: <megaraidlinux@lsi.com>
|
||||
* Send feedback to: megaraidlinux.pdl@avagotech.com
|
||||
*
|
||||
* Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
|
||||
* ATTN: Linuxraid
|
||||
* Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
|
||||
* San Jose, California 95131
|
||||
*/
|
||||
|
||||
#ifndef _MEGARAID_SAS_FUSION_H_
|
||||
|
|
@ -834,8 +836,6 @@ struct fusion_context {
|
|||
|
||||
u32 max_map_sz;
|
||||
u32 current_map_sz;
|
||||
u32 old_map_sz;
|
||||
u32 new_map_sz;
|
||||
u32 drv_map_sz;
|
||||
u32 drv_map_pages;
|
||||
u8 fast_path_io;
|
||||
|
|
|
|||
|
|
@ -1179,15 +1179,14 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
|
|||
}
|
||||
|
||||
/**
|
||||
* _scsih_adjust_queue_depth - setting device queue depth
|
||||
* _scsih_change_queue_depth - setting device queue depth
|
||||
* @sdev: scsi device struct
|
||||
* @qdepth: requested queue depth
|
||||
*
|
||||
*
|
||||
* Returns nothing
|
||||
* Returns queue depth.
|
||||
*/
|
||||
static void
|
||||
_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
static int
|
||||
_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
int max_depth;
|
||||
|
|
@ -1217,41 +1216,11 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
|
|||
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
|
||||
|
||||
not_sata:
|
||||
|
||||
if (!sdev->tagged_supported)
|
||||
max_depth = 1;
|
||||
if (qdepth > max_depth)
|
||||
qdepth = max_depth;
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* _scsih_change_queue_depth - setting device queue depth
|
||||
* @sdev: scsi device struct
|
||||
* @qdepth: requested queue depth
|
||||
* @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
|
||||
* (see include/scsi/scsi_host.h for definition)
|
||||
*
|
||||
* Returns queue depth.
|
||||
*/
|
||||
static int
|
||||
_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
||||
{
|
||||
if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
|
||||
_scsih_adjust_queue_depth(sdev, qdepth);
|
||||
else if (reason == SCSI_QDEPTH_QFULL)
|
||||
scsi_track_queue_full(sdev, qdepth);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (sdev->inquiry_len > 7)
|
||||
sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
|
||||
"simple(%d), scsi_level(%d), cmd_que(%d)\n",
|
||||
sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
|
||||
sdev->scsi_level,
|
||||
(sdev->inquiry[7] & 2) >> 1);
|
||||
|
||||
return sdev->queue_depth;
|
||||
return scsi_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2082,7 +2051,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
|||
r_level, raid_device->handle,
|
||||
(unsigned long long)raid_device->wwid,
|
||||
raid_device->num_pds, ds);
|
||||
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
|
||||
_scsih_change_queue_depth(sdev, qdepth);
|
||||
/* raid transport support */
|
||||
if (!ioc->is_warpdrive)
|
||||
_scsih_set_level(sdev, raid_device->volume_type);
|
||||
|
|
@ -2147,7 +2116,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
|||
_scsih_display_sata_capabilities(ioc, handle, sdev);
|
||||
|
||||
|
||||
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
|
||||
_scsih_change_queue_depth(sdev, qdepth);
|
||||
|
||||
if (ssp_target) {
|
||||
sas_read_port_mode_page(sdev);
|
||||
|
|
@ -7637,6 +7606,7 @@ static struct scsi_host_template scsih_driver_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = mpt2sas_host_attrs,
|
||||
.sdev_attrs = mpt2sas_dev_attrs,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1053,9 +1053,15 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
|
|||
return found;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
/**
|
||||
* _scsih_change_queue_depth - setting device queue depth
|
||||
* @sdev: scsi device struct
|
||||
* @qdepth: requested queue depth
|
||||
*
|
||||
* Returns queue depth.
|
||||
*/
|
||||
static int
|
||||
_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
int max_depth;
|
||||
|
|
@ -1090,36 +1096,7 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
|
|||
max_depth = 1;
|
||||
if (qdepth > max_depth)
|
||||
qdepth = max_depth;
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* _scsih_change_queue_depth - setting device queue depth
|
||||
* @sdev: scsi device struct
|
||||
* @qdepth: requested queue depth
|
||||
* @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
|
||||
* (see include/scsi/scsi_host.h for definition)
|
||||
*
|
||||
* Returns queue depth.
|
||||
*/
|
||||
static int
|
||||
_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
||||
{
|
||||
if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
|
||||
_scsih_adjust_queue_depth(sdev, qdepth);
|
||||
else if (reason == SCSI_QDEPTH_QFULL)
|
||||
scsi_track_queue_full(sdev, qdepth);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (sdev->inquiry_len > 7)
|
||||
sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \
|
||||
"simple(%d), scsi_level(%d), cmd_que(%d)\n",
|
||||
sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
|
||||
sdev->scsi_level,
|
||||
(sdev->inquiry[7] & 2) >> 1);
|
||||
|
||||
return sdev->queue_depth;
|
||||
return scsi_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1739,7 +1716,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
|||
raid_device->num_pds, ds);
|
||||
|
||||
|
||||
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
|
||||
_scsih_change_queue_depth(sdev, qdepth);
|
||||
|
||||
/* raid transport support */
|
||||
_scsih_set_level(sdev, raid_device->volume_type);
|
||||
|
|
@ -1805,7 +1782,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
|||
_scsih_display_sata_capabilities(ioc, handle, sdev);
|
||||
|
||||
|
||||
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
|
||||
_scsih_change_queue_depth(sdev, qdepth);
|
||||
|
||||
if (ssp_target) {
|
||||
sas_read_port_mode_page(sdev);
|
||||
|
|
@ -7266,6 +7243,7 @@ static struct scsi_host_template scsih_driver_template = {
|
|||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = mpt3sas_host_attrs,
|
||||
.sdev_attrs = mpt3sas_dev_attrs,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,18 +26,9 @@
|
|||
|
||||
#include "mv_sas.h"
|
||||
|
||||
static int lldd_max_execute_num = 1;
|
||||
module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(collector, "\n"
|
||||
"\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
|
||||
"\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
|
||||
"\tThe mvsas SAS LLDD supports both modes.\n"
|
||||
"\tDefault: 1 (Direct Mode).\n");
|
||||
|
||||
int interrupt_coalescing = 0x80;
|
||||
|
||||
static struct scsi_transport_template *mvs_stt;
|
||||
struct kmem_cache *mvs_task_list_cache;
|
||||
static const struct mvs_chip_info mvs_chips[] = {
|
||||
[chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
|
||||
[chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
|
||||
|
|
@ -77,6 +68,7 @@ static struct scsi_host_template mvs_sht = {
|
|||
.ioctl = sas_ioctl,
|
||||
.shost_attrs = mvst_host_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct sas_domain_function_template mvs_transport_ops = {
|
||||
|
|
@ -512,14 +504,11 @@ static void mvs_post_sas_ha_init(struct Scsi_Host *shost,
|
|||
|
||||
sha->num_phys = nr_core * chip_info->n_phy;
|
||||
|
||||
sha->lldd_max_execute_num = lldd_max_execute_num;
|
||||
|
||||
if (mvi->flags & MVF_FLAG_SOC)
|
||||
can_queue = MVS_SOC_CAN_QUEUE;
|
||||
else
|
||||
can_queue = MVS_CHIP_SLOT_SZ;
|
||||
|
||||
sha->lldd_queue_size = can_queue;
|
||||
shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
|
||||
shost->can_queue = can_queue;
|
||||
mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
|
||||
|
|
@ -832,16 +821,7 @@ static int __init mvs_init(void)
|
|||
if (!mvs_stt)
|
||||
return -ENOMEM;
|
||||
|
||||
mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!mvs_task_list_cache) {
|
||||
rc = -ENOMEM;
|
||||
mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rc = pci_register_driver(&mvs_pci_driver);
|
||||
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
|
|
@ -856,7 +836,6 @@ static void __exit mvs_exit(void)
|
|||
{
|
||||
pci_unregister_driver(&mvs_pci_driver);
|
||||
sas_release_transport(mvs_stt);
|
||||
kmem_cache_destroy(mvs_task_list_cache);
|
||||
}
|
||||
|
||||
struct device_attribute *mvst_host_attrs[] = {
|
||||
|
|
|
|||
|
|
@ -852,43 +852,7 @@ prep_out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static struct mvs_task_list *mvs_task_alloc_list(int *num, gfp_t gfp_flags)
|
||||
{
|
||||
struct mvs_task_list *first = NULL;
|
||||
|
||||
for (; *num > 0; --*num) {
|
||||
struct mvs_task_list *mvs_list = kmem_cache_zalloc(mvs_task_list_cache, gfp_flags);
|
||||
|
||||
if (!mvs_list)
|
||||
break;
|
||||
|
||||
INIT_LIST_HEAD(&mvs_list->list);
|
||||
if (!first)
|
||||
first = mvs_list;
|
||||
else
|
||||
list_add_tail(&mvs_list->list, &first->list);
|
||||
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
static inline void mvs_task_free_list(struct mvs_task_list *mvs_list)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
struct list_head *pos, *a;
|
||||
struct mvs_task_list *mlist = NULL;
|
||||
|
||||
__list_add(&list, mvs_list->list.prev, &mvs_list->list);
|
||||
|
||||
list_for_each_safe(pos, a, &list) {
|
||||
list_del_init(pos);
|
||||
mlist = list_entry(pos, struct mvs_task_list, list);
|
||||
kmem_cache_free(mvs_task_list_cache, mlist);
|
||||
}
|
||||
}
|
||||
|
||||
static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
|
||||
static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags,
|
||||
struct completion *completion, int is_tmf,
|
||||
struct mvs_tmf_task *tmf)
|
||||
{
|
||||
|
|
@ -912,74 +876,9 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int mvs_collector_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
|
||||
struct completion *completion, int is_tmf,
|
||||
struct mvs_tmf_task *tmf)
|
||||
int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
||||
{
|
||||
struct domain_device *dev = task->dev;
|
||||
struct mvs_prv_info *mpi = dev->port->ha->lldd_ha;
|
||||
struct mvs_info *mvi = NULL;
|
||||
struct sas_task *t = task;
|
||||
struct mvs_task_list *mvs_list = NULL, *a;
|
||||
LIST_HEAD(q);
|
||||
int pass[2] = {0};
|
||||
u32 rc = 0;
|
||||
u32 n = num;
|
||||
unsigned long flags = 0;
|
||||
|
||||
mvs_list = mvs_task_alloc_list(&n, gfp_flags);
|
||||
if (n) {
|
||||
printk(KERN_ERR "%s: mvs alloc list failed.\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto free_list;
|
||||
}
|
||||
|
||||
__list_add(&q, mvs_list->list.prev, &mvs_list->list);
|
||||
|
||||
list_for_each_entry(a, &q, list) {
|
||||
a->task = t;
|
||||
t = list_entry(t->list.next, struct sas_task, list);
|
||||
}
|
||||
|
||||
list_for_each_entry(a, &q , list) {
|
||||
|
||||
t = a->task;
|
||||
mvi = ((struct mvs_device *)t->dev->lldd_dev)->mvi_info;
|
||||
|
||||
spin_lock_irqsave(&mvi->lock, flags);
|
||||
rc = mvs_task_prep(t, mvi, is_tmf, tmf, &pass[mvi->id]);
|
||||
if (rc)
|
||||
dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
|
||||
spin_unlock_irqrestore(&mvi->lock, flags);
|
||||
}
|
||||
|
||||
if (likely(pass[0]))
|
||||
MVS_CHIP_DISP->start_delivery(mpi->mvi[0],
|
||||
(mpi->mvi[0]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
|
||||
|
||||
if (likely(pass[1]))
|
||||
MVS_CHIP_DISP->start_delivery(mpi->mvi[1],
|
||||
(mpi->mvi[1]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
|
||||
|
||||
list_del_init(&q);
|
||||
|
||||
free_list:
|
||||
if (mvs_list)
|
||||
mvs_task_free_list(mvs_list);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mvs_queue_command(struct sas_task *task, const int num,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct mvs_device *mvi_dev = task->dev->lldd_dev;
|
||||
struct sas_ha_struct *sas = mvi_dev->mvi_info->sas;
|
||||
|
||||
if (sas->lldd_max_execute_num < 2)
|
||||
return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
|
||||
else
|
||||
return mvs_collector_task_exec(task, num, gfp_flags, NULL, 0, NULL);
|
||||
return mvs_task_exec(task, gfp_flags, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
|
||||
|
|
@ -1411,7 +1310,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
|
|||
task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);
|
||||
res = mvs_task_exec(task, GFP_KERNEL, NULL, 1, tmf);
|
||||
|
||||
if (res) {
|
||||
del_timer(&task->slow_task->timer);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ extern struct mvs_tgt_initiator mvs_tgt;
|
|||
extern struct mvs_info *tgt_mvi;
|
||||
extern const struct mvs_dispatch mvs_64xx_dispatch;
|
||||
extern const struct mvs_dispatch mvs_94xx_dispatch;
|
||||
extern struct kmem_cache *mvs_task_list_cache;
|
||||
|
||||
#define DEV_IS_EXPANDER(type) \
|
||||
((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
|
||||
|
|
@ -440,12 +439,6 @@ struct mvs_task_exec_info {
|
|||
int n_elem;
|
||||
};
|
||||
|
||||
struct mvs_task_list {
|
||||
struct sas_task *task;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
||||
/******************** function prototype *********************/
|
||||
void mvs_get_sas_addr(void *buf, u32 buflen);
|
||||
void mvs_tag_clear(struct mvs_info *mvi, u32 tag);
|
||||
|
|
@ -462,8 +455,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
|
|||
u32 off_hi, u64 sas_addr);
|
||||
void mvs_scan_start(struct Scsi_Host *shost);
|
||||
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
|
||||
int mvs_queue_command(struct sas_task *task, const int num,
|
||||
gfp_t gfp_flags);
|
||||
int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags);
|
||||
int mvs_abort_task(struct sas_task *task);
|
||||
int mvs_abort_task_set(struct domain_device *dev, u8 *lun);
|
||||
int mvs_clear_aca(struct domain_device *dev, u8 *lun);
|
||||
|
|
|
|||
|
|
@ -7997,7 +7997,7 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device)
|
|||
if (depth_to_use > MAX_TAGS)
|
||||
depth_to_use = MAX_TAGS;
|
||||
|
||||
scsi_adjust_queue_depth(device, depth_to_use);
|
||||
scsi_change_queue_depth(device, depth_to_use);
|
||||
|
||||
/*
|
||||
** Since the queue depth is not tunable under Linux,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
#define AUTOSENSE
|
||||
#define PSEUDO_DMA
|
||||
#define FOO
|
||||
#define UNSAFE /* Not unsafe for PAS16 -- use it */
|
||||
#define PDEBUG 0
|
||||
|
||||
|
|
@ -24,47 +22,9 @@
|
|||
* Media Vision
|
||||
* (510) 770-8600
|
||||
* (800) 348-7116
|
||||
*
|
||||
* and
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
/*
|
||||
* Options :
|
||||
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
|
||||
* for commands that return with a CHECK CONDITION status.
|
||||
*
|
||||
* LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
|
||||
* bytes at a time. Since interrupts are disabled by default during
|
||||
* these transfers, we might need this to give reasonable interrupt
|
||||
* service time if the transfer size gets too large.
|
||||
*
|
||||
* PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
|
||||
* increase compared to polled I/O.
|
||||
*
|
||||
* PARITY - enable parity checking. Not supported.
|
||||
*
|
||||
* SCSI2 - enable support for SCSI-II tagged queueing. Untested.
|
||||
*
|
||||
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers. This
|
||||
* parameter comes from the NCR5380 code. It is NOT unsafe with
|
||||
* the PAS16 and you should use it. If you don't you will have
|
||||
* a problem with dropped characters during high speed
|
||||
* communications during SCSI transfers. If you really don't
|
||||
* want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
|
||||
* twiddle with the transfer size in the high level code.
|
||||
*
|
||||
* USLEEP - enable support for devices that don't disconnect. Untested.
|
||||
*
|
||||
* The card is detected and initialized in one of several ways :
|
||||
* 1. Autoprobe (default) - There are many different models of
|
||||
* the Pro Audio Spectrum/Studio 16, and I only have one of
|
||||
|
|
@ -102,13 +62,11 @@
|
|||
* If you have problems with your card not being recognized, use
|
||||
* the LILO command line override. Try to get it recognized without
|
||||
* interrupts. Ie, for a board at the default 0x388 base port,
|
||||
* boot: linux pas16=0x388,255
|
||||
* boot: linux pas16=0x388,0
|
||||
*
|
||||
* SCSI_IRQ_NONE (255) should be specified for no interrupt,
|
||||
* NO_IRQ (0) should be specified for no interrupt,
|
||||
* IRQ_AUTO (254) to autoprobe for an IRQ line if overridden
|
||||
* on the command line.
|
||||
*
|
||||
* (IRQ_AUTO == 254, SCSI_IRQ_NONE == 255 in NCR5380.h)
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -123,15 +81,12 @@
|
|||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "pas16.h"
|
||||
#define AUTOPROBE_IRQ
|
||||
#include "NCR5380.h"
|
||||
|
||||
|
||||
static int pas_maxi = 0;
|
||||
static int pas_wmaxi = 0;
|
||||
static unsigned short pas16_addr = 0;
|
||||
static int pas16_irq = 0;
|
||||
|
||||
|
|
@ -337,6 +292,7 @@ static int __init
|
|||
}
|
||||
|
||||
|
||||
#ifndef MODULE
|
||||
/*
|
||||
* Function : pas16_setup(char *str, int *ints)
|
||||
*
|
||||
|
|
@ -347,10 +303,13 @@ static int __init
|
|||
*
|
||||
*/
|
||||
|
||||
void __init pas16_setup(char *str, int *ints)
|
||||
static int __init pas16_setup(char *str)
|
||||
{
|
||||
static int commandline_current = 0;
|
||||
int i;
|
||||
int ints[10];
|
||||
|
||||
get_options(str, ARRAY_SIZE(ints), ints);
|
||||
if (ints[0] != 2)
|
||||
printk("pas16_setup : usage pas16=io_port,irq\n");
|
||||
else
|
||||
|
|
@ -364,8 +323,12 @@ void __init pas16_setup(char *str, int *ints)
|
|||
}
|
||||
++commandline_current;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("pas16=", pas16_setup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function : int pas16_detect(struct scsi_host_template * tpnt)
|
||||
*
|
||||
|
|
@ -379,7 +342,7 @@ void __init pas16_setup(char *str, int *ints)
|
|||
*
|
||||
*/
|
||||
|
||||
int __init pas16_detect(struct scsi_host_template * tpnt)
|
||||
static int __init pas16_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
static int current_override = 0;
|
||||
static unsigned short current_base = 0;
|
||||
|
|
@ -387,10 +350,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
|
|||
unsigned short io_port;
|
||||
int count;
|
||||
|
||||
tpnt->proc_name = "pas16";
|
||||
tpnt->show_info = pas16_show_info;
|
||||
tpnt->write_info = pas16_write_info;
|
||||
|
||||
if (pas16_addr != 0) {
|
||||
overrides[0].io_port = pas16_addr;
|
||||
/*
|
||||
|
|
@ -452,15 +411,19 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
|
|||
else
|
||||
instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
|
||||
|
||||
if (instance->irq != SCSI_IRQ_NONE)
|
||||
/* Compatibility with documented NCR5380 kernel parameters */
|
||||
if (instance->irq == 255)
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
if (instance->irq != NO_IRQ)
|
||||
if (request_irq(instance->irq, pas16_intr, 0,
|
||||
"pas16", instance)) {
|
||||
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
|
||||
instance->host_no, instance->irq);
|
||||
instance->irq = SCSI_IRQ_NONE;
|
||||
instance->irq = NO_IRQ;
|
||||
}
|
||||
|
||||
if (instance->irq == SCSI_IRQ_NONE) {
|
||||
if (instance->irq == NO_IRQ) {
|
||||
printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
|
||||
printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
|
||||
/* Disable 5380 interrupts, leave drive params the same */
|
||||
|
|
@ -472,17 +435,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
|
|||
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
|
||||
#endif
|
||||
|
||||
printk("scsi%d : at 0x%04x", instance->host_no, (int)
|
||||
instance->io_port);
|
||||
if (instance->irq == SCSI_IRQ_NONE)
|
||||
printk (" interrupts disabled");
|
||||
else
|
||||
printk (" irq %d", instance->irq);
|
||||
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
|
||||
CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE);
|
||||
NCR5380_print_options(instance);
|
||||
printk("\n");
|
||||
|
||||
++current_override;
|
||||
++count;
|
||||
}
|
||||
|
|
@ -509,8 +461,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
|
|||
* and matching the H_C_S coordinates to what DOS uses.
|
||||
*/
|
||||
|
||||
int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
|
||||
sector_t capacity, int * ip)
|
||||
static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
|
||||
sector_t capacity, int *ip)
|
||||
{
|
||||
int size = capacity;
|
||||
ip[0] = 64;
|
||||
|
|
@ -547,6 +499,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
|
|||
P_DATA_REG_OFFSET);
|
||||
register int i = len;
|
||||
int ii = 0;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) )
|
||||
++ii;
|
||||
|
|
@ -559,8 +512,8 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
|
|||
instance->host_no);
|
||||
return -1;
|
||||
}
|
||||
if (ii > pas_maxi)
|
||||
pas_maxi = ii;
|
||||
if (ii > hostdata->spin_max_r)
|
||||
hostdata->spin_max_r = ii;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -583,6 +536,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
|
|||
register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
|
||||
register int i = len;
|
||||
int ii = 0;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) )
|
||||
++ii;
|
||||
|
|
@ -595,8 +549,8 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
|
|||
instance->host_no);
|
||||
return -1;
|
||||
}
|
||||
if (ii > pas_maxi)
|
||||
pas_wmaxi = ii;
|
||||
if (ii > hostdata->spin_max_w)
|
||||
hostdata->spin_max_w = ii;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -604,7 +558,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
|
|||
|
||||
static int pas16_release(struct Scsi_Host *shost)
|
||||
{
|
||||
if (shost->irq)
|
||||
if (shost->irq != NO_IRQ)
|
||||
free_irq(shost->irq, shost);
|
||||
NCR5380_exit(shost);
|
||||
if (shost->io_port && shost->n_io_port)
|
||||
|
|
@ -617,6 +571,10 @@ static struct scsi_host_template driver_template = {
|
|||
.name = "Pro Audio Spectrum-16 SCSI",
|
||||
.detect = pas16_detect,
|
||||
.release = pas16_release,
|
||||
.proc_name = "pas16",
|
||||
.show_info = pas16_show_info,
|
||||
.write_info = pas16_write_info,
|
||||
.info = pas16_info,
|
||||
.queuecommand = pas16_queue_command,
|
||||
.eh_abort_handler = pas16_abort,
|
||||
.eh_bus_reset_handler = pas16_bus_reset,
|
||||
|
|
|
|||
|
|
@ -18,26 +18,12 @@
|
|||
* Media Vision
|
||||
* (510) 770-8600
|
||||
* (800) 348-7116
|
||||
*
|
||||
* and
|
||||
*
|
||||
* NCR 5380 Family
|
||||
* SCSI Protocol Controller
|
||||
* Databook
|
||||
*
|
||||
* NCR Microelectronics
|
||||
* 1635 Aeroplaza Drive
|
||||
* Colorado Springs, CO 80916
|
||||
* 1+ (719) 578-3400
|
||||
* 1+ (800) 334-5454
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PAS16_H
|
||||
#define PAS16_H
|
||||
|
||||
#define PAS16_PUBLIC_RELEASE 3
|
||||
|
||||
#define PDEBUG_INIT 0x1
|
||||
#define PDEBUG_TRANSFER 0x2
|
||||
|
||||
|
|
@ -114,12 +100,6 @@
|
|||
|
||||
|
||||
#ifndef ASM
|
||||
static int pas16_abort(Scsi_Cmnd *);
|
||||
static int pas16_biosparam(struct scsi_device *, struct block_device *,
|
||||
sector_t, int*);
|
||||
static int pas16_detect(struct scsi_host_template *);
|
||||
static int pas16_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int pas16_bus_reset(Scsi_Cmnd *);
|
||||
|
||||
#ifndef CMD_PER_LUN
|
||||
#define CMD_PER_LUN 2
|
||||
|
|
@ -161,6 +141,7 @@ static int pas16_bus_reset(Scsi_Cmnd *);
|
|||
#define NCR5380_queue_command pas16_queue_command
|
||||
#define NCR5380_abort pas16_abort
|
||||
#define NCR5380_bus_reset pas16_bus_reset
|
||||
#define NCR5380_info pas16_info
|
||||
#define NCR5380_show_info pas16_show_info
|
||||
#define NCR5380_write_info pas16_write_info
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ static struct scsi_host_template pm8001_sht = {
|
|||
.ioctl = sas_ioctl,
|
||||
.shost_attrs = pm8001_host_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -600,8 +601,6 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
|
|||
sha->lldd_module = THIS_MODULE;
|
||||
sha->sas_addr = &pm8001_ha->sas_addr[0];
|
||||
sha->num_phys = chip_info->n_phy;
|
||||
sha->lldd_max_execute_num = 1;
|
||||
sha->lldd_queue_size = PM8001_CAN_QUEUE;
|
||||
sha->core.shost = shost;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
|
|||
*/
|
||||
#define DEV_IS_GONE(pm8001_dev) \
|
||||
((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
|
||||
static int pm8001_task_exec(struct sas_task *task, const int num,
|
||||
static int pm8001_task_exec(struct sas_task *task,
|
||||
gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
|
||||
{
|
||||
struct domain_device *dev = task->dev;
|
||||
|
|
@ -360,7 +360,6 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
|
|||
struct sas_task *t = task;
|
||||
struct pm8001_ccb_info *ccb;
|
||||
u32 tag = 0xdeadbeef, rc, n_elem = 0;
|
||||
u32 n = num;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (!dev->port) {
|
||||
|
|
@ -387,18 +386,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
|
|||
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
|
||||
t->task_done(t);
|
||||
spin_lock_irqsave(&pm8001_ha->lock, flags);
|
||||
if (n > 1)
|
||||
t = list_entry(t->list.next,
|
||||
struct sas_task, list);
|
||||
continue;
|
||||
} else {
|
||||
struct task_status_struct *ts = &t->task_status;
|
||||
ts->resp = SAS_TASK_UNDELIVERED;
|
||||
ts->stat = SAS_PHY_DOWN;
|
||||
t->task_done(t);
|
||||
if (n > 1)
|
||||
t = list_entry(t->list.next,
|
||||
struct sas_task, list);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -460,9 +453,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
|
|||
t->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock(&t->task_state_lock);
|
||||
pm8001_dev->running_req++;
|
||||
if (n > 1)
|
||||
t = list_entry(t->list.next, struct sas_task, list);
|
||||
} while (--n);
|
||||
} while (0);
|
||||
rc = 0;
|
||||
goto out_done;
|
||||
|
||||
|
|
@ -483,14 +474,11 @@ out_done:
|
|||
* pm8001_queue_command - register for upper layer used, all IO commands sent
|
||||
* to HBA are from this interface.
|
||||
* @task: the task to be execute.
|
||||
* @num: if can_queue great than 1, the task can be queued up. for SMP task,
|
||||
* we always execute one one time
|
||||
* @gfp_flags: gfp_flags
|
||||
*/
|
||||
int pm8001_queue_command(struct sas_task *task, const int num,
|
||||
gfp_t gfp_flags)
|
||||
int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
||||
{
|
||||
return pm8001_task_exec(task, num, gfp_flags, 0, NULL);
|
||||
return pm8001_task_exec(task, gfp_flags, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -708,7 +696,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
|
|||
task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf);
|
||||
res = pm8001_task_exec(task, GFP_KERNEL, 1, tmf);
|
||||
|
||||
if (res) {
|
||||
del_timer(&task->slow_task->timer);
|
||||
|
|
|
|||
|
|
@ -623,8 +623,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
|
|||
void *funcdata);
|
||||
void pm8001_scan_start(struct Scsi_Host *shost);
|
||||
int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time);
|
||||
int pm8001_queue_command(struct sas_task *task, const int num,
|
||||
gfp_t gfp_flags);
|
||||
int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags);
|
||||
int pm8001_abort_task(struct sas_task *task);
|
||||
int pm8001_abort_task_set(struct domain_device *dev, u8 *lun);
|
||||
int pm8001_clear_aca(struct domain_device *dev, u8 *lun);
|
||||
|
|
|
|||
|
|
@ -285,23 +285,15 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev)
|
|||
* pmcraid_change_queue_depth - Change the device's queue depth
|
||||
* @scsi_dev: scsi device struct
|
||||
* @depth: depth to set
|
||||
* @reason: calling context
|
||||
*
|
||||
* Return value
|
||||
* actual depth set
|
||||
*/
|
||||
static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth,
|
||||
int reason)
|
||||
static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth)
|
||||
{
|
||||
if (reason != SCSI_QDEPTH_DEFAULT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (depth > PMCRAID_MAX_CMD_PER_LUN)
|
||||
depth = PMCRAID_MAX_CMD_PER_LUN;
|
||||
|
||||
scsi_adjust_queue_depth(scsi_dev, depth);
|
||||
|
||||
return scsi_dev->queue_depth;
|
||||
return scsi_change_queue_depth(scsi_dev, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1224,9 +1224,9 @@ qla1280_slave_configure(struct scsi_device *device)
|
|||
|
||||
if (device->tagged_supported &&
|
||||
(ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) {
|
||||
scsi_adjust_queue_depth(device, ha->bus_settings[bus].hiwat);
|
||||
scsi_change_queue_depth(device, ha->bus_settings[bus].hiwat);
|
||||
} else {
|
||||
scsi_adjust_queue_depth(device, default_depth);
|
||||
scsi_change_queue_depth(device, default_depth);
|
||||
}
|
||||
|
||||
nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
|
||||
|
|
|
|||
|
|
@ -752,8 +752,6 @@ extern void qla8044_set_idc_dontreset(struct scsi_qla_host *ha);
|
|||
extern int qla8044_rd_direct(struct scsi_qla_host *vha, const uint32_t crb_reg);
|
||||
extern void qla8044_wr_direct(struct scsi_qla_host *vha,
|
||||
const uint32_t crb_reg, const uint32_t value);
|
||||
extern inline void qla8044_set_qsnt_ready(struct scsi_qla_host *vha);
|
||||
extern inline void qla8044_need_reset_handler(struct scsi_qla_host *vha);
|
||||
extern int qla8044_device_state_handler(struct scsi_qla_host *vha);
|
||||
extern void qla8044_clear_qsnt_ready(struct scsi_qla_host *vha);
|
||||
extern void qla8044_clear_drv_active(struct qla_hw_data *);
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ qla8044_rmw_crb_reg(struct scsi_qla_host *vha,
|
|||
return;
|
||||
}
|
||||
|
||||
inline void
|
||||
static inline void
|
||||
qla8044_set_qsnt_ready(struct scsi_qla_host *vha)
|
||||
{
|
||||
uint32_t qsnt_state;
|
||||
|
|
|
|||
|
|
@ -236,7 +236,6 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
|
|||
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
|
||||
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
|
||||
|
||||
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
|
||||
static void qla2x00_clear_drv_active(struct qla_hw_data *);
|
||||
static void qla2x00_free_device(scsi_qla_host_t *);
|
||||
static void qla83xx_disable_laser(scsi_qla_host_t *vha);
|
||||
|
|
@ -258,7 +257,7 @@ struct scsi_host_template qla2xxx_driver_template = {
|
|||
.slave_destroy = qla2xxx_slave_destroy,
|
||||
.scan_finished = qla2xxx_scan_finished,
|
||||
.scan_start = qla2xxx_scan_start,
|
||||
.change_queue_depth = qla2x00_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
.change_queue_type = scsi_change_queue_type,
|
||||
.this_id = -1,
|
||||
.cmd_per_lun = 3,
|
||||
|
|
@ -270,6 +269,7 @@ struct scsi_host_template qla2xxx_driver_template = {
|
|||
|
||||
.supported_mode = MODE_INITIATOR,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
|
||||
|
|
@ -1405,7 +1405,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
|
|||
if (IS_T10_PI_CAPABLE(vha->hw))
|
||||
blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
|
||||
|
||||
scsi_adjust_queue_depth(sdev, req->max_q_depth);
|
||||
scsi_change_queue_depth(sdev, req->max_q_depth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1415,58 +1415,6 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
|
|||
sdev->hostdata = NULL;
|
||||
}
|
||||
|
||||
static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
|
||||
|
||||
if (!scsi_track_queue_full(sdev, qdepth))
|
||||
return;
|
||||
|
||||
ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
|
||||
"Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n",
|
||||
sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
|
||||
}
|
||||
|
||||
static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
fc_port_t *fcport = sdev->hostdata;
|
||||
struct scsi_qla_host *vha = fcport->vha;
|
||||
struct req_que *req = NULL;
|
||||
|
||||
req = vha->req;
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
|
||||
return;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
|
||||
ql_dbg(ql_dbg_io, vha, 0x302a,
|
||||
"Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n",
|
||||
sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case SCSI_QDEPTH_DEFAULT:
|
||||
scsi_adjust_queue_depth(sdev, qdepth);
|
||||
break;
|
||||
case SCSI_QDEPTH_QFULL:
|
||||
qla2x00_handle_queue_full(sdev, qdepth);
|
||||
break;
|
||||
case SCSI_QDEPTH_RAMP_UP:
|
||||
qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
|
||||
* @ha: HA context
|
||||
|
|
|
|||
|
|
@ -164,8 +164,6 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
|
|||
static int qla4xxx_slave_alloc(struct scsi_device *device);
|
||||
static umode_t qla4_attr_is_visible(int param_type, int param);
|
||||
static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
|
||||
static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason);
|
||||
|
||||
/*
|
||||
* iSCSI Flash DDB sysfs entry points
|
||||
|
|
@ -203,7 +201,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
|
|||
.eh_timed_out = qla4xxx_eh_cmd_timed_out,
|
||||
|
||||
.slave_alloc = qla4xxx_slave_alloc,
|
||||
.change_queue_depth = qla4xxx_change_queue_depth,
|
||||
.change_queue_depth = scsi_change_queue_depth,
|
||||
|
||||
.this_id = -1,
|
||||
.cmd_per_lun = 3,
|
||||
|
|
@ -9061,19 +9059,10 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
|
|||
if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
|
||||
queue_depth = ql4xmaxqdepth;
|
||||
|
||||
scsi_adjust_queue_depth(sdev, queue_depth);
|
||||
scsi_change_queue_depth(sdev, queue_depth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
||||
int reason)
|
||||
{
|
||||
if (!ql4xqfulltracking)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return iscsi_change_queue_depth(sdev, qdepth, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4xxx_del_from_active_array - returns an active srb
|
||||
* @ha: Pointer to host adapter structure.
|
||||
|
|
@ -9873,6 +9862,9 @@ static int __init qla4xxx_module_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (ql4xqfulltracking)
|
||||
qla4xxx_driver_template.track_queue_depth = 1;
|
||||
|
||||
/* Allocate cache for SRBs. */
|
||||
srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
|
|
|
|||
|
|
@ -661,30 +661,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
|
|||
}
|
||||
|
||||
/**
|
||||
* scsi_adjust_queue_depth - Let low level drivers change a device's queue depth
|
||||
* scsi_change_queue_depth - change a device's queue depth
|
||||
* @sdev: SCSI Device in question
|
||||
* @tags: Number of tags allowed if tagged queueing enabled,
|
||||
* or number of commands the low level driver can
|
||||
* queue up in non-tagged mode (as per cmd_per_lun).
|
||||
* @depth: number of commands allowed to be queued to the driver
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Lock Status: None held on entry
|
||||
*
|
||||
* Notes: Low level drivers may call this at any time and we will do
|
||||
* the right thing depending on whether or not the device is
|
||||
* currently active and whether or not it even has the
|
||||
* command blocks built yet.
|
||||
* Sets the device queue depth and returns the new value.
|
||||
*/
|
||||
void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags)
|
||||
int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* refuse to set tagged depth to an unworkable size
|
||||
*/
|
||||
if (tags <= 0)
|
||||
return;
|
||||
if (depth <= 0)
|
||||
goto out;
|
||||
|
||||
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
|
||||
|
||||
|
|
@ -699,15 +687,17 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags)
|
|||
*/
|
||||
if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
|
||||
if (blk_queue_tagged(sdev->request_queue) &&
|
||||
blk_queue_resize_tags(sdev->request_queue, tags) != 0)
|
||||
goto out;
|
||||
blk_queue_resize_tags(sdev->request_queue, depth) != 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
sdev->queue_depth = tags;
|
||||
out:
|
||||
sdev->queue_depth = depth;
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
|
||||
out:
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_adjust_queue_depth);
|
||||
EXPORT_SYMBOL(scsi_change_queue_depth);
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth
|
||||
|
|
@ -752,12 +742,11 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
|
|||
if (sdev->last_queue_full_depth < 8) {
|
||||
/* Drop back to untagged */
|
||||
scsi_set_tag_type(sdev, 0);
|
||||
scsi_adjust_queue_depth(sdev, sdev->host->cmd_per_lun);
|
||||
scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scsi_adjust_queue_depth(sdev, depth);
|
||||
return depth;
|
||||
return scsi_change_queue_depth(sdev, depth);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_track_queue_full);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -610,7 +610,7 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
|
|||
struct scsi_host_template *sht = sdev->host->hostt;
|
||||
struct scsi_device *tmp_sdev;
|
||||
|
||||
if (!sht->change_queue_depth ||
|
||||
if (!sht->track_queue_depth ||
|
||||
sdev->queue_depth >= sdev->max_queue_depth)
|
||||
return;
|
||||
|
||||
|
|
@ -631,12 +631,8 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
|
|||
tmp_sdev->id != sdev->id ||
|
||||
tmp_sdev->queue_depth == sdev->max_queue_depth)
|
||||
continue;
|
||||
/*
|
||||
* call back into LLD to increase queue_depth by one
|
||||
* with ramp up reason code.
|
||||
*/
|
||||
sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1,
|
||||
SCSI_QDEPTH_RAMP_UP);
|
||||
|
||||
scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1);
|
||||
sdev->last_queue_ramp_up = jiffies;
|
||||
}
|
||||
}
|
||||
|
|
@ -646,7 +642,7 @@ static void scsi_handle_queue_full(struct scsi_device *sdev)
|
|||
struct scsi_host_template *sht = sdev->host->hostt;
|
||||
struct scsi_device *tmp_sdev;
|
||||
|
||||
if (!sht->change_queue_depth)
|
||||
if (!sht->track_queue_depth)
|
||||
return;
|
||||
|
||||
shost_for_each_device(tmp_sdev, sdev->host) {
|
||||
|
|
@ -658,8 +654,7 @@ static void scsi_handle_queue_full(struct scsi_device *sdev)
|
|||
* the device when we got the queue full so we start
|
||||
* from the highest possible value and work our way down.
|
||||
*/
|
||||
sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
|
||||
SCSI_QDEPTH_QFULL);
|
||||
scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
|
|||
blk_queue_init_tags(sdev->request_queue,
|
||||
sdev->host->cmd_per_lun, shost->bqt);
|
||||
}
|
||||
scsi_adjust_queue_depth(sdev, sdev->host->cmd_per_lun);
|
||||
scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
|
||||
|
||||
scsi_sysfs_device_initialize(sdev);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue