diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-03 20:08:13 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-03 20:08:13 -0700 |
| commit | 9028b7b80906bfe5c25132274ff96330e274c9b6 (patch) | |
| tree | 2a64dec2170ed71c904b50fcd180394c954d4a6a | |
| parent | 1db8f9f9ff0de5ef592ce9419c55ad3a0b4808a6 (diff) | |
| parent | fe7696127c27ee596328b96915f38d2b0b5adf8c (diff) | |
Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
47 files changed, 971 insertions, 1410 deletions
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl index 1dbafa7c2bd9..81e1561caf14 100644 --- a/Documentation/DocBook/scsidrivers.tmpl +++ b/Documentation/DocBook/scsidrivers.tmpl @@ -16,20 +16,40 @@ </affiliation> </author> </authorgroup> - <pubdate>2002-04-27</pubdate> + <pubdate>2003-08-11</pubdate> <copyright> <year>2002</year> + <year>2003</year> <holder>Douglas Gilbert</holder> </copyright> + <legalnotice> <para> - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU Free Documentation License, - Version 1.1 or any later version published by the Free Software - Foundation; with no Invariant Sections, with no Front-Cover Texts, - and with no Back-Cover Texts. A copy of the license is included - in the section entitled "GNU Free Documentation License". + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + 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 + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. </para> </legalnotice> diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a5a449a4a7d9..680507243d4a 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -475,6 +475,8 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, (struct scatterlist *) SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + if (sges_left == 0) + return FAILED; } else if (SCpnt->request_bufflen) { dma_addr_t buf_dma_addr; scPrivate *my_priv; @@ -3328,9 +3330,8 @@ mptscsih_slave_configure(Scsi_Device *device) device, device->id, device->lun, device->channel)); dsprintk((KERN_INFO "sdtr %d wdtr %d ppr %d inq length=%d\n", device->sdtr, device->wdtr, device->ppr, device->inquiry_len)); - dsprintk(("tagged %d queue %d simple %d ordered %d\n", - device->tagged_supported, device->tagged_queue, - device->simple_tags, device->ordered_tags)); + dsprintk(("tagged %d simple %d ordered %d\n", + device->tagged_supported, device->simple_tags, device->ordered_tags)); /* set target parameters, queue depths, set dv flags ? */ if (hd && (hd->Targets != NULL)) { diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 60bb81d4649b..4e384344042c 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1758,7 +1758,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) printk("53c700: scsi%d, command ", SCp->device->host->host_no); print_command(SCp->cmnd); #endif - if(SCp->device->tagged_supported && !SCp->device->tagged_queue + if(SCp->device->tagged_supported && !SCp->device->simple_tags && (hostdata->tag_negotiated &(1<<SCp->device->id)) == 0 && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { /* upper layer has indicated tags are supported. We don't diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c index 85d4d0507546..904115d0eac3 100644 --- a/drivers/scsi/AM53C974.c +++ b/drivers/scsi/AM53C974.c @@ -1231,8 +1231,8 @@ static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) hostdata->sel_cmd = NULL; hostdata->selecting = 0; #ifdef SCSI2 - if (!hostdata->connected->device->tagged_queue) -#endif + if (!hostdata->conneted->device->simple_tags) +#else hostdata->busy[hostdata->connected->device->id] |= (1 << hostdata->connected->device->lun); /* very strange -- use_sg is sometimes nonzero for request sense commands !! */ if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) { @@ -1811,7 +1811,7 @@ static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd * cmd, case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; + cmd->device->simple_tags = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); break; default: @@ -1958,7 +1958,7 @@ static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag #endif #ifdef SCSI2 - if (cmd->device->tagged_queue && (tag != TAG_NONE)) { + if (cmd->device->simple_tags && (tag != TAG_NONE)) { tmp[1] = SIMPLE_QUEUE_TAG; if (tag == TAG_NEXT) { /* 0 is TAG_NONE, used to imply no tag for this command */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 315967cc013a..b3c9048c3a17 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -22,6 +22,17 @@ config SCSI module if your root file system (the one containing the directory /) is located on a SCSI device. +config SCSI_PROC_FS + bool "legacy /proc/scsi/ support" + depends on SCSI + default y + ---help--- + This option enables support for the various files in + /proc/scsi. In Linux 2.6 this has been superceeded by + files in sysfs but many legacy applications rely on this. + + If unusure say Y. + comment "SCSI support type (disk, tape, CD-ROM)" depends on SCSI @@ -726,13 +737,13 @@ config IBMMCA_SCSI_DEV_RESET config SCSI_IPS tristate "IBM ServeRAID support" - depends on X86 && PCI && SCSI + depends on PCI && SCSI ---help--- This is support for the IBM ServeRAID hardware RAID controllers. See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html> for more information. If this driver does not work correctly without modification please contact the author by email at - ipslinux@us.ibm.com. + ipslinux@adaptec.com. You can build this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -989,36 +1000,9 @@ config SCSI_NCR_Q720 Unless you have an NCR manufactured machine, the chances are that you do not have this SCSI card, so say N. -config SCSI_SYM53C8XX - tristate "SYM53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI - ---help--- - This driver supports all the features of recent 53C8XX chips (used - in PCI SCSI controllers), notably the hardware phase mismatch - feature of the SYM53C896. - - Older versions of the 53C8XX chips are not supported by this - driver. If your system uses either a 810 rev. < 16, a 815, or a 825 - rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX - driver ("NCR53C8XX SCSI support" above) or configure both the - NCR53C8XX and this SYM53C8XX drivers either as module or linked to - the kernel image. - - When both drivers are linked into the kernel, the SYM53C8XX driver - is called first at initialization and you can use the 'excl=ioaddr' - driver boot option to exclude attachment of adapters by the - SYM53C8XX driver. For example, entering - 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents - adapters at io address 0xb400 and 0xc000 from being attached by the - SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them. - The 'excl' option is also supported by the NCR53C8XX driver. - - Please read <file:Documentation/scsi/ncr53c8xx.txt> for more - information. - config SCSI_NCR53C8XX_DEFAULT_TAGS int " default tagged command queue depth" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "8" ---help--- "Tagged command queuing" is a feature of SCSI-2 which improves @@ -1044,7 +1028,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS config SCSI_NCR53C8XX_MAX_TAGS int " maximum number of queued commands" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "32" ---help--- This option allows you to specify the maximum number of commands @@ -1061,7 +1045,7 @@ config SCSI_NCR53C8XX_MAX_TAGS config SCSI_NCR53C8XX_SYNC int " synchronous transfers frequency in MHz" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 default "20" ---help--- The SCSI Parallel Interface-2 Standard defines 5 classes of transfer @@ -1095,7 +1079,7 @@ config SCSI_NCR53C8XX_SYNC config SCSI_NCR53C8XX_PROFILE bool " enable profiling" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) + depends on SCSI_ZALON || SCSI_NCR_Q720 help This option allows you to enable profiling information gathering. These statistics are not very accurate due to the low frequency @@ -1104,34 +1088,9 @@ config SCSI_NCR53C8XX_PROFILE The normal answer therefore is N. -config SCSI_NCR53C8XX_IOMAPPED - bool " use normal IO" - depends on SCSI_SYM53C8XX && !(SCSI_ZALON || SCSI_NCR_Q720) - help - If you say Y here, the driver will use normal IO, as opposed to - memory mapped IO. Memory mapped IO has less latency than normal IO - and works for most Intel-based hardware. Under Linux/Alpha only - normal IO is currently supported by the driver and so, this option - has no effect on those systems. - - The normal answer therefore is N; try Y only if you encounter SCSI - related problems. - -config SCSI_NCR53C8XX_PQS_PDS - bool " include support for the NCR PQS/PDS SCSI card" - depends on SCSI_SYM53C8XX - help - Say Y here if you have a special SCSI adapter produced by NCR - corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need - this if you do not have one of these adapters. However, since this - device is detected as a specific PCI device, this option is quite - safe. - - The common answer here is N, but answering Y is safe. - config SCSI_NCR53C8XX_NO_DISCONNECT bool " not allow targets to disconnect" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 + depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 help This option is only provided for safety if you suspect some SCSI device of yours to not support properly the target-disconnect @@ -1139,26 +1098,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT not allow targets to disconnect is not reasonable if there is more than 1 device on a SCSI bus. The normal answer therefore is N. -config SCSI_NCR53C8XX_SYMBIOS_COMPAT - bool " assume boards are SYMBIOS compatible (EXPERIMENTAL)" - depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720 ) && EXPERIMENTAL - ---help--- - This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for - vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS controllers use GPIO0 in output for - controller LED and GPIO3 bit as a flag indicating - singled-ended/differential interface. The Tekram DC-390U/F boards - uses a different GPIO wiring. - - Your answer to this question is ignored if all your controllers have - NVRAM, since the driver is able to detect the board type from the - NVRAM format. - - If all the controllers in your system are genuine SYMBIOS boards or - use BIOS and drivers from SYMBIOS, you would want to say Y here, - otherwise N. N is the safe answer. - config SCSI_MCA_53C9X tristate "NCR MCA 53C9x SCSI support" depends on MCA && SCSI && BROKEN_ON_SMP diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b2ed067c7b98..fb2442aeb330 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -126,7 +126,8 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_syms.o scsi_sysfs.o \ scsi_devinfo.o -scsi_mod-$(CONFIG_PROC_FS) += scsi_proc.o +scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o +scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o sd_mod-objs := sd.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index dba125a0db5c..7262cca5529e 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2512,7 +2512,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; + cmd->device->simple_tags = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); break; default: diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 1ec4a55cbd10..390f63b3a371 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -6362,8 +6362,8 @@ advansys_slave_configure(Scsi_Device *device) } else { scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); } - ASC_DBG3(1, "advansys_slave_configure: shp 0x%lx, id %d, depth %d\n", - (ulong) shp, device->id, device->queue_depth); + ASC_DBG4(1, "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", + (ulong) device, (ulong) boardp, device->id, device->queue_depth); return 0; } @@ -9354,8 +9354,8 @@ asc_prt_scsi_host(struct Scsi_Host *s) printk("Scsi_Host at addr 0x%lx\n", (ulong) s); printk( -" next 0x%lx, host_busy %u, host_no %d, last_reset %d,\n", - (ulong) s->next, s->host_busy, s->host_no, +" host_busy %u, host_no %d, last_reset %d,\n", + s->host_busy, s->host_no, (unsigned) s->last_reset); #if ASC_LINUX_KERNEL24 @@ -9399,8 +9399,8 @@ asc_prt_scsi_cmnd(Scsi_Cmnd *s) printk( " host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", - (ulong) s->host, (ulong) s->device, s->target, s->lun, - s->channel); + (ulong) s->device->host, (ulong) s->device, s->device->id, s->device->lun, + s->device->channel); asc_prt_hex(" CDB", s->cmnd, s->cmd_len); diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index a0452a6c6122..efc61b3f2502 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -768,7 +768,7 @@ intr_ret_t acornscsi_kick(AS_Host *host) /* * tagged queueing - allocate a new tag to this command */ - if (SCpnt->device->tagged_queue) { + if (SCpnt->device->simple_tags) { SCpnt->device->current_tag += 1; if (SCpnt->device->current_tag == 0) SCpnt->device->current_tag = 1; @@ -1590,7 +1590,7 @@ void acornscsi_message(AS_Host *host) */ printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", host->host->host_no, acornscsi_target(host)); - host->SCpnt->device->tagged_queue = 0; + host->SCpnt->device->simple_tags = 0; set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); break; #endif @@ -2935,7 +2935,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, p += sprintf(p, " %d/%d ", scd->id, scd->lun); if (scd->tagged_supported) p += sprintf(p, "%3sabled(%3d) ", - scd->tagged_queue ? "en" : "dis", + scd->simple_tags ? "en" : "dis", scd->current_tag); else p += sprintf(p, "unsupported "); diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index fbda4d4f78a7..2c99ea7dae85 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -1819,7 +1819,7 @@ static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt) /* * tagged queuing - allocate a new tag to this command */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && + if (SCpnt->device->simple_tags && SCpnt->cmnd[0] != REQUEST_SENSE && SCpnt->cmnd[0] != INQUIRY) { SCpnt->device->current_tag += 1; if (SCpnt->device->current_tag == 0) @@ -3012,7 +3012,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer) p += sprintf(p, " %d/%d ", scd->id, scd->lun); if (scd->tagged_supported) p += sprintf(p, "%3sabled(%3d) ", - scd->tagged_queue ? "en" : "dis", + scd->simple_tags ? "en" : "dis", scd->current_tag); else p += sprintf(p, "unsupported "); diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c index 943778cca0eb..d165a3af3e14 100644 --- a/drivers/scsi/cpqfcTSinit.c +++ b/drivers/scsi/cpqfcTSinit.c @@ -603,7 +603,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg) return -ENOMEM; } // Now build a Scsi_Request to pass down... - ScsiPassThruReq = scsi_allocate_request(ScsiDev); + ScsiPassThruReq = scsi_allocate_request(ScsiDev, GFP_KERNEL); if (ScsiPassThruReq == NULL) { kfree(buf); return -ENOMEM; diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c index b41038baa394..2b5735863b65 100644 --- a/drivers/scsi/cpqfcTSworker.c +++ b/drivers/scsi/cpqfcTSworker.c @@ -2878,7 +2878,7 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd) } } -Done: +Done: ; } extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index e0a1d2191eed..107c220ae086 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -224,14 +224,14 @@ static char traceoverflow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; #define DC395x_SMP_IO_UNLOCK(dev,irq_flags) spin_unlock_irqrestore(((struct Scsi_Host*)dev)->host_lock,irq_flags) -#define DC395x_read8(acb,address) (u8)(inb(acb->IOPortBase + (address))) +#define DC395x_read8(acb,address) (u8)(inb(acb->io_port_base + (address))) #define DC395x_read8_(address, base) (u8)(inb((USHORT)(base) + (address))) -#define DC395x_read16(acb,address) (u16)(inw(acb->IOPortBase + (address))) -#define DC395x_read32(acb,address) (u32)(inl(acb->IOPortBase + (address))) -#define DC395x_write8(acb,address,value) outb((value), acb->IOPortBase + (address)) +#define DC395x_read16(acb,address) (u16)(inw(acb->io_port_base + (address))) +#define DC395x_read32(acb,address) (u32)(inl(acb->io_port_base + (address))) +#define DC395x_write8(acb,address,value) outb((value), acb->io_port_base + (address)) #define DC395x_write8_(address,value,base) outb((value), (USHORT)(base) + (address)) -#define DC395x_write16(acb,address,value) outw((value), acb->IOPortBase + (address)) -#define DC395x_write32(acb,address,value) outl((value), acb->IOPortBase + (address)) +#define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address)) +#define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address)) #define BUS_ADDR(sg) sg_dma_address(&(sg)) @@ -383,7 +383,8 @@ struct DeviceCtlBlk { struct AdapterCtlBlk { struct Scsi_Host *scsi_host; - u16 IOPortBase; + u16 io_port_base; + u16 io_port_len; struct list_head dcb_list; /* head of going dcb list */ struct DeviceCtlBlk *dcb_run_robin; @@ -496,10 +497,6 @@ static void request_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static inline void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb); -static void init_dcb(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk **pdcb, u8 target, u8 lun); -static void remove_dev(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb); static void waiting_timeout(unsigned long ptr); @@ -822,6 +819,7 @@ void __init eeprom_override(struct NvRamType *eeprom) * * @head: The pointer to the head of the list to count the items in. **/ +static unsigned int list_size(struct list_head *head) { unsigned int count = 0; @@ -841,6 +839,7 @@ unsigned int list_size(struct list_head *head) * @pos: The pointer the dcb for which we are searching for the * following dcb. **/ +static struct DeviceCtlBlk *dcb_get_next( struct list_head *head, struct DeviceCtlBlk *pos) @@ -1449,34 +1448,6 @@ complete: } -/*********************************************************************** - * Function static int dc395x_slave_alloc() - * - * Purpose: Allocate DCB - ***********************************************************************/ -static int dc395x_slave_alloc(struct scsi_device *sdp) -{ - struct AdapterCtlBlk *acb; - struct DeviceCtlBlk *dummy; - - acb = (struct AdapterCtlBlk *) sdp->host->hostdata; - - init_dcb(acb, &dummy, sdp->id, sdp->lun); - - return dummy ? 0 : -ENOMEM; -} - - -static void dc395x_slave_destroy(struct scsi_device *sdp) -{ - struct AdapterCtlBlk *acb; - struct DeviceCtlBlk *dcb; - - acb = (struct AdapterCtlBlk *) sdp->host->hostdata; - dcb = find_dcb(acb, sdp->id, sdp->lun); - - remove_dev(acb, dcb); -} /* @@ -1635,7 +1606,6 @@ static void reset_dev_param(struct AdapterCtlBlk *acb) dcb->sync_offset = 0; dcb->dev_mode = eeprom->target[dcb->target_id].cfg0; - /*dcb->AdpMode = eeprom->channel_cfg; */ period_index = eeprom->target[dcb->target_id].period & 0x07; dcb->min_nego_period = clock_period[period_index]; if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO) @@ -1824,7 +1794,6 @@ static void selto_timer(struct AdapterCtlBlk *acb) { if (timer_pending(&acb->selto_timer)) return; - init_timer(&acb->selto_timer); acb->selto_timer.function = selection_timeout_missed; acb->selto_timer.data = (unsigned long) acb; if (time_before @@ -4049,40 +4018,8 @@ static void reselect(struct AdapterCtlBlk *acb) } -/* Dynamic device handling */ - -/* Remove dev (and DCB) */ -static -void remove_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) -{ - struct DeviceCtlBlk *i; - struct DeviceCtlBlk *tmp; - - dprintkdbg(DBG_0, "remove_dev\n"); - if (list_size(&dcb->srb_going_list) > 1) { - dprintkdbg(DBG_DCB, "Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n", - dcb->target_id, dcb->target_lun, (int) dcb, - list_size(&dcb->srb_going_list)); - return; - } - acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun); - acb->children[dcb->target_id][dcb->target_lun] = NULL; - list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) { - if (dcb == i) { - list_del(&i->list); - break; - } - } - dprintkdbg(DBG_DCB, "Driver about to free DCB (ID %i, LUN %i): %p\n", - dcb->target_id, dcb->target_lun, dcb); - if (dcb == acb->active_dcb) - acb->active_dcb = NULL; - if (dcb == acb->dcb_run_robin) - acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb); - dc395x_kfree(dcb); -} static inline u8 tagq_blacklist(char *name) @@ -4681,58 +4618,55 @@ void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, } -/* - ********************************************************************* - * dc395x_queue_command + + + +/** + * device_alloc - Allocate a new device instance. This create the + * devices instance and sets up all the data items. The adapter + * instance is required to obtain confiuration information for this + * device. This does *not* add this device to the adapters device + * list. * - * Function : void init_dcb - * Purpose : initialize the internal structures for a given DCB - * Inputs : cmd - pointer to this scsi cmd request block structure - ********************************************************************* - */ + * @acb: The adapter to obtain configuration information from. + * @target: The target for the new device. + * @lun: The lun for the new device. + * + * Return the new device if succesfull or NULL on failure. + **/ static -void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, - u8 target, u8 lun) +struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun) { struct NvRamType *eeprom = &acb->eeprom; - u8 period_index; + u8 period_index = eeprom->target[target].period & 0x07; struct DeviceCtlBlk *dcb; - struct DeviceCtlBlk *dcb2; - dprintkdbg(DBG_0, "init_dcb..............\n"); dcb = dc395x_kmalloc(sizeof(struct DeviceCtlBlk), GFP_ATOMIC); - /*dcb = find_dcb (acb, target, lun); */ - *pdcb = dcb; - dcb2 = NULL; - if (!dcb) - return; - - INIT_LIST_HEAD(&dcb->srb_waiting_list); + dprintkdbg(DBG_0, "device_alloc: device %p\n", dcb); + if (!dcb) { + return NULL; + } + dcb->acb = NULL; INIT_LIST_HEAD(&dcb->srb_going_list); - if (list_empty(&acb->dcb_list)) - acb->dcb_run_robin = dcb; - list_add_tail(&dcb->list, &acb->dcb_list); - - /* $$$$$$$ */ - dcb->acb = acb; - dcb->target_id = target; - dcb->target_lun = lun; - /* $$$$$$$ */ + INIT_LIST_HEAD(&dcb->srb_waiting_list); dcb->active_srb = NULL; - /* $$$$$$$ */ dcb->tag_mask = 0; - dcb->flag = 0; dcb->max_command = 1; - /* $$$$$$$ */ + dcb->target_id = target; + dcb->target_lun = lun; +#ifndef DC395x_NO_DISCONNECT + dcb->identify_msg = + IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun); +#else + dcb->identify_msg = IDENTIFY(0, lun); +#endif dcb->dev_mode = eeprom->target[target].cfg0; - /*dcb->AdpMode = eeprom->channel_cfg; */ dcb->inquiry7 = 0; dcb->sync_mode = 0; - /* $$$$$$$ */ + dcb->min_nego_period = clock_period[period_index]; dcb->sync_period = 0; dcb->sync_offset = 0; - period_index = eeprom->target[target].period & 0x07; - dcb->min_nego_period = clock_period[period_index]; + dcb->flag = 0; #ifndef DC395x_NO_WIDE if ((dcb->dev_mode & NTC_DO_WIDE_NEGO) @@ -4744,318 +4678,166 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, if (!(lun) || current_sync_offset) dcb->sync_mode |= SYNC_NEGO_ENABLE; #endif - /* $$$$$$$ */ -#ifndef DC395x_NO_DISCONNECT - dcb->identify_msg = - IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun); -#else - dcb->identify_msg = IDENTIFY(0, lun); -#endif - /* $$$$$$$ */ if (dcb->target_lun != 0) { /* Copy settings */ - struct DeviceCtlBlk *prevDCB; - list_for_each_entry(prevDCB, &acb->dcb_list, list) - if (prevDCB->target_id == dcb->target_id) + struct DeviceCtlBlk *p; + list_for_each_entry(p, &acb->dcb_list, list) + if (p->target_id == dcb->target_id) break; - dprintkdbg(DBG_KG, + dprintkdbg(DBG_KG, "Copy settings from %02i-%02i to %02i-%02i\n", - prevDCB->target_id, prevDCB->target_lun, + p->target_id, p->target_lun, dcb->target_id, dcb->target_lun); - dcb->sync_mode = prevDCB->sync_mode; - dcb->sync_period = prevDCB->sync_period; - dcb->min_nego_period = prevDCB->min_nego_period; - dcb->sync_offset = prevDCB->sync_offset; - dcb->inquiry7 = prevDCB->inquiry7; - }; - - acb->dcb_map[target] |= (1 << lun); - acb->children[target][lun] = dcb; + dcb->sync_mode = p->sync_mode; + dcb->sync_period = p->sync_period; + dcb->min_nego_period = p->min_nego_period; + dcb->sync_offset = p->sync_offset; + dcb->inquiry7 = p->inquiry7; + } + return dcb; } -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) -/* - * Memory for trace buffers - */ +/** + * adapter_add_device - Adds the device instance to the adaptor instance. + * + * @acb: The adapter device to be updated + * @dcb: A newly created and intialised device instance to add. + **/ static -void free_tracebufs(struct AdapterCtlBlk *acb, int srb_idx) +void adapter_add_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - for (i = 0; i < srb_idx; i += bufs_per_page) { - /*dprintkl(KERN_DEBUG, "Free tracebuf %p (for %i)\n", */ - /* acb->srb_array[i].debugtrace, i); */ - dc395x_kfree(acb->srb_array[i].debugtrace); - } -} + /* backpointer to adapter */ + dcb->acb = acb; + + /* set run_robin to this device if it is currently empty */ + if (list_empty(&acb->dcb_list)) + acb->dcb_run_robin = dcb; + /* add device to list */ + list_add_tail(&dcb->list, &acb->dcb_list); -static -int alloc_tracebufs(struct AdapterCtlBlk *acb) -{ - const unsigned mem_needed = - (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ; - int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - int srb_idx = 0; - unsigned i = 0; - unsigned char *ptr; - /*dprintkl(KERN_DEBUG, "Alloc %i pages for tracebufs\n", pages); */ - while (pages--) { - ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ptr) { - free_tracebufs(acb, srb_idx); - return 1; - } - /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */ - /* PAGE_SIZE, ptr, srb_idx); */ - i = 0; - while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT) - acb->srb_array[srb_idx++].debugtrace = - ptr + (i++ * DEBUGTRACEBUFSZ); - } - if (i < bufs_per_page) { - acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ); - acb->srb.debugtrace[0] = 0; - } else - dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n"); - return 0; + /* update device maps */ + acb->dcb_map[dcb->target_id] |= (1 << dcb->target_lun); + acb->children[dcb->target_id][dcb->target_lun] = dcb; } -#endif -/* Free SG tables */ -static void free_sg_tables(struct AdapterCtlBlk *acb, int srb_idx) +/** + * adapter_remove_device - Removes the device instance from the adaptor + * instance. The device instance is not check in any way or freed by this. + * The caller is expected to take care of that. This will simply remove the + * device from the adapters data strcutures. + * + * @acb: The adapter device to be updated + * @dcb: A device that has previously been added to the adapter. + **/ +static +void adapter_remove_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - const unsigned srbs_per_page = - PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry)); - for (i = 0; i < srb_idx; i += srbs_per_page) { - /*dprintkl(KERN_DEBUG, "Free SG segs %p (for %i)\n", */ - /* acb->srb_array[i].segment_x, i); */ - dc395x_kfree(acb->srb_array[i].segment_x); - } -} + struct DeviceCtlBlk *i; + struct DeviceCtlBlk *tmp; + dprintkdbg(DBG_0, "adapter_remove_device: Remove device (ID %i, LUN %i): %p\n", + dcb->target_id, dcb->target_lun, dcb); + /* fix up any pointers to this device that we have in the adapter */ + if (acb->active_dcb == dcb) + acb->active_dcb = NULL; + if (acb->dcb_run_robin == dcb) + acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb); -/* - * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) - * should never cross a page boundary */ -static int alloc_sg_tables(struct AdapterCtlBlk *acb) -{ - const unsigned mem_needed = - (DC395x_MAX_SRB_CNT + - 1) * DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry); - int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; - const unsigned srbs_per_page = - PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry)); - int srb_idx = 0; - unsigned i = 0; - struct SGentry *ptr; - /*dprintkl(KERN_DEBUG, "Alloc %i pages for SG tables\n", pages); */ - while (pages--) { - ptr = (struct SGentry *) dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ptr) { - free_sg_tables(acb, srb_idx); - return 1; + /* unlink from list */ + list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) + if (dcb == i) { + list_del(&i->list); + break; } - /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for SG segments %i\n", */ - /* PAGE_SIZE, ptr, srb_idx); */ - i = 0; - while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT) - acb->srb_array[srb_idx++].segment_x = - ptr + (i++ * DC395x_MAX_SG_LISTENTRY); - } - if (i < srbs_per_page) - acb->srb.segment_x = - ptr + (i * DC395x_MAX_SG_LISTENTRY); - else - dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - return 0; + + /* clear map and children */ + acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun); + acb->children[dcb->target_id][dcb->target_lun] = NULL; + dcb->acb = NULL; } -/* - ******************************************************************** - * scsiio - * init_acb - ******************************************************************** +/** + * adapter_remove_and_free_device - Removes a single device from the adapter + * and then frees the device information. + * + * @acb: The adapter device to be updated + * @dcb: A device that has previously been added to the adapter. */ -static void __init link_srb(struct AdapterCtlBlk *acb) +static +void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { - int i; - - for (i = 0; i < acb->srb_count - 1; i++) - srb_free_insert(acb, &acb->srb_array[i]); + if (list_size(&dcb->srb_going_list) > 1) { + dprintkdbg(DBG_DCB, "adapter_remove_and_free_device: " + "Won't remove because of %i active requests\n", + list_size(&dcb->srb_going_list)); + return; + } + adapter_remove_device(acb, dcb); + dc395x_kfree(dcb); } -/* - *********************************************************************** - * host_init +/** + * adapter_remove_and_free_all_devices - Removes and frees all of the + * devices associated with the specified adapter. * - * Function : static void init_acb - * Purpose : initialize the internal structures for a given SCSI host - * Inputs : host - pointer to this host adapter's structure - *********************************************************************** - */ + * @acb: The adapter from which all devices should be removed. + **/ static -int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq) +void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb) { - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; - struct NvRamType *eeprom = &acb->eeprom; - u16 i; + struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *tmp; + dprintkdbg(DBG_DCB, "adapter_remove_and_free_all_devices: Free all devices (%i devices)\n", + list_size(&acb->dcb_list)); - host->max_cmd_len = 24; - host->can_queue = DC395x_MAX_CMD_QUEUE; - host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN; - host->this_id = (int) eeprom->scsi_id; - host->io_port = io_port; - host->n_io_port = 0x80; - host->dma_channel = -1; - host->unique_id = io_port; - host->irq = irq; - host->last_reset = jiffies; + list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) + adapter_remove_and_free_device(acb, dcb); +} - host->max_id = 16; - if (host->max_id - 1 == eeprom->scsi_id) - host->max_id--; -#ifdef CONFIG_SCSI_MULTI_LUN - if (eeprom->channel_cfg & NAC_SCANLUN) - host->max_lun = 8; - else - host->max_lun = 1; -#else - host->max_lun = 1; -#endif - /* - ******************************** - */ - acb->scsi_host = host; - acb->IOPortBase = (u16) io_port; - acb->dcb_run_robin = NULL; - acb->active_dcb = NULL; - acb->srb_count = DC395x_MAX_SRB_CNT; - acb->scsi_host->this_id = eeprom->scsi_id; - acb->hostid_bit = (1 << acb->scsi_host->this_id); - /*acb->scsi_host->this_lun = 0; */ - acb->irq_level = irq; - acb->tag_max_num = 1 << eeprom->max_tag; - if (acb->tag_max_num > 30) - acb->tag_max_num = 30; - acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */ - acb->scan_devices = 1; - acb->msg_len = 0; - acb->gmode2 = eeprom->channel_cfg; - if (eeprom->channel_cfg & NAC_SCANLUN) - acb->lun_chk = 1; - /* - * link all device's SRB Q of this adapter - */ - if (alloc_sg_tables(acb)) { - dprintkl(KERN_DEBUG, "SG table allocation failed!\n"); - return 1; - } -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - if (alloc_tracebufs(acb)) { - dprintkl(KERN_DEBUG, "SG trace buffer allocation failed!\n"); - free_sg_tables(acb, DC395x_MAX_SRB_CNT); - return 1; - } -#endif - INIT_LIST_HEAD(&acb->dcb_list); - INIT_LIST_HEAD(&acb->srb_free_list); - link_srb(acb); +/** + * dc395x_slave_alloc - Called by the scsi mid layer to tell us about a new + * scsi device that we need to deal with. We allocate a new device and then + * insert that device into the adapters device list. + * + * @scsi_device: The new scsi device that we need to handle. + **/ +static +int dc395x_slave_alloc(struct scsi_device *scsi_device) +{ + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; + struct DeviceCtlBlk *dcb; - /* - * temp SRB for Q tag used or abort command used - */ - acb->tmp_srb = &acb->srb; - init_timer(&acb->waiting_timer); + dcb = device_alloc(acb, scsi_device->id, scsi_device->lun); + if (!dcb) + return -ENOMEM; + adapter_add_device(acb, dcb); - for (i = 0; i < DC395x_MAX_SCSI_ID; i++) - acb->dcb_map[i] = 0; - dprintkdbg(DBG_0, "acb = %p, pdcb_map = %p, psrb_array = %p\n", acb, - acb->dcb_map, acb->srb_array); - dprintkdbg(DBG_0, "ACB size= %04x, DCB size= %04x, SRB size= %04x\n", - sizeof(struct AdapterCtlBlk), sizeof(struct DeviceCtlBlk), - sizeof(struct ScsiReqBlk)); return 0; } -/*=========================================================================== - Init - ===========================================================================*/ /** - * init_adapter - Initialize the SCSI chip control registers - * - * @host: This hosts adapter strcuture - * @io_port: The base I/O port - * @irq: IRQ + * dc395x_slave_destroy - Called by the scsi mid layer to tell us about a + * device that is going away. * - * Returns 0 if the initialization succeeds, any other value on failure. + * @scsi_device: The new scsi device that we need to handle. **/ static -int __init init_adapter(struct Scsi_Host *host, u32 io_port, u8 irq) +void dc395x_slave_destroy(struct scsi_device *scsi_device) { - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; - struct NvRamType *eeprom = &acb->eeprom; - - if (!request_region(io_port, host->n_io_port, DC395X_NAME)) { - dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); - return -1; - } - if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) { - /* release the region we just claimed */ - release_region(io_port, host->n_io_port); - dprintkl(KERN_INFO, "Failed to register IRQ!\n"); - return -1; - } - - acb->IOPortBase = io_port; - - /* selection timeout = 250 ms */ - acb->sel_timeout = DC395x_SEL_TIMEOUT; - - /* Mask all the interrupt */ - DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00); - DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00); - - /* Reset SCSI module */ - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE); - - /* Reset PCI/DMA module */ - DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE); - udelay(20); - - /* program configuration 0 */ - acb->config = HCC_AUTOTERM | HCC_PARITY; - if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI) - acb->config |= HCC_WIDE_CARD; - - if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET) - acb->config |= HCC_SCSI_RESET; - - if (acb->config & HCC_SCSI_RESET) { - dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n"); - DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI); - - /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */ - /*spin_unlock_irq (&io_request_lock); */ - udelay(500); + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; + struct DeviceCtlBlk *dcb = find_dcb(acb, scsi_device->id, scsi_device->lun); + if (dcb) + adapter_remove_and_free_device(acb, dcb); +} - acb->scsi_host->last_reset = - jiffies + HZ / 2 + - HZ * acb->eeprom.delay_time; - /*spin_lock_irq (&io_request_lock); */ - } - set_basic_config(acb); - return 0; -} /** @@ -5363,20 +5145,161 @@ void __init check_eeprom(struct NvRamType *eeprom, u16 io_port) } + + /** - * print_config - print adapter connection and termination + * print_eeprom_settings - output the eeprom settings + * to the kernel log so people can see what they were. + * + * @eeprom: The eeprom data strucutre to show details for. + **/ +static +void __init print_eeprom_settings(struct NvRamType *eeprom) +{ + dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", + eeprom->scsi_id, + eeprom->target[0].period, + clock_speed[eeprom->target[0].period] / 10, + clock_speed[eeprom->target[0].period] % 10, + eeprom->target[0].cfg0); + dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", + eeprom->channel_cfg, + eeprom->max_tag, + 1 << eeprom->max_tag, + eeprom->delay_time); +} + + + +#if debug_enabled(DBG_TRACE|DBG_TRACEALL) +/* + * Memory for trace buffers + */ +static +void free_tracebufs(struct AdapterCtlBlk *acb) +{ + int i; + const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; + + for (i = 0; i < srb_idx; i += bufs_per_page) + if (acb->srb_array[i].debugtrace) + dc395x_kfree(acb->srb_array[i].debugtrace); +} + + +static +int alloc_tracebufs(struct AdapterCtlBlk *acb) +{ + const unsigned mem_needed = + (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ; + int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; + const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; + int srb_idx = 0; + unsigned i = 0; + unsigned char *ptr; + + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) + acb->srb_array[i].debugtrace = NULL; + + while (pages--) { + ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!ptr) { + free_tracebufs(acb); + return 1; + } + /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */ + /* PAGE_SIZE, ptr, srb_idx); */ + i = 0; + while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT) + acb->srb_array[srb_idx++].debugtrace = + ptr + (i++ * DEBUGTRACEBUFSZ); + } + if (i < bufs_per_page) { + acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ); + acb->srb.debugtrace[0] = 0; + } else + dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n"); + return 0; +} +#else +static void free_tracebufs(struct AdapterCtlBlk *acb) {} +static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; } +#endif + +/* Free SG tables */ +static +void adapter_sg_tables_free(struct AdapterCtlBlk *acb) +{ + int i; + const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry)); + + for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) + if (acb->srb_array[i].segment_x) + dc395x_kfree(acb->srb_array[i].segment_x); +} + + +/* + * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) + * should never cross a page boundary */ +static +int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) +{ + const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1) + *DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry); + int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE; + const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY + *sizeof(struct SGentry)); + int srb_idx = 0; + unsigned i = 0; + struct SGentry *ptr; + + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) + acb->srb_array[i].segment_x = NULL; + + dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); + while (pages--) { + ptr = (struct SGentry *)dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!ptr) { + adapter_sg_tables_free(acb); + return 1; + } + dprintkdbg(DBG_1, "Allocate %li bytes at %p for SG segments %i\n", + PAGE_SIZE, ptr, srb_idx); + i = 0; + while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT) + acb->srb_array[srb_idx++].segment_x = + ptr + (i++ * DC395x_MAX_SG_LISTENTRY); + } + if (i < srbs_per_page) + acb->srb.segment_x = + ptr + (i * DC395x_MAX_SG_LISTENTRY); + else + dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); + return 0; +} + + + +/** + * adapter_print_config - print adapter connection and termination * config * - * @acb: adapter control block + * The io port in the adapter needs to have been set before calling + * this function. + * + * @acb: The adapter to print the information for. **/ static -void __init print_config(struct AdapterCtlBlk *acb) +void __init adapter_print_config(struct AdapterCtlBlk *acb) { u8 bval; bval = DC395x_read8(acb, TRM_S1040_GEN_STATUS); - dprintkl(KERN_INFO, "%c: Connectors: ", - ((bval & WIDESCSI) ? 'W' : ' ')); + dprintkl(KERN_INFO, "%s Connectors: ", + ((bval & WIDESCSI) ? "(Wide)" : "")); if (!(bval & CON5068)) printk("ext%s ", !(bval & EXT68HIGH) ? "68" : "50"); if (!(bval & CON68)) @@ -5403,77 +5326,290 @@ void __init print_config(struct AdapterCtlBlk *acb) /** - * print_eeprom_settings - output the eeprom settings - * to the kernel log so people can see what they were. + * adapter_init_params - Initialize the various parameters in the + * adapter structure. Note that the pointer to the scsi_host is set + * early (when this instance is created) and the io_port and irq + * values are set later after they have been reserved. This just gets + * everything set to a good starting position. * - * @eeprom: The eeprom data strucutre to show details for. + * The eeprom structure in the adapter needs to have been set before + * calling this function. + * + * @acb: The adapter to initialize. **/ static -void __init print_eeprom_settings(struct NvRamType *eeprom) +void __init adapter_init_params(struct AdapterCtlBlk *acb) { - dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", - eeprom->scsi_id, - eeprom->target[0].period, - clock_speed[eeprom->target[0].period] / 10, - clock_speed[eeprom->target[0].period] % 10, - eeprom->target[0].cfg0); - dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", - eeprom->channel_cfg, - eeprom->max_tag, - 1 << eeprom->max_tag, - eeprom->delay_time); + struct NvRamType *eeprom = &acb->eeprom; + int i; + + /* NOTE: acb->scsi_host is set at scsi_host/acb creation time */ + /* NOTE: acb->io_port_base is set at port registration time */ + /* NOTE: acb->io_port_len is set at port registration time */ + + INIT_LIST_HEAD(&acb->dcb_list); + acb->dcb_run_robin = NULL; + acb->active_dcb = NULL; + + INIT_LIST_HEAD(&acb->srb_free_list); + /* temp SRB for Q tag used or abort command used */ + acb->tmp_srb = &acb->srb; + init_timer(&acb->waiting_timer); + init_timer(&acb->selto_timer); + + acb->srb_count = DC395x_MAX_SRB_CNT; + + acb->sel_timeout = DC395x_SEL_TIMEOUT; /* timeout=250ms */ + /* NOTE: acb->irq_level is set at IRQ registration time */ + + acb->tag_max_num = 1 << eeprom->max_tag; + if (acb->tag_max_num > 30) + acb->tag_max_num = 30; + + acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */ + acb->gmode2 = eeprom->channel_cfg; + acb->config = 0; /* NOTE: actually set in adapter_init_chip */ + + if (eeprom->channel_cfg & NAC_SCANLUN) + acb->lun_chk = 1; + acb->scan_devices = 1; + + acb->scsi_host->this_id = eeprom->scsi_id; + acb->hostid_bit = (1 << acb->scsi_host->this_id); + + for (i = 0; i < DC395x_MAX_SCSI_ID; i++) + acb->dcb_map[i] = 0; + + acb->msg_len = 0; + + /* link static array of srbs into the srb free list */ + for (i = 0; i < acb->srb_count - 1; i++) + srb_free_insert(acb, &acb->srb_array[i]); } -/* - ********************************************************************* - * DC395x_detect +/** + * adapter_init_host - Initialize the scsi host instance based on + * values that we have already stored in the adapter instance. There's + * some mention that a lot of these are deprecated, so we won't use + * them (we'll use the ones in the adapter instance) but we'll fill + * them in in case something else needs them. * - * Function : static int host_init (struct Scsi_Host *host) - * Purpose : initialize the internal structures for a given SCSI host - * Inputs : host - pointer to this host adapter's structure/ - * Preconditions : when this function is called, the chip_type - * field of the acb structure MUST have been set. - ********************************************************************* - */ + * The eeprom structure, irq and io ports in the adapter need to have + * been set before calling this function. + * + * @host: The scsi host instance to fill in the values for. + **/ static -struct Scsi_Host *__init host_init(Scsi_Host_Template * host_template, - u32 io_port, u8 irq) +void __init adapter_init_scsi_host(struct Scsi_Host *host) { - struct Scsi_Host *host; - struct AdapterCtlBlk *acb; + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; + struct NvRamType *eeprom = &acb->eeprom; + + host->max_cmd_len = 24; + host->can_queue = DC395x_MAX_CMD_QUEUE; + host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN; + host->this_id = (int)eeprom->scsi_id; + host->io_port = acb->io_port_base; + host->n_io_port = acb->io_port_len; + host->dma_channel = -1; + host->unique_id = acb->io_port_base; + host->irq = acb->irq_level; + host->last_reset = jiffies; - host = scsi_host_alloc(host_template, sizeof(struct AdapterCtlBlk)); - if (!host) { - dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); + host->max_id = 16; + if (host->max_id - 1 == eeprom->scsi_id) + host->max_id--; + +#ifdef CONFIG_SCSI_MULTI_LUN + if (eeprom->channel_cfg & NAC_SCANLUN) + host->max_lun = 8; + else + host->max_lun = 1; +#else + host->max_lun = 1; +#endif + +} + + +/** + * adapter_init_chip - Get the chip into a know state and figure out + * some of the settings that apply to this adapter. + * + * The io port in the adapter needs to have been set before calling + * this function. The config will be configured correctly on return. + * + * @acb: The adapter which we are to init. + **/ +void __init adapter_init_chip(struct AdapterCtlBlk *acb) +{ + struct NvRamType *eeprom = &acb->eeprom; + + /* Mask all the interrupt */ + DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00); + DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00); + + /* Reset SCSI module */ + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE); + + /* Reset PCI/DMA module */ + DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE); + udelay(20); + + /* program configuration 0 */ + acb->config = HCC_AUTOTERM | HCC_PARITY; + if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI) + acb->config |= HCC_WIDE_CARD; + + if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET) + acb->config |= HCC_SCSI_RESET; + + if (acb->config & HCC_SCSI_RESET) { + dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n"); + DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI); + + /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */ + /*spin_unlock_irq (&io_request_lock); */ + udelay(500); + + acb->scsi_host->last_reset = + jiffies + HZ / 2 + + HZ * acb->eeprom.delay_time; + + /*spin_lock_irq (&io_request_lock); */ + } +} + + +/** + * init_adapter - Grab the resource for the card, setup the adapter + * information, set the card into a known state, create the various + * tables etc etc. This basically gets all adapter information all up + * to date, intialised and gets the chip in sync with it. + * + * @host: This hosts adapter structure + * @io_port: The base I/O port + * @irq: IRQ + * + * Returns 0 if the initialization succeeds, any other value on + * failure. + **/ +static +int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, u32 io_port_len, u8 irq) +{ + if (!request_region(io_port, io_port_len, DC395X_NAME)) { + dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); goto failed; } - acb = (struct AdapterCtlBlk *)host->hostdata; + /* store port base to indicate we have registered it */ + acb->io_port_base = io_port; + acb->io_port_len = io_port_len; + + if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) { + /* release the region we just claimed */ + dprintkl(KERN_INFO, "Failed to register IRQ\n"); + goto failed; + } + /* store irq to indicate we have registered it */ + acb->irq_level = irq; + /* get eeprom configuration information and command line settings etc */ check_eeprom(&acb->eeprom, (u16)io_port); print_eeprom_settings(&acb->eeprom); - if (init_acb(host, io_port, irq)) { + /* setup adapter control block */ + adapter_init_params(acb); + + /* display card connectors/termination settings */ + adapter_print_config(acb); + + if (adapter_sg_tables_alloc(acb)) { + dprintkl(KERN_DEBUG, "Memory allocation for SG tables failed\n"); goto failed; } - print_config(acb); - - if (init_adapter(host, io_port, irq)) { - dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); + if (alloc_tracebufs(acb)) { + dprintkl(KERN_DEBUG, "Memory allocation for trace buffers failed\n"); goto failed; } + adapter_init_scsi_host(acb->scsi_host); + adapter_init_chip(acb); + set_basic_config(acb); - return host; + dprintkdbg(DBG_0, "adapter_init: acb=%p, pdcb_map=%p " + "psrb_array=%p ACB size=%04x, DCB size=%04x " + "SRB size=%04x\n", + acb, acb->dcb_map, acb->srb_array, sizeof(struct AdapterCtlBlk), + sizeof(struct DeviceCtlBlk), sizeof(struct ScsiReqBlk)); + return 0; failed: - if (host) - scsi_host_put(host); - return NULL; + if (acb->irq_level) + free_irq(acb->irq_level, acb); + if (acb->io_port_base) + release_region(acb->io_port_base, acb->io_port_len); + adapter_sg_tables_free(acb); + free_tracebufs(acb); + + return 1; } -#undef SEARCH -#undef YESNO -#undef SCANF + +/** + * adapter_uninit_chip - cleanly shut down the scsi controller chip, + * stopping all operations and disabling interrupt generation on the + * card. + * + * @acb: The adapter which we are to shutdown. + **/ +static +void adapter_uninit_chip(struct AdapterCtlBlk *acb) +{ + /* disable interrupts */ + DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0); + DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0); + + /* reset the scsi bus */ + if (acb->config & HCC_SCSI_RESET) + reset_scsi_bus(acb); + + /* clear any pending interupt state */ + DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); +} + + + +/** + * adapter_uninit - Shut down the chip and release any resources that + * we had allocated. Once this returns the adapter should not be used + * anymore. + * + * @acb: The adapter which we are to un-initialize. + **/ +static +void adapter_uninit(struct AdapterCtlBlk *acb) +{ + unsigned long flags; + DC395x_LOCK_IO(acb->scsi_host, flags); + + /* remove timers */ + if (timer_pending(&acb->waiting_timer)) + del_timer(&acb->waiting_timer); + if (timer_pending(&acb->selto_timer)) + del_timer(&acb->selto_timer); + + adapter_uninit_chip(acb); + adapter_remove_and_free_all_devices(acb); + DC395x_UNLOCK_IO(acb->scsi_host, flags); + + if (acb->irq_level) + free_irq(acb->irq_level, acb); + if (acb->io_port_base) + release_region(acb->io_port_base, acb->io_port_len); + + adapter_sg_tables_free(acb); + free_tracebufs(acb); +} /* @@ -5500,6 +5636,7 @@ failed: #undef SPRINTF #define SPRINTF(args...) pos += sprintf(pos, args) +#undef YESNO #define YESNO(YN) \ if (YN) SPRINTF(" Yes ");\ else SPRINTF(" No ") @@ -5526,7 +5663,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o SPRINTF("SCSI Host Nr %i, ", host->host_no); SPRINTF("DC395U/UW/F DC315/U %s\n", (acb->config & HCC_WIDE_CARD) ? "Wide" : ""); - SPRINTF("IOPortBase 0x%04x, ", acb->IOPortBase); + SPRINTF("io_port_base 0x%04x, ", acb->io_port_base); SPRINTF("irq_level 0x%02x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); @@ -5633,84 +5770,6 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o } -/** - * chip_shutdown - cleanly shut down the scsi controller chip, - * stopping all operations and disablig interrupt generation on the - * card. - * - * @acb: The scsi adapter control block of the adapter to shut down. - **/ -static -void chip_shutdown(struct AdapterCtlBlk *acb) -{ - /* disable interrupt */ - DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0); - DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0); - - /* remove timers */ - if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); - if (timer_pending(&acb->selto_timer)) - del_timer(&acb->selto_timer); - - /* reset the scsi bus */ - if (acb->config & HCC_SCSI_RESET) - reset_scsi_bus(acb); - - /* clear any pending interupt state */ - DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); - - /* release chip resources */ -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - free_tracebufs(acb, DC395x_MAX_SRB_CNT); -#endif - free_sg_tables(acb, DC395x_MAX_SRB_CNT); -} - - -/** - * free_dcbs - Free all of the DCBs. - * - * @acb: Adapter to remove the DCBs for. - **/ -static -void free_dcbs(struct AdapterCtlBlk* acb) -{ - struct DeviceCtlBlk *dcb; - struct DeviceCtlBlk *tmp; - - dprintkdbg(DBG_DCB, "Free %i DCBs\n", list_size(&acb->dcb_list)); - - list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) { - dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n", - dcb->target_id, dcb->target_lun, dcb); - remove_dev(acb, dcb); - } -} - -/** - * host_release - shutdown device and release resources that were - * allocate for it. Called once for each card as it is shutdown. - * - * @host: The adapter instance to shutdown. - **/ -static -void host_release(struct Scsi_Host *host) -{ - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(host->hostdata); - unsigned long flags; - - dprintkl(KERN_DEBUG, "DC395x release\n"); - - DC395x_LOCK_IO(acb->scsi_host, flags); - chip_shutdown(acb); - free_dcbs(acb); - - free_irq(host->irq, acb); - release_region(host->io_port, host->n_io_port); - - DC395x_UNLOCK_IO(acb->scsi_host, flags); -} /* @@ -5737,6 +5796,22 @@ static Scsi_Host_Template dc395x_driver_template = { /** + * banner_display - Display banner on first instance of driver + * initialized. + **/ +static +void banner_display(void) +{ + static int banner_done = 0; + if (!banner_done) + { + dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION); + banner_done = 1; + } +} + + +/** * dc395x_init_one - Initialise a single instance of the adapter. * * The PCI layer will call this once for each instance of the adapter @@ -5753,51 +5828,55 @@ static int __devinit dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - unsigned int io_port; - u8 irq; struct Scsi_Host *scsi_host; - static int banner_done = 0; - int error = 0; - - dprintkdbg(DBG_0, "Init one instance of the dc395x\n"); - if (!banner_done) - { - dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION); - banner_done = 1; - } + struct AdapterCtlBlk *acb; + unsigned int io_port_base; + unsigned int io_port_len; + u8 irq; + + dprintkdbg(DBG_0, "Init one instance (%s)\n", pci_name(dev)); + banner_display(); if (pci_enable_device(dev)) { dprintkl(KERN_INFO, "PCI Enable device failed.\n"); return -ENODEV; } - - dprintkdbg(DBG_0, "Get resources...\n"); - io_port = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK; + io_port_base = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK; + io_port_len = pci_resource_len(dev, 0); irq = dev->irq; - dprintkdbg(DBG_0, "IO_PORT=%04x,IRQ=%x\n", (unsigned int) io_port, irq); + dprintkdbg(DBG_0, "IO_PORT=%04x, IRQ=%x\n", io_port_base, dev->irq); - scsi_host = host_init(&dc395x_driver_template, io_port, irq); - if (!scsi_host) - { - dprintkdbg(DBG_0, "host_init failed\n"); + /* allocate scsi host information (includes out adapter) */ + scsi_host = scsi_host_alloc(&dc395x_driver_template, + sizeof(struct AdapterCtlBlk)); + if (!scsi_host) { + dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); return -ENOMEM; } - ((struct AdapterCtlBlk *)(scsi_host->hostdata))->dev = dev; + acb = (struct AdapterCtlBlk*)scsi_host->hostdata; + acb->scsi_host = scsi_host; + + /* initialise the adapter and everything we need */ + if (adapter_init(acb, io_port_base, io_port_len, irq)) { + dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); + scsi_host_put(scsi_host); + return -ENODEV; + } + pci_set_master(dev); - pci_set_drvdata(dev, scsi_host); /* get the scsi mid level to scan for new devices on the bus */ - error = scsi_add_host(scsi_host, &dev->dev); - if (error) { + if (scsi_add_host(scsi_host, &dev->dev)) { dprintkl(KERN_ERR, "scsi_add_host failed\n"); - error = -ENODEV; - host_release(scsi_host); + adapter_uninit(acb); scsi_host_put(scsi_host); - } else - scsi_scan_host(scsi_host); + return -ENODEV; + } + pci_set_drvdata(dev, scsi_host); + scsi_scan_host(scsi_host); - return error; + return 0; } @@ -5809,16 +5888,14 @@ int __devinit dc395x_init_one(struct pci_dev *dev, **/ static void __devexit dc395x_remove_one(struct pci_dev *dev) { - struct Scsi_Host *host = pci_get_drvdata(dev); + struct Scsi_Host *scsi_host = pci_get_drvdata(dev); + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata); dprintkdbg(DBG_0, "Removing instance\n"); - if (!host) { - dprintkl(KERN_ERR, "no host allocated\n"); - return; - } - scsi_remove_host(host); - host_release(host); - scsi_host_put(host); + + scsi_remove_host(scsi_host); + adapter_uninit(acb); + scsi_host_put(scsi_host); pci_set_drvdata(dev, NULL); } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 19b77daaf4ee..6ffd2df205b6 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4990,7 +4990,7 @@ static int ioc_resetdrv(unsigned long arg, char *cmnd) cmd.u.cache.DeviceNo = res.number; #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5091,7 +5091,7 @@ static int ioc_general(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5164,7 +5164,7 @@ static int ioc_hdrlist(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5253,7 +5253,7 @@ static int ioc_rescan(unsigned long arg, char *cmnd) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return -ENOMEM; srp->sr_cmd_len = 12; @@ -5631,7 +5631,7 @@ static void gdth_flush(int hanum) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return; srp->sr_cmd_len = 12; @@ -5727,7 +5727,7 @@ void gdth_halt(void) TRACE2(("gdth_halt(): reset controller %d\n", hanum)); #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev); + srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) { #if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 9c4485b2fd1c..ef67f26855fd 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -44,7 +44,7 @@ static int gdth_set_info(char *buffer,int length,int hanum,int busnum) #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_request(sdev); + scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; @@ -797,7 +797,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset, #if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_request(sdev); + scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 3c8377c3aa48..bcee9b28fbfe 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -86,6 +86,7 @@ int imm_release(struct Scsi_Host *host) int host_no = host->unique_id; printk("Releasing imm%i\n", host_no); + scsi_unregister(host); parport_unregister_device(imm_hosts[host_no].dev); return 0; } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 46b0069406e9..7213e6263642 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -199,7 +199,7 @@ MODULE_PARM(ips, "s"); #define IPS_VERSION_LOW ".90-BETA" #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) -#error "This driver has only been tested on the x86/ia64/x86_64 platforms" +#warning "This driver has only been tested on the x86/ia64/x86_64 platforms" #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) @@ -284,9 +284,9 @@ IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */ /* This table describes all ServeRAID Adapters */ static struct pci_device_id ips_pci_table[] = { { 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, } + { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, + { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, + { 0, } }; MODULE_DEVICE_TABLE( pci, ips_pci_table ); @@ -300,7 +300,7 @@ struct pci_driver ips_pci_driver = { .name = ips_hot_plug_name, .id_table = ips_pci_table, .probe = ips_insert_device, - .remove = __devexit_p(ips_remove_device), + .remove = __devexit_p(ips_remove_device), }; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index f0e8d85e6500..4fa1a9955ddf 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4357,19 +4357,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } cp->cmd = cmd; - /*--------------------------------------------------- - ** - ** Enable tagged queue if asked by scsi ioctl - ** - **---------------------------------------------------- - */ -#if 0 /* This stuff was only useful for linux-1.2.13 */ - if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) { - lp->numtags = tp->usrtags; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); - } -#endif - /*---------------------------------------------------- ** ** Build the identify / tag / sdtr message diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 48afbdd2faa8..c6bfb85db04b 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -316,7 +316,7 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp, static int repeat = 0; #endif if (SRpnt == NULL) { - if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) { + if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) { printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp)); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index f8ebdb8bbfc4..5de0a6329d8a 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -3655,7 +3655,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -3955,7 +3955,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -4915,7 +4915,7 @@ qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) } else printk(" Async"); - if (device->tagged_queue) + if (device->simple_tags) printk(", Tagged queuing: depth %d", device->queue_depth); printk("\n"); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d5894886fcea..cda15b271b21 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -113,26 +113,21 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = { * * Purpose: Allocate a request descriptor. * - * Arguments: device - device for which we want a request + * Arguments: device - device for which we want a request + * gfp_mask - allocation flags passed to kmalloc * * Lock status: No locks assumed to be held. This function is SMP-safe. * * Returns: Pointer to request block. - * - * Notes: With the new queueing code, it becomes important - * to track the difference between a command and a - * request. A request is a pending item in the queue that - * has not yet reached the top of the queue. - * - * XXX(hch): Need to add a gfp_mask argument. */ -struct scsi_request *scsi_allocate_request(struct scsi_device *sdev) +struct scsi_request *scsi_allocate_request(struct scsi_device *sdev, + int gfp_mask) { const int offset = ALIGN(sizeof(struct scsi_request), 4); const int size = offset + sizeof(struct request); struct scsi_request *sreq; - sreq = kmalloc(size, GFP_ATOMIC); + sreq = kmalloc(size, gfp_mask); if (likely(sreq != NULL)) { memset(sreq, 0, size); sreq->sr_request = (struct request *)(((char *)sreq) + offset); @@ -1006,9 +1001,12 @@ static int __init init_scsi(void) error = scsi_init_hosts(); if (error) goto cleanup_devlist; - error = scsi_sysfs_register(); + error = scsi_init_sysctl(); if (error) goto cleanup_hosts; + error = scsi_sysfs_register(); + if (error) + goto cleanup_sysctl; for (i = 0; i < NR_CPUS; i++) INIT_LIST_HEAD(&done_q[i]); @@ -1018,6 +1016,8 @@ static int __init init_scsi(void) printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; +cleanup_sysctl: + scsi_exit_sysctl(); cleanup_hosts: scsi_exit_hosts(); cleanup_devlist: @@ -1034,6 +1034,7 @@ cleanup_queue: static void __exit exit_scsi(void) { scsi_sysfs_unregister(); + scsi_exit_sysctl(); scsi_exit_hosts(); scsi_exit_devinfo(); devfs_remove("scsi"); diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 8424c445c6b7..4b5a903704b4 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -381,6 +381,7 @@ int scsi_get_device_flags(unsigned char *vendor, unsigned char *model) return scsi_default_dev_flags; } +#ifdef CONFIG_SCSI_PROC_FS /* * proc_scsi_dev_info_read: dump the scsi_dev_info_list via * /proc/scsi/device_info @@ -451,6 +452,7 @@ out: free_page((unsigned long)buffer); return err; } +#endif /* CONFIG_SCSI_PROC_FS */ module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0); MODULE_PARM_DESC(dev_flags, @@ -471,7 +473,9 @@ void scsi_exit_devinfo(void) struct list_head *lh, *lh_next; struct scsi_dev_info_list *devinfo; +#ifdef CONFIG_SCSI_PROC_FS remove_proc_entry("scsi/device_info", 0); +#endif list_for_each_safe(lh, lh_next, &scsi_dev_info_list) { devinfo = list_entry(lh, struct scsi_dev_info_list, @@ -490,7 +494,9 @@ void scsi_exit_devinfo(void) **/ int scsi_init_devinfo(void) { +#ifdef CONFIG_SCSI_PROC_FS struct proc_dir_entry *p; +#endif int error, i; error = scsi_dev_info_list_add_str(scsi_dev_flags); @@ -507,6 +513,7 @@ int scsi_init_devinfo(void) goto out; } +#ifdef CONFIG_SCSI_PROC_FS p = create_proc_entry("scsi/device_info", 0, NULL); if (!p) { error = -ENOMEM; @@ -516,6 +523,7 @@ int scsi_init_devinfo(void) p->owner = THIS_MODULE; p->get_info = proc_scsi_devinfo_read; p->write_proc = proc_scsi_devinfo_write; +#endif /* CONFIG_SCSI_PROC_FS */ out: if (error) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 6e4906ab2241..fce6a580363c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1339,7 +1339,7 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd) **/ static void scsi_eh_lock_door(struct scsi_device *sdev) { - struct scsi_request *sreq = scsi_allocate_request(sdev); + struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (unlikely(!sreq)) { printk(KERN_ERR "%s: request allocate failed," diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 3dfdcf1f5bc8..53d4b5dd5344 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -98,7 +98,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { printk("SCSI internal ioctl failed, no memory\n"); return -ENOMEM; @@ -321,7 +321,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, break; } - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_KERNEL); if (!sreq) { result = -EINTR; goto error; @@ -408,30 +408,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg) return 0; case SCSI_IOCTL_GET_BUS_NUMBER: return put_user(sdev->host->host_no, (int *)arg); - /* - * The next two ioctls either need to go or need to be changed to - * pass tagged queueing changes through the low level drivers. - * Simply enabling or disabling tagged queueing without the knowledge - * of the low level driver is a *BAD* thing. - * - * Oct. 10, 2002 - Doug Ledford <dledford@redhat.com> - */ - case SCSI_IOCTL_TAGGED_ENABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!sdev->tagged_supported) - return -EINVAL; - sdev->tagged_queue = 1; - sdev->current_tag = 1; - return 0; - case SCSI_IOCTL_TAGGED_DISABLE: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!sdev->tagged_supported) - return -EINVAL; - sdev->tagged_queue = 0; - sdev->current_tag = 0; - return 0; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(sdev->host, arg); case SCSI_IOCTL_SEND_COMMAND: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 415be0cf47b0..e9e374cbdb4f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1454,7 +1454,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data) { - struct scsi_request *sreq = scsi_allocate_request(sdev); + struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); int ret; if (!sreq) diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h index a282c84c8ef5..b0a31a11ffcf 100644 --- a/drivers/scsi/scsi_logging.h +++ b/drivers/scsi/scsi_logging.h @@ -37,39 +37,23 @@ #define SCSI_LOG_HLCOMPLETE_BITS 3 #define SCSI_LOG_IOCTL_BITS 3 +extern unsigned int scsi_logging_level; #ifdef CONFIG_SCSI_LOGGING -extern unsigned int scsi_logging_level; #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ { \ unsigned int mask = (1 << (BITS)) - 1; \ if (((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL)) \ (CMD); \ } - -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \ -{ \ - unsigned int mask = ((1 << (BITS)) - 1) << SHIFT; \ - scsi_logging_level = ((scsi_logging_level & ~mask) \ - | ((LEVEL << SHIFT) & mask)); \ -} #else -/* - * With no logging enabled, stub these out so they don't do anything. - */ #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) #endif /* CONFIG_SCSI_LOGGING */ /* * These are the macros that are actually used throughout the code to * log events. If logging isn't enabled, they are no-ops and will be * completely absent from the user's code. - * - * The 'set' versions of the macros are really intended to only be called - * from the /proc filesystem, and in production kernels this will be about - * all that is ever used. It could be useful in a debugging environment to - * bump the logging level when certain strange events are detected, however. */ #define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \ SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD); @@ -92,26 +76,4 @@ extern unsigned int scsi_logging_level; #define SCSI_LOG_IOCTL(LEVEL,CMD) \ SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD); - -#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL); -#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL); -#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL); -#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL); -#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL); -#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL); -#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_IOCTL_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); - #endif /* _SCSI_LOGGING_H */ diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 8608752c0fa4..62123cefb4c3 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -1,6 +1,17 @@ #ifndef _SCSI_PRIV_H #define _SCSI_PRIV_H +#include <linux/config.h> +#include <linux/device.h> + +struct request_queue; +struct scsi_cmnd; +struct scsi_device; +struct scsi_host_template; +struct scsi_request; +struct Scsi_Host; + + /* * These are the values that the owner field can take. * They are used as an indication of who the command belongs to. @@ -98,7 +109,7 @@ extern int scsi_init_queue(void); extern void scsi_exit_queue(void); /* scsi_proc.c */ -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS extern void scsi_proc_hostdir_add(struct scsi_host_template *); extern void scsi_proc_hostdir_rm(struct scsi_host_template *); extern void scsi_proc_host_add(struct Scsi_Host *); @@ -115,12 +126,21 @@ extern void scsi_exit_procfs(void); #endif /* CONFIG_PROC_FS */ /* scsi_scan.c */ -int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int, - unsigned int, int); +extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, + unsigned int, unsigned int, int); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_free_sdev(struct scsi_device *); extern void scsi_rescan_device(struct device *); +/* scsi_sysctl.c */ +#ifdef CONFIG_SYSCTL +extern int scsi_init_sysctl(void); +extern void scsi_exit_sysctl(void); +#else +# define scsi_init_sysctl() (0) +# define scsi_exit_sysctl() do { } while (0) +#endif /* CONFIG_SYSCTL */ + /* scsi_sysfs.c */ extern int scsi_device_register(struct scsi_device *); extern int scsi_sysfs_add_host(struct Scsi_Host *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index dd8bfd4b36c6..f72dd45bb651 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -37,9 +37,7 @@ /* 4K page size, but our output routines, use some slack for overruns */ #define PROC_BLOCK_SIZE (3*1024) -/* XXX: this shouldn't really be exposed to drivers. */ -struct proc_dir_entry *proc_scsi; -EXPORT_SYMBOL(proc_scsi); +static struct proc_dir_entry *proc_scsi; /* Protect sht->present and sht->proc_dir */ static DECLARE_MUTEX(global_host_template_sem); @@ -235,106 +233,28 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, char *buffer, *p; int err; - if (!buf || length>PAGE_SIZE) + if (!buf || length > PAGE_SIZE) return -EINVAL; buffer = (char *)__get_free_page(GFP_KERNEL); if (!buffer) return -ENOMEM; - if (copy_from_user(buffer, buf, length)) { - err =-EFAULT; + + err = -EFAULT; + if (copy_from_user(buffer, buf, length)) goto out; - } err = -EINVAL; - if (length < PAGE_SIZE) buffer[length] = '\0'; else if (buffer[PAGE_SIZE-1]) goto out; - if (length < 11 || strncmp("scsi", buffer, 4)) - goto out; - -#ifdef CONFIG_SCSI_LOGGING - /* - * Usage: echo "scsi log token #N" > /proc/scsi/scsi - * where token is one of [error,scan,mlqueue,mlcomplete,llqueue, - * llcomplete,hlqueue,hlcomplete] - */ - if (!strncmp("log", buffer + 5, 3)) { - char *token; - unsigned int level; - - p = buffer + 9; - token = p; - while (*p != ' ' && *p != '\t' && *p != '\0') { - p++; - } - - if (*p == '\0') { - if (strncmp(token, "all", 3) == 0) { - /* - * Turn on absolutely everything. - */ - scsi_logging_level = ~0; - } else if (strncmp(token, "none", 4) == 0) { - /* - * Turn off absolutely everything. - */ - scsi_logging_level = 0; - } else { - goto out; - } - } else { - *p++ = '\0'; - - level = simple_strtoul(p, NULL, 0); - - /* - * Now figure out what to do with it. - */ - if (strcmp(token, "error") == 0) { - SCSI_SET_ERROR_RECOVERY_LOGGING(level); - } else if (strcmp(token, "timeout") == 0) { - SCSI_SET_TIMEOUT_LOGGING(level); - } else if (strcmp(token, "scan") == 0) { - SCSI_SET_SCAN_BUS_LOGGING(level); - } else if (strcmp(token, "mlqueue") == 0) { - SCSI_SET_MLQUEUE_LOGGING(level); - } else if (strcmp(token, "mlcomplete") == 0) { - SCSI_SET_MLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "llqueue") == 0) { - SCSI_SET_LLQUEUE_LOGGING(level); - } else if (strcmp(token, "llcomplete") == 0) { - SCSI_SET_LLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "hlqueue") == 0) { - SCSI_SET_HLQUEUE_LOGGING(level); - } else if (strcmp(token, "hlcomplete") == 0) { - SCSI_SET_HLCOMPLETE_LOGGING(level); - } else if (strcmp(token, "ioctl") == 0) { - SCSI_SET_IOCTL_LOGGING(level); - } else { - goto out; - } - } - - printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level); - } -#endif /* CONFIG_SCSI_LOGGING */ - /* * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * Consider this feature BETA. - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware ! - * However perhaps it is legal to switch on an - * already connected device. It is perhaps not - * guaranteed this device doesn't corrupt an ongoing data transfer. */ - if (!strncmp("add-single-device", buffer + 5, 17)) { + if (!strncmp("scsi add-single-device", buffer, 22)) { p = buffer + 23; host = simple_strtoul(p, &p, 0); @@ -345,18 +265,12 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, err = scsi_add_single_device(host, channel, id, lun); if (err >= 0) err = length; + /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * - * Consider this feature pre-BETA. - * - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware and thoroughly confuse the SCSI subsystem. - * */ - } else if (!strncmp("remove-single-device", buffer + 5, 20)) { + } else if (!strncmp("scsi remove-single-device", buffer, 25)) { p = buffer + 26; host = simple_strtoul(p, &p, 0); @@ -366,8 +280,8 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, err = scsi_remove_single_device(host, channel, id, lun); } -out: - + + out: free_page((unsigned long)buffer); return err; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index cef0c4467a92..65807367d046 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -30,6 +30,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/blkdev.h> +#include <asm/semaphore.h> #include "scsi.h" #include "hosts.h" @@ -94,6 +95,13 @@ MODULE_PARM_DESC(max_report_luns, " between 1 and 16384)"); #endif +/* + * This mutex serializes all scsi scanning activity from kernel- and + * userspace. It could easily be made per-host but I'd like to avoid + * the overhead for now. + */ +static DECLARE_MUTEX(scsi_scan_mutex); + /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command * @sreq: used to send the command @@ -685,7 +693,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, sdev = scsi_alloc_sdev(host, channel, id, lun); if (!sdev) goto out; - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_ATOMIC); if (!sreq) goto out_free_sdev; result = kmalloc(256, GFP_ATOMIC | @@ -898,7 +906,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, if (bflags & BLIST_NOLUN) return 0; - sreq = scsi_allocate_request(sdev); + sreq = scsi_allocate_request(sdev, GFP_ATOMIC); if (!sreq) goto out; @@ -1067,9 +1075,12 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, struct scsi_device *sdev; int res; + down(&scsi_scan_mutex); res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1); if (res != SCSI_SCAN_LUN_PRESENT) sdev = ERR_PTR(-ENODEV); + up(&scsi_scan_mutex); + return sdev; } @@ -1191,11 +1202,14 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; + down(&scsi_scan_mutex); if (channel == SCAN_WILD_CARD) for (channel = 0; channel <= shost->max_channel; channel++) scsi_scan_channel(shost, channel, id, lun, rescan); else scsi_scan_channel(shost, channel, id, lun, rescan); + up(&scsi_scan_mutex); + return 0; } diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c new file mode 100644 index 000000000000..04d06c25132b --- /dev/null +++ b/drivers/scsi/scsi_sysctl.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003 Christoph Hellwig. + * Released under GPL v2. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sysctl.h> + +#include "scsi_logging.h" + + +static ctl_table scsi_table[] = { + { .ctl_name = DEV_SCSI_LOGGING_LEVEL, + .procname = "logging_level", + .data = &scsi_logging_level, + .maxlen = sizeof(scsi_logging_level), + .mode = 0644, + .proc_handler = &proc_dointvec }, + { } +}; + +static ctl_table scsi_dir_table[] = { + { .ctl_name = DEV_SCSI, + .procname = "scsi", + .mode = 0555, + .child = scsi_table }, + { } +}; + +static ctl_table scsi_root_table[] = { + { .ctl_name = CTL_DEV, + .procname = "dev", + .mode = 0555, + .child = scsi_dir_table }, + { } +}; + +static struct ctl_table_header *scsi_table_header; + +int __init scsi_init_sysctl(void) +{ + scsi_table_header = register_sysctl_table(scsi_root_table, 1); + if (!scsi_table_header) + return -ENOMEM; + return 0; +} + +void scsi_exit_sysctl(void) +{ + unregister_sysctl_table(scsi_table_header); +} diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2d9c592537b7..2bd0ee80e138 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -370,25 +370,24 @@ static int sd_open(struct inode *inode, struct file *filp) if (!scsi_block_when_processing_errors(sdev)) goto error_out; - if (sdev->removable) { + if (sdev->removable || sdkp->write_prot) check_disk_change(inode->i_bdev); - /* - * If the drive is empty, just let the open fail. - */ - retval = -ENOMEDIUM; - if ((!sdkp->media_present) && !(filp->f_flags & O_NDELAY)) - goto error_out; + /* + * If the drive is empty, just let the open fail. + */ + retval = -ENOMEDIUM; + if (sdev->removable && !sdkp->media_present && + !(filp->f_flags & O_NDELAY)) + goto error_out; - /* - * Similarly, if the device has the write protect tab set, - * have the open fail if the user expects to be able to write - * to the thing. - */ - retval = -EROFS; - if ((sdkp->write_prot) && (filp->f_mode & FMODE_WRITE)) - goto error_out; - } + /* + * If the device has the write protect tab set, have the open fail + * if the user expects to be able to write to the thing. + */ + retval = -EROFS; + if (sdkp->write_prot && (filp->f_mode & FMODE_WRITE)) + goto error_out; /* * It is possible that the disk changing stuff resulted in @@ -1174,7 +1173,7 @@ static int sd_revalidate_disk(struct gendisk *disk) if (!sdp->online) goto out; - sreq = scsi_allocate_request(sdp); + sreq = scsi_allocate_request(sdp, GFP_KERNEL); if (!sreq) { printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " "failure.\n"); @@ -1355,12 +1354,12 @@ static int sd_remove(struct device *dev) static void sd_shutdown(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - struct scsi_disk *sdkp; + struct scsi_disk *sdkp; struct scsi_request *sreq; int retries, res; - sdkp = dev_get_drvdata(dev); - if (!sdkp) + sdkp = dev_get_drvdata(dev); + if (!sdkp) return; /* this can happen */ if (!sdp->online || !sdkp->WCE) @@ -1369,7 +1368,7 @@ static void sd_shutdown(struct device *dev) printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", sdkp->disk->disk_name); - sreq = scsi_allocate_request(sdp); + sreq = scsi_allocate_request(sdp, GFP_KERNEL); if (!sreq) { printk("FAILED\n No memory for request\n"); return; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 813364338aea..0a5497ea2389 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -70,7 +70,7 @@ static int sg_version_num = 30529; /* 2 digits for each component */ #include "scsi_logging.h" -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS #include <linux/proc_fs.h> static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -222,7 +222,7 @@ static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); // static void sg_unmap_and(Sg_scatter_hold * schp, int free_also); static Sg_device *sg_get_dev(int dev); static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp); -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void); #endif @@ -680,7 +680,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, sg_finish_rem_req(srp); return -ENODEV; } - SRpnt = scsi_allocate_request(sdp->device); + SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC); if (SRpnt == NULL) { SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n")); sg_finish_rem_req(srp); @@ -1516,18 +1516,18 @@ init_sg(void) rc = scsi_register_interface(&sg_interface); if (rc) return rc; -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS sg_proc_init(); -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ return 0; } static void __exit exit_sg(void) { -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS sg_proc_cleanup(); -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ scsi_unregister_interface(&sg_interface); unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if (sg_dev_arr != NULL) { @@ -2225,7 +2225,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) return resp; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static Sg_request * sg_get_nth_request(Sg_fd * sfp, int nth) { @@ -2317,7 +2317,7 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) return res; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static Sg_fd * sg_get_nth_sfp(Sg_device * sdp, int nth) { @@ -2548,7 +2548,7 @@ sg_allow_access(unsigned char opcode, char dev_type) return 0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void) { @@ -2579,11 +2579,11 @@ sg_get_dev(int dev) return sdp; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SCSI_PROC_FS static struct proc_dir_entry *sg_proc_sgp = NULL; -static char sg_proc_sg_dirname[] = "sg"; +static char sg_proc_sg_dirname[] = "scsi/sg"; static int sg_proc_adio_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data); @@ -2657,10 +2657,6 @@ static struct sg_proc_leaf sg_proc_leaf_arr[] = { size : begin + len - offset; \ } while(0) -/* this should _really_ be private to the scsi midlayer. But - /proc/scsi/sg is an established name, so.. */ -extern struct proc_dir_entry *proc_scsi; - static int sg_proc_init(void) { @@ -2670,10 +2666,8 @@ sg_proc_init(void) struct proc_dir_entry *pdep; struct sg_proc_leaf * leaf; - if (!proc_scsi) - return 1; sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname, - S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi); + S_IFDIR | S_IRUGO | S_IXUGO, NULL); if (!sg_proc_sgp) return 1; for (k = 0; k < num_leaves; ++k) { @@ -2696,11 +2690,11 @@ sg_proc_cleanup(void) int num_leaves = sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); - if ((!proc_scsi) || (!sg_proc_sgp)) + if (!sg_proc_sgp) return; for (k = 0; k < num_leaves; ++k) remove_proc_entry(sg_proc_leaf_arr[k].name, sg_proc_sgp); - remove_proc_entry(sg_proc_sg_dirname, proc_scsi); + remove_proc_entry(sg_proc_sg_dirname, NULL); } static int @@ -2971,7 +2965,7 @@ sg_proc_version_info(char *buffer, int *len, off_t * begin, PRINT_PROC("%d\t%s\n", sg_version_num, sg_version_str); return 1; } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SCSI_PROC_FS */ module_init(init_sg); module_exit(exit_sg); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index bbef9a48030f..089510b7a819 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -599,7 +599,7 @@ static void get_sectorsize(struct scsi_cd *cd) buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) goto Enomem; - SRpnt = scsi_allocate_request(cd->device); + SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); if (!SRpnt) goto Enomem; @@ -713,7 +713,7 @@ static void get_capabilities(struct scsi_cd *cd) }; /* allocate a request for the TEST_UNIT_READY */ - SRpnt = scsi_allocate_request(cd->device); + SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL); if (!SRpnt) { printk(KERN_WARNING "(get_capabilities:) Request allocation " "failure.\n"); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 7eb274c0a33d..0416030f717f 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -82,7 +82,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct cdrom_generic_command *cgc) int result, err = 0, retries = 0; SDev = cd->device; - SRpnt = scsi_allocate_request(SDev); + SRpnt = scsi_allocate_request(SDev, GFP_KERNEL); if (!SRpnt) { printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl"); err = -ENOMEM; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 85969cd26c84..ed0a5ab2667b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -374,7 +374,7 @@ static Scsi_Request * unsigned char *bp; if (SRpnt == NULL) { - SRpnt = scsi_allocate_request(STp->device); + SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC); if (SRpnt == NULL) { DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n", tape_name(STp)); ); diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index c549d49e3c30..a31642785f19 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -6594,19 +6594,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } cp->cmd = cmd; - /*--------------------------------------------------- - ** - ** Enable tagged queue if asked by scsi ioctl - ** - **---------------------------------------------------- - */ -#if 0 /* This stuff was only useful for linux-1.2.13 */ - if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) { - lp->numtags = tp->usrtags; - ncr_setup_tags (np, cp->target, cp->lun); - } -#endif - /*---------------------------------------------------- ** ** Build the identify / tag / sdtr message diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h index 8bc52f731a5a..705ffaadb31f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_conf.h +++ b/drivers/scsi/sym53c8xx_2/sym_conf.h @@ -131,11 +131,6 @@ /* #define SYM_CONF_IARB_SUPPORT */ /* - * Support for some PCI fix-ups (or assumed so). - */ -#define SYM_CONF_PCI_FIX_UP - -/* * Number of lists for the optimization of the IO timeout handling. * Not used under FreeBSD and Linux. */ diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h index 70649d107d6a..f8344b42dfd1 100644 --- a/drivers/scsi/sym53c8xx_2/sym_defs.h +++ b/drivers/scsi/sym53c8xx_2/sym_defs.h @@ -74,8 +74,8 @@ #define PCI_ID_SYM53C896 0xb #define PCI_ID_SYM53C895A 0x12 #define PCI_ID_SYM53C875A 0x13 -#define PCI_ID_LSI53C1010 0x20 -#define PCI_ID_LSI53C1010_2 0x21 +#define PCI_ID_LSI53C1010_33 0x20 +#define PCI_ID_LSI53C1010_66 0x21 #define PCI_ID_LSI53C1510D 0xa /* diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index bcdd7c5297e0..5b24d1fe9652 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -270,13 +270,13 @@ sym_fw2_patch(hcb_p np) * Remove a couple of work-arounds specific to C1010 if * they are not desirable. See `sym_fw2.h' for more details. */ - if (!(np->device_id == PCI_ID_LSI53C1010_2 && + if (!(np->device_id == PCI_ID_LSI53C1010_66 && np->revision_id < 0x1 && np->pciclk_khz < 60000)) { scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP); scripta0->datao_phase[1] = cpu_to_scr(0); } - if (!(np->device_id == PCI_ID_LSI53C1010 && + if (!(np->device_id == PCI_ID_LSI53C1010_33 && /* np->revision_id < 0xff */ 1)) { scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP); scripta0->sel_done[1] = cpu_to_scr(0); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index a8cb6c5ad4fe..26dcbea2b562 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -57,7 +57,7 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -static int __init +static int __devinit pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) { u32 tmp; @@ -77,30 +77,6 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) #undef PCI_BAR_OFFSET } -/* - * Insert a delay in micro-seconds and milli-seconds. - */ -void sym_udelay(int us) { udelay(us); } -void sym_mdelay(int ms) { mdelay(ms); } - -/* - * SMP threading. - * - * The whole SCSI sub-system under Linux is basically single-threaded. - * Everything, including low-level driver interrupt routine, happens - * with the `io_request_lock' held. - * The sym53c8xx-1.x drivers series ran their interrupt code using a - * spin mutex per controller. This added complexity without improving - * scalability significantly. the sym-2 driver still use a spinlock - * per controller for safety, but basically runs with the damned - * io_request_lock held. - */ - -spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; - -#define SYM_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags) -#define SYM_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags) - #define SYM_INIT_LOCK_HCB(np) spin_lock_init((np)->s.host->host_lock); #define SYM_LOCK_HCB(np, flags) \ spin_lock_irqsave((np)->s.host->host_lock, flags) @@ -118,6 +94,9 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; #define ktime_add(a, o) ((a) + (u_long)(o)) #define ktime_sub(a, o) ((a) - (u_long)(o)) +/* This lock protects only the memory allocation/free. */ +spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED; + /* * Wrappers to the generic memory allocator. */ @@ -125,58 +104,53 @@ void *sym_calloc(int size, char *name) { u_long flags; void *m; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); m = sym_calloc_unlocked(size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return m; } void sym_mfree(void *m, int size, char *name) { u_long flags; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); sym_mfree_unlocked(m, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); } -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING - void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name) { u_long flags; void *m; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); m = __sym_calloc_dma_unlocked(dev_dmat, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return m; } void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name) { u_long flags; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); __sym_mfree_dma_unlocked(dev_dmat, m, size, name); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); } m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m) { u_long flags; m_addr_t b; - SYM_LOCK_DRIVER(flags); + spin_lock_irqsave(&sym53c8xx_lock, flags); b = __vtobus_unlocked(dev_dmat, m); - SYM_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&sym53c8xx_lock, flags); return b; } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - - /* * Map/unmap a PCI memory window. */ #ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING -static u_long __init pci_map_mem(u_long base, u_long size) +static u_long __devinit pci_map_mem(u_long base, u_long size) { u_long page_base = ((u_long) base) & PAGE_MASK; u_long page_offs = ((u_long) base) - page_base; @@ -185,19 +159,13 @@ static u_long __init pci_map_mem(u_long base, u_long size) return page_remapped? (page_remapped + page_offs) : 0UL; } -static void __init pci_unmap_mem(u_long vaddr, u_long size) +static void __devinit pci_unmap_mem(u_long vaddr, u_long size) { if (vaddr) iounmap((void *) (vaddr & PAGE_MASK)); } #endif -/* - * Used to retrieve the host structure when the - * driver is called from the proc FS. - */ -static struct Scsi_Host *first_host = NULL; - #define scsi_data_direction(cmd) (cmd->sc_data_direction) /* @@ -210,11 +178,7 @@ struct host_data { /* * Some type that fit DMA addresses as seen from BUS. */ -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING -typedef u_long bus_addr_t; -#else typedef dma_addr_t bus_addr_t; -#endif /* * Used by the eh thread to wait for command completion. @@ -233,10 +197,8 @@ struct sym_eh_wait { */ struct sym_ucmd { /* Override the SCSI pointer structure */ SYM_QUEHEAD link_cmdq; /* Must stay at offset ZERO */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING bus_addr_t data_mapping; u_char data_mapped; -#endif struct sym_eh_wait *eh_wait; }; @@ -249,39 +211,18 @@ typedef struct sym_ucmd *ucmd_p; /* * Deal with DMA mapping/unmapping. */ - -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING - -/* Linux versions prior to pci bus iommu kernel interface */ - -#define __unmap_scsi_data(pdev, cmd) do {; } while (0) -#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer)) -#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg) -#define __sync_scsi_data(pdev, cmd) do {; } while (0) - -#define bus_sg_dma_address(sc) vtobus((sc)->address) -#define bus_sg_dma_len(sc) ((sc)->length) - -#else /* Linux version with pci bus iommu kernel interface */ - #define bus_unmap_sg(pdev, sgptr, sgcnt, dir) \ pci_unmap_sg(pdev, sgptr, sgcnt, dir) - #define bus_unmap_single(pdev, mapping, bufptr, dir) \ pci_unmap_single(pdev, mapping, bufptr, dir) - #define bus_map_single(pdev, bufptr, bufsiz, dir) \ pci_map_single(pdev, bufptr, bufsiz, dir) - #define bus_map_sg(pdev, sgptr, sgcnt, dir) \ pci_map_sg(pdev, sgptr, sgcnt, dir) - #define bus_dma_sync_sg(pdev, sgptr, sgcnt, dir) \ pci_dma_sync_sg(pdev, sgptr, sgcnt, dir) - #define bus_dma_sync_single(pdev, mapping, bufsiz, dir) \ pci_dma_sync_single(pdev, mapping, bufsiz, dir) - #define bus_sg_dma_address(sc) sg_dma_address(sc) #define bus_sg_dma_len(sc) sg_dma_len(sc) @@ -345,8 +286,6 @@ static void __sync_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) } } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - #define unmap_scsi_data(np, cmd) \ __unmap_scsi_data(np->s.device, cmd) #define map_scsi_single_data(np, cmd) \ @@ -1656,13 +1595,13 @@ static int sym_host_info(hcb_p np, char *ptr, off_t offset, int len) copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, np->device_id, np->revision_id); - copy_info(&info, "On PCI bus %d, device %d, function %d, " + copy_info(&info, "At PCI address %s, " #ifdef __sparc__ "IRQ %s\n", #else "IRQ %d\n", #endif - np->s.bus, (np->s.device_fn & 0xf8) >> 3, np->s.device_fn & 7, + pci_name(np->s.device), #ifdef __sparc__ __irq_itoa(np->s.irq)); #else @@ -1748,7 +1687,6 @@ static void sym_free_resources(hcb_p np) /* * Ask/tell the system about DMA addressing. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING static int sym_setup_bus_dma_mask(hcb_p np) { #if SYM_CONF_DMA_ADDRESSING_MODE == 0 @@ -1780,7 +1718,6 @@ out_err32: sym_name(np)); return -1; } -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ /* * Host attach and initialisations. @@ -1791,7 +1728,7 @@ out_err32: * If all is OK, install interrupt handling and * start the timer daemon. */ -static int __init +static int __devinit sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) { struct host_data *host_data; @@ -1802,15 +1739,14 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) struct sym_fw *fw; printk(KERN_INFO - "sym%d: <%s> rev 0x%x on pci bus %d device %d function %d " + "sym%d: <%s> rev 0x%x at pci %s " #ifdef __sparc__ "irq %s\n", #else "irq %d\n", #endif unit, dev->chip.name, dev->chip.revision_id, - dev->s.bus, (dev->s.device_fn & 0xf8) >> 3, - dev->s.device_fn & 7, + pci_name(dev->pdev), #ifdef __sparc__ __irq_itoa(dev->s.irq)); #else @@ -1837,7 +1773,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) * We keep track in the HCB of all the resources that * are to be released on error. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB"); if (np) { np->s.device = dev->pdev; @@ -1845,11 +1780,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) } else goto attach_failed; -#else - np = sym_calloc_dma(sizeof(*np), "HCB"); - if (!np) - goto attach_failed; -#endif + host_data->ncb = np; np->s.host = instance; @@ -1866,8 +1797,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) np->s.unit = unit; np->device_id = dev->chip.device_id; np->revision_id = dev->chip.revision_id; - np->s.bus = dev->s.bus; - np->s.device_fn = dev->s.device_fn; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; np->maxoffs = dev->chip.offset_max; @@ -1883,10 +1812,8 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) /* * Ask/tell the system about DMA addressing. */ -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING if (sym_setup_bus_dma_mask(np)) goto attach_failed; -#endif /* * Try to map the controller chip to @@ -1987,12 +1914,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) sym_timer (np); /* - * Done. - */ - if (!first_host) - first_host = instance; - - /* * Fill Linux host instance structure * and return success. */ @@ -2039,7 +1960,7 @@ attach_failed: * Detect and try to read SYMBIOS and TEKRAM NVRAM. */ #if SYM_CONF_NVRAM_SUPPORT -static void __init sym_get_nvram(sym_device *devp, sym_nvram *nvp) +static void __devinit sym_get_nvram(sym_device *devp, sym_nvram *nvp) { if (!nvp) return; @@ -2087,37 +2008,6 @@ char *sym53c8xx = 0; /* command line passed by insmod */ MODULE_PARM(sym53c8xx, "s"); #endif -static void __init sym53c8xx_print_driver_setup(void) -{ - printf_info (NAME53C8XX ": setup=" - "mpar:%d,spar:%d,tags:%d,sync:%d,burst:%d," - "led:%d,wide:%d,diff:%d,irqm:%d, buschk:%d\n", - sym_driver_setup.pci_parity, - sym_driver_setup.scsi_parity, - sym_driver_setup.max_tag, - sym_driver_setup.min_sync, - sym_driver_setup.burst_order, - sym_driver_setup.scsi_led, - sym_driver_setup.max_wide, - sym_driver_setup.scsi_diff, - sym_driver_setup.irq_mode, - sym_driver_setup.scsi_bus_check); - printf_info (NAME53C8XX ": setup=" - "hostid:%d,offs:%d,luns:%d,pcifix:%d,revprob:%d," - "verb:%d,debug:0x%x,setlle_delay:%d\n", - sym_driver_setup.host_id, - sym_driver_setup.max_offs, - sym_driver_setup.max_lun, - sym_driver_setup.pci_fix_up, - sym_driver_setup.reverse_probe, - sym_driver_setup.verbose, - sym_driver_setup.debug, - sym_driver_setup.settle_delay); -#ifdef DEBUG_2_0_X -MDELAY(5000); -#endif -}; - #define OPT_PCI_PARITY 1 #define OPT_SCSI_PARITY 2 #define OPT_MAX_TAG 3 @@ -2131,15 +2021,13 @@ MDELAY(5000); #define OPT_HOST_ID 11 #define OPT_MAX_OFFS 12 #define OPT_MAX_LUN 13 -#define OPT_PCI_FIX_UP 14 - -#define OPT_REVERSE_PROBE 15 -#define OPT_VERBOSE 16 -#define OPT_DEBUG 17 -#define OPT_SETTLE_DELAY 18 -#define OPT_USE_NVRAM 19 -#define OPT_EXCLUDE 20 -#define OPT_SAFE_SETUP 21 +#define OPT_REVERSE_PROBE 14 +#define OPT_VERBOSE 15 +#define OPT_DEBUG 16 +#define OPT_SETTLE_DELAY 17 +#define OPT_USE_NVRAM 18 +#define OPT_EXCLUDE 19 +#define OPT_SAFE_SETUP 20 static char setup_token[] __initdata = "mpar:" "spar:" @@ -2148,11 +2036,10 @@ static char setup_token[] __initdata = "wide:" "diff:" "irqm:" "buschk:" "hostid:" "offset:" - "luns:" "pcifix:" - "revprob:" "verb:" - "debug:" "settle:" - "nvram:" "excl:" - "safe:" + "luns:" "revprob:" + "verb:" "debug:" + "settle:" "nvram:" + "excl:" "safe:" ; #ifdef MODULE @@ -2239,7 +2126,6 @@ int __init sym53c8xx_setup(char *str) __SIMPLE_OPTION(HOST_ID, host_id) __SIMPLE_OPTION(MAX_OFFS, max_offs) __SIMPLE_OPTION(MAX_LUN, max_lun) - __SIMPLE_OPTION(PCI_FIX_UP, pci_fix_up) __SIMPLE_OPTION(REVERSE_PROBE, reverse_probe) __SIMPLE_OPTION(VERBOSE, verbose) __SIMPLE_OPTION(DEBUG, debug) @@ -2269,19 +2155,16 @@ __setup("sym53c8xx=", sym53c8xx_setup); * boards and save data for attaching after all boards have * been detected. */ -static int __init +static int __devinit sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) { - u_short vendor_id, device_id, command, status_reg; - u_char cache_line_size; - u_char suggested_cache_line_size = 0; - u_char pci_fix_up = SYM_SETUP_PCI_FIX_UP; + u_short vendor_id, device_id, status_reg; u_char revision; u_int irq; u_long base, base_2; u_long base_c, base_2_c, io_port; int i; - sym_chip *chip; + struct sym_pci_chip *chip; /* Choose some short name for this device */ sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, @@ -2393,25 +2276,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) pci_set_master(pdev); /* - * Read additionnal info from the configuration space. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); - - /* - * If cache line size is not configured, suggest - * a value for well known CPUs. - */ -#if defined(__i386__) && !defined(MODULE) - if (!cache_line_size && boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { - switch(boot_cpu_data.x86) { - case 4: suggested_cache_line_size = 4; break; - case 6: if (boot_cpu_data.x86_model > 8) break; - case 5: suggested_cache_line_size = 8; break; - } - } -#endif /* __i386__ */ - - /* * Some features are required to be enabled in order to * work around some chip problems. :) ;) * (ITEM 12 of a DEL about the 896 I haven't yet). @@ -2420,31 +2284,12 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) */ if (device_id == PCI_DEVICE_ID_NCR_53C896 && revision < 0x4) { chip->features |= (FE_WRIE | FE_CLSE); - pci_fix_up |= 3; /* Force appropriate PCI fix-up */ - } - -#ifdef SYM_CONF_PCI_FIX_UP - /* - * Try to fix up PCI config according to wished features. - */ - if ((pci_fix_up & 1) && (chip->features & FE_CLSE) && - !cache_line_size && suggested_cache_line_size) { - cache_line_size = suggested_cache_line_size; - pci_write_config_byte(pdev, - PCI_CACHE_LINE_SIZE, cache_line_size); - printf_info("%s: PCI_CACHE_LINE_SIZE set to %d.\n", - sym_name(device), cache_line_size); } - pci_read_config_word(pdev, PCI_COMMAND, &command); - if ((pci_fix_up & 2) && cache_line_size && - (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) { - printf_info("%s: setting PCI_COMMAND_INVALIDATE.\n", - sym_name(device)); - command |= PCI_COMMAND_INVALIDATE; - pci_write_config_word(pdev, PCI_COMMAND, command); + if (chip->features & FE_WRIE) { + if (pci_set_mwi(pdev)) + return -1; } -#endif /* SYM_CONF_PCI_FIX_UP */ /* * Work around for errant bit in 895A. The 66Mhz @@ -2461,8 +2306,7 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) if (chip->features & FE_66MHZ) { if (!(status_reg & PCI_STATUS_66MHZ)) chip->features &= ~FE_66MHZ; - } - else { + } else { if (status_reg & PCI_STATUS_66MHZ) { status_reg = PCI_STATUS_66MHZ; pci_write_config_word(pdev, PCI_STATUS, status_reg); @@ -2474,8 +2318,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) * Initialise device structure with items required by sym_attach. */ device->pdev = pdev; - device->s.bus = pdev->bus->number; - device->s.device_fn = pdev->devfn; device->s.base = base; device->s.base_2 = base_2; device->s.base_c = base_c; @@ -2487,203 +2329,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) return 0; } -#if 0 -/* - * Detect all 53c8xx hosts and then attach them. - * - * If we are using NVRAM, once all hosts are detected, we need to - * check any NVRAM for boot order in case detect and boot order - * differ and attach them using the order in the NVRAM. - * - * If no NVRAM is found or data appears invalid attach boards in - * the order they are detected. - */ -int __init sym53c8xx_detect(struct scsi_host_template *tpnt) -{ - struct pci_dev *pcidev; - int i, j, chips, hosts, count; - int attach_count = 0; - sym_device *devtbl, *devp; - sym_nvram nvram; -#if SYM_CONF_NVRAM_SUPPORT - sym_nvram nvram0, *nvp; -#endif - - /* - * Initialize driver general stuff. - */ -#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT -#ifdef MODULE -if (sym53c8xx) - sym53c8xx_setup(sym53c8xx); -#endif -#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT - sym_debug_flags = sym_driver_setup.debug; -#endif - if (boot_verbose >= 2) - sym53c8xx_print_driver_setup(); -#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */ - - /* - * Allocate the device table since we donnot want to - * overflow the kernel stack. - * 1 x 4K PAGE is enough for more than 40 devices for i386. - */ - devtbl = sym_calloc(PAGE_SIZE, "DEVTBL"); - if (!devtbl) - return 0; - - /* - * Detect all NCR PQS/PDS memory controllers. - */ -#ifdef SYM_CONF_PQS_PDS_SUPPORT - sym_detect_pqs_pds(); -#endif - - /* - * Detect all 53c8xx hosts. - * Save the first Symbios NVRAM content if any - * for the boot order. - */ - chips = sizeof(sym_chip_ids) / sizeof(sym_chip_ids[0]); - hosts = PAGE_SIZE / sizeof(*devtbl); -#if SYM_CONF_NVRAM_SUPPORT - nvp = (sym_driver_setup.use_nvram & 0x1) ? &nvram0 : 0; -#endif - j = 0; - count = 0; - pcidev = NULL; - while (1) { - char *msg = ""; - if (count >= hosts) - break; - if (j >= chips) - break; - i = sym_driver_setup.reverse_probe ? chips - 1 - j : j; - pcidev = pci_find_device(PCI_VENDOR_ID_NCR, sym_chip_ids[i], - pcidev); - if (pcidev == NULL) { - ++j; - continue; - } - /* This one is guaranteed by AC to do nothing :-) */ - if (pci_enable_device(pcidev)) - continue; - devp = &devtbl[count]; - devp->host_id = SYM_SETUP_HOST_ID; - if (sym53c8xx_pci_init(pcidev, devp)) { - continue; - } - ++count; -#if SYM_CONF_NVRAM_SUPPORT - if (nvp) { - sym_get_nvram(devp, nvp); - switch(nvp->type) { - case SYM_SYMBIOS_NVRAM: - /* - * Switch to the other nvram buffer, so that - * nvram0 will contain the first Symbios - * format NVRAM content with boot order. - */ - nvp = &nvram; - msg = "with Symbios NVRAM"; - break; - case SYM_TEKRAM_NVRAM: - msg = "with Tekram NVRAM"; - break; - } - } -#endif -#ifdef SYM_CONF_PQS_PDS_SUPPORT - /* - * Match the BUS number for PQS/PDS devices. - * Read the SCSI ID from a special register mapped - * into the configuration space of the individual - * 875s. This register is set up by the PQS bios - */ - for(i = 0; i < SYM_CONF_MAX_PQS_BUS && pqs_bus[i] != -1; i++) { - u_char tmp; - if (pqs_bus[i] == pcidev->bus->number) { - pci_read_config_byte(pcidev, 0x84, &tmp); - devp->pqs_pds = 1; - devp->host_id = tmp; - break; - } - } - if (devp->pqs_pds) - msg = "(NCR PQS/PDS)"; -#endif - if (boot_verbose) - printf_info("%s: 53c%s detected %s\n", - sym_name(devp), devp->chip.name, msg); - } - - /* - * If we have found a SYMBIOS NVRAM, use first the NVRAM boot - * sequence as device boot order. - * check devices in the boot record against devices detected. - * attach devices if we find a match. boot table records that - * do not match any detected devices will be ignored. - * devices that do not match any boot table will not be attached - * here but will attempt to be attached during the device table - * rescan. - */ -#if SYM_CONF_NVRAM_SUPPORT - if (!nvp || nvram0.type != SYM_SYMBIOS_NVRAM) - goto next; - for (i = 0; i < 4; i++) { - Symbios_host *h = &nvram0.data.Symbios.host[i]; - for (j = 0 ; j < count ; j++) { - devp = &devtbl[j]; - if (h->device_fn != devp->s.device_fn || - h->bus_nr != devp->s.bus || - h->device_id != devp->chip.device_id) - continue; - if (devp->attach_done) - continue; - if (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) { - sym_get_nvram(devp, nvp); - if (!sym_attach (tpnt, attach_count, devp)) - attach_count++; - } - else if (!(sym_driver_setup.use_nvram & 0x80)) - printf_info( - "%s: 53c%s state OFF thus not attached\n", - sym_name(devp), devp->chip.name); - else - continue; - - devp->attach_done = 1; - break; - } - } -next: -#endif - - /* - * Rescan device list to make sure all boards attached. - * Devices without boot records will not be attached yet - * so try to attach them here. - */ - for (i= 0; i < count; i++) { - devp = &devtbl[i]; - if (!devp->attach_done) { - devp->nvram = &nvram; - nvram.type = 0; -#if SYM_CONF_NVRAM_SUPPORT - sym_get_nvram(devp, nvp); -#endif - if (!sym_attach (tpnt, attach_count, devp)) - attach_count++; - } - } - - sym_mfree(devtbl, PAGE_SIZE, "DEVTBL"); - - return attach_count; -} -#endif - /* * Linux release module stuff. @@ -2717,15 +2362,6 @@ static int sym_detach(hcb_p np) return 1; } -#if 0 -int sym53c8xx_release(struct Scsi_Host *host) -{ - sym_detach(((struct host_data *) host->hostdata)->ncb); - - return 0; -} -#endif - MODULE_LICENSE("Dual BSD/GPL"); /* @@ -2734,10 +2370,6 @@ MODULE_LICENSE("Dual BSD/GPL"); static struct scsi_host_template sym2_template = { .module = THIS_MODULE, .name = "sym53c8xx", -#if 0 - .detect = sym53c8xx_detect, - .release = sym53c8xx_release, -#endif .info = sym53c8xx_info, .queuecommand = sym53c8xx_queue_command, .slave_configure = sym53c8xx_slave_configure, @@ -2839,7 +2471,6 @@ static int __devinit sym2_probe(struct pci_dev *pdev, sym_dev.host_id = SYM_SETUP_HOST_ID; if (sym53c8xx_pci_init(pdev, &sym_dev)) return -ENODEV; - printk(KERN_INFO "%s: 53c%s detected\n", sym_name(&sym_dev), sym_dev.chip.name); sym_dev.nvram = &nvram; nvram.type = 0; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 5ee8c1b63f0f..a8f5a81cad40 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -111,8 +111,6 @@ typedef u_long vm_offset_t; /* * Configuration addendum for Linux. */ -#define SYM_LINUX_DYNAMIC_DMA_MAPPING - #define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2) #define SYM_OPT_HANDLE_DIR_UNKNOWN @@ -121,10 +119,7 @@ typedef u_long vm_offset_t; #define SYM_OPT_SNIFF_INQUIRY #define SYM_OPT_LIMIT_COMMAND_REORDERING #define SYM_OPT_ANNOUNCE_TRANSFER_RATE - -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING #define SYM_OPT_BUS_DMA_ABSTRACTION -#endif /* * Print a message with severity. @@ -142,8 +137,8 @@ typedef u_long vm_offset_t; /* * Insert a delay in micro-seconds and milli-seconds. */ -void sym_udelay(int us); -void sym_mdelay(int ms); +#define sym_udelay(us) udelay(us) +#define sym_mdelay(ms) mdelay(ms) /* * Let the compiler know about driver data structure names. @@ -426,9 +421,6 @@ struct sym_shcb { struct Scsi_Host *host; - u_char bus; /* PCI BUS number */ - u_char device_fn; /* PCI BUS device and function */ - vm_offset_t mmio_va; /* MMIO kernel virtual address */ vm_offset_t ram_va; /* RAM kernel virtual address */ u_long io_port; /* IO port address cookie */ @@ -455,8 +447,6 @@ struct sym_shcb { * used as sub-field 's' of another structure. */ typedef struct { - int bus; - u_char device_fn; u_long base; u_long base_2; u_long base_c; @@ -469,12 +459,11 @@ typedef struct { } sym_slot; typedef struct sym_nvram sym_nvram; -typedef struct sym_pci_chip sym_chip; typedef struct { struct pci_dev *pdev; sym_slot s; - sym_chip chip; + struct sym_pci_chip chip; sym_nvram *nvram; u_short device_id; u_char host_id; @@ -496,9 +485,7 @@ typedef u_long m_addr_t; /* Enough bits to represent any address */ #ifdef MODULE #define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */ #endif -#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING typedef struct pci_dev *m_pool_ident_t; -#endif /* * Include driver soft definitions. @@ -521,19 +508,7 @@ typedef struct pci_dev *m_pool_ident_t; void *sym_calloc(int size, char *name); void sym_mfree(void *m, int size, char *name); -#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING /* - * Simple case. - * All the memory assummed DMAable and O/S providing virtual - * to bus physical address translation. - */ -#define __sym_calloc_dma(pool_id, size, name) sym_calloc(size, name) -#define __sym_mfree_dma(pool_id, m, size, name) sym_mfree(m, size, name) -#define __vtobus(b, p) virt_to_bus(p) - -#else /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ -/* - * Complex case. * We have to provide the driver memory allocator with methods for * it to maintain virtual to bus physical address translations. */ @@ -560,15 +535,12 @@ static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp) } #define sym_m_create_dma_mem_tag(mp) (0) - #define sym_m_delete_dma_mem_tag(mp) do { ; } while (0) void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name); void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name); m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m); -#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */ - /* * Set the status field of a CAM CCB. */ diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 7d83f2c28869..a8984f6ee40e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -50,7 +50,7 @@ * SUCH DAMAGE. */ -#define SYM_DRIVER_NAME "sym-2.1.16a" +#define SYM_DRIVER_NAME "sym-2.1.17a" #ifdef __FreeBSD__ #include <dev/sym/sym_glue.h> @@ -289,7 +289,7 @@ int sym_reset_scsi_bus(hcb_p np, int enab_int) ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */ INB(nc_sbcl); /* req ack bsy sel atn msg cd io */ - if (!(np->features & FE_WIDE)) + if (!np->maxwide) term &= 0x3ffff; if (term != (2<<7)) { @@ -744,6 +744,12 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) u32 period; int i; +#ifdef CONFIG_PARISC + unsigned long pdc_period; + char scsi_mode = -1; + struct hardware_path hwpath; +#endif + /* * Wide ? */ @@ -800,6 +806,31 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * Btw, 'period' is in tenths of nanoseconds. */ period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; + +#if defined(CONFIG_PARISC) + /* Host firmware (PDC) keeps a table for crippling SCSI capabilities. + * Many newer machines export one channel of 53c896 chip + * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters + * to set the SCSI Initiator ID. + */ + get_pci_node_path(np->s.device, &hwpath); + if (pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period, &np->maxwide, &scsi_mode)) + { + if (scsi_mode >= 0) { + /* C3000 PDC reports period/mode */ + SYM_SETUP_SCSI_DIFF = 0; + switch(scsi_mode) { + case 0: np->scsi_mode = SMODE_SE; break; + case 1: np->scsi_mode = SMODE_HVD; break; + case 2: np->scsi_mode = SMODE_LVD; break; + default: break; + } + } + + period = (u32) pdc_period; + } +#endif + if (period <= 250) np->minsync = 10; else if (period <= 303) np->minsync = 11; else if (period <= 500) np->minsync = 12; @@ -862,7 +893,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * In dual channel mode, contention occurs if internal cycles * are used. Disable internal cycles. */ - if (np->device_id == PCI_ID_LSI53C1010 && + if (np->device_id == PCI_ID_LSI53C1010_33 && np->revision_id < 0x1) np->rv_ccntl0 |= DILS; @@ -1362,17 +1393,17 @@ static struct sym_pci_chip sym_pci_dev_table[] = { FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ} , - {PCI_ID_LSI53C1010, 0x00, "1010-33", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10} , - {PCI_ID_LSI53C1010, 0xff, "1010-33", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10|FE_U3EN} , - {PCI_ID_LSI53C1010_2, 0xff, "1010-66", 6, 31, 7, 8, + {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC| FE_C10|FE_U3EN} @@ -1809,7 +1840,7 @@ void sym_start_up (hcb_p np, int reason) /* * For now, disable AIP generation on C1010-66. */ - if (np->device_id == PCI_ID_LSI53C1010_2) + if (np->device_id == PCI_ID_LSI53C1010_66) OUTB (nc_aipcntl1, DISAIP); /* @@ -1819,7 +1850,7 @@ void sym_start_up (hcb_p np, int reason) * that from SCRIPTS for each selection/reselection, but * I just don't want. :) */ - if (np->device_id == PCI_ID_LSI53C1010 && + if (np->device_id == PCI_ID_LSI53C1010_33 && np->revision_id < 1) OUTB (nc_stest1, INB(nc_stest1) | 0x30); diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.h b/drivers/scsi/sym53c8xx_2/sym_misc.h index 3a4b41f13907..2b01031c5283 100644 --- a/drivers/scsi/sym53c8xx_2/sym_misc.h +++ b/drivers/scsi/sym53c8xx_2/sym_misc.h @@ -77,23 +77,8 @@ * should be enough). */ -#if defined __i386__ -#define __READ_BARRIER() \ - __asm__ volatile("lock; addl $0,0(%%esp)": : :"memory") -#define __WRITE_BARRIER() __asm__ volatile ("": : :"memory") -#elif defined __powerpc__ -#define __READ_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") -#define __WRITE_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") -#elif defined __ia64__ -#define __READ_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory") -#define __WRITE_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory") -#elif defined __alpha__ -#define __READ_BARRIER() __asm__ volatile("mb": : :"memory") -#define __WRITE_BARRIER() __asm__ volatile("mb": : :"memory") -#else -#define __READ_BARRIER() mb() -#define __WRITE_BARRIER() mb() -#endif +#define __READ_BARRIER() rmb() +#define __WRITE_BARRIER() wmb() #ifndef MEMORY_READ_BARRIER #define MEMORY_READ_BARRIER() __READ_BARRIER() diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h index 289e3f06bca9..13a68b562dda 100644 --- a/drivers/scsi/sym53c8xx_defs.h +++ b/drivers/scsi/sym53c8xx_defs.h @@ -259,17 +259,6 @@ #endif /* - * Vendor specific stuff - */ -#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT -#define SCSI_NCR_SETUP_LED_PIN (1) -#define SCSI_NCR_SETUP_DIFF_SUPPORT (4) -#else -#define SCSI_NCR_SETUP_LED_PIN (0) -#define SCSI_NCR_SETUP_DIFF_SUPPORT (0) -#endif - -/* * Settle time after reset at boot-up */ #define SCSI_NCR_SETUP_SETTLE_TIME (2) @@ -926,10 +915,10 @@ struct ncr_driver_setup { SCSI_NCR_SETUP_DEFAULT_SYNC, \ 0x00, \ 7, \ - SCSI_NCR_SETUP_LED_PIN, \ + 0, \ 1, \ SCSI_NCR_SETUP_SETTLE_TIME, \ - SCSI_NCR_SETUP_DIFF_SUPPORT, \ + 0, \ 0, \ 1, \ 0, \ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index c48edf4a551e..38c43d95a616 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -603,7 +603,8 @@ enum { DEV_HWMON=2, DEV_PARPORT=3, DEV_RAID=4, - DEV_MAC_HID=5 + DEV_MAC_HID=5, + DEV_SCSI=6, }; /* /proc/sys/dev/cdrom */ @@ -664,6 +665,11 @@ enum { DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6 }; +/* /proc/sys/dev/scsi */ +enum { + DEV_SCSI_LOGGING_LEVEL=1, +}; + /* /proc/sys/abi */ enum { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 04b8f47837a9..17cac6fdaa34 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -74,8 +74,6 @@ struct scsi_device { unsigned wdtr:1; /* Device supports WDTR messages */ unsigned ppr:1; /* Device supports PPR messages */ unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ - unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags - instead!!! Please fix your driver now!! */ unsigned simple_tags:1; /* simple queue tag messages are enabled */ unsigned ordered_tags:1;/* ordered queue tag messages are enabled */ unsigned single_lun:1; /* Indicates we should only allow I/O to diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index d591d365c983..98719407d554 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -45,7 +45,7 @@ struct scsi_request { level driver) of this request */ }; -extern struct scsi_request *scsi_allocate_request(struct scsi_device *); +extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int); extern void scsi_release_request(struct scsi_request *); extern void scsi_wait_req(struct scsi_request *, const void *cmnd, void *buffer, unsigned bufflen, |
