- description of what an IRQ is.
ManagementStyle
- how to (attempt to) manage kernel hackers.
-MSI-HOWTO.txt
- - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
RCU/
- directory with info on RCU (read-copy update).
-README.DAC960
- - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
-README.cycladesZ
- - info on Cyclades-Z firmware loading.
SAK.txt
- info on Secure Attention Keys.
SM501.txt
- directory with documentation for the Blackfin arch.
block/
- info on the Block I/O (BIO) layer.
+blockdev/
+ - info on block devices & drivers
cachetlb.txt
- describes the cache/TLB flushing interfaces Linux uses.
-cciss.txt
- - info, major/minor #'s for Compaq's SMART Array Controllers.
cdrom/
- directory with information on the CD-ROM drivers that Linux has.
-computone.txt
- - info on Computone Intelliport II/Plus Multiport Serial Driver.
connector/
- docs on the netlink based userspace<->kernel space communication mod.
console/
- documentation on Linux console drivers.
-cpqarray.txt
- - info on using Compaq's SMART2 Intelligent Disk Array Controllers.
cpu-freq/
- info on CPU frequency and voltage scaling.
cpu-hotplug.txt
- directory with info on Device Mapper.
devices.txt
- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
-digiepca.txt
- - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
dontdiff
- file containing a list of files that should never be diff'ed.
driver-model/
- info on the vfs and the various filesystems that Linux supports.
firmware_class/
- request_firmware() hotplug interface info.
-floppy.txt
- - notes and driver options for the floppy disk driver.
frv/
- Fujitsu FR-V Linux documentation.
gpio.txt
- overview of GPIO (General Purpose Input/Output) access conventions.
-hayes-esp.txt
- - info on using the Hayes ESP serial driver.
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
timers/
- info on ordering I/O writes to memory-mapped addresses.
ioctl/
- directory with documents describing various IOCTL calls.
-ioctl-number.txt
- - how to implement and register device/driver ioctl calls.
iostats.txt
- info on I/O statistics Linux kernel provides.
irqflags-tracing.txt
- directory with info about Linux on MIPS architecture.
mono.txt
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
-moxa-smartio
- - file with info on installing/using Moxa multiport serial driver.
mutex-design.txt
- info on the generic mutex subsystem.
namespaces/
- directory with various information about namespaces
-nbd.txt
- - info on a TCP implementation of a network block device.
netlabel/
- directory with information on the NetLabel subsystem.
networking/
- info on how to read Numa policy hit/miss statistics in sysfs.
oops-tracing.txt
- how to decode those nasty internal kernel error dump messages.
-paride.txt
- - information about the parallel port IDE subsystem.
parisc/
- directory with info on using Linux on PA-RISC architecture.
parport.txt
- how to get printk format specifiers right
prio_tree.txt
- info on radix-priority-search-tree use for indexing vmas.
-ramdisk.txt
- - short guide on how to set up and use the RAM disk.
rbtree.txt
- info on what red-black trees are and what they are for.
-riscom8.txt
- - notes on using the RISCom/8 multi-port serial driver.
robust-futex-ABI.txt
- documentation of the robust futex ABI.
robust-futexes.txt
- a description of what robust futexes are.
-rocket.txt
- - info on the Comtrol RocketPort multiport serial driver.
rt-mutex-design.txt
- description of the RealTime mutex implementation design.
rt-mutex.txt
- directory with info on using Linux on Sparc architecture.
sparse.txt
- info on how to obtain and use the sparse tool for typechecking.
-specialix.txt
- - info on hardware/driver for specialix IO8+ multiport serial card.
spi/
- overview of Linux kernel Serial Peripheral Interface (SPI) support.
spinlocks.txt
- info on why the kernel does not have a stable in-kernel api or abi.
stable_kernel_rules.txt
- rules and procedures for the -stable kernel releases.
-stallion.txt
- - info on using the Stallion multiport serial driver.
svga.txt
- short guide on selecting video modes at boot via VGA BIOS.
sysfs-rules.txt
- How not to use sysfs.
-sx.txt
- - info on the Specialix SX/SI multiport serial driver.
sysctl/
- directory with info on the /proc/sys/* files.
sysrq.txt
- directory with info on telephony (e.g. voice over IP) support.
time_interpolators.txt
- info on time interpolators.
-tty.txt
- - guide to the locking policies of the tty layer.
uml/
- directory with information about User Mode Linux.
unicode.txt
+++ /dev/null
- The MSI Driver Guide HOWTO
- Tom L Nguyen tom.l.nguyen@intel.com
- 10/03/2003
- Revised Feb 12, 2004 by Martine Silbermann
- email: Martine.Silbermann@hp.com
- Revised Jun 25, 2004 by Tom L Nguyen
-
-1. About this guide
-
-This guide describes the basics of Message Signaled Interrupts (MSI),
-the advantages of using MSI over traditional interrupt mechanisms,
-and how to enable your driver to use MSI or MSI-X. Also included is
-a Frequently Asked Questions (FAQ) section.
-
-1.1 Terminology
-
-PCI devices can be single-function or multi-function. In either case,
-when this text talks about enabling or disabling MSI on a "device
-function," it is referring to one specific PCI device and function and
-not to all functions on a PCI device (unless the PCI device has only
-one function).
-
-2. Copyright 2003 Intel Corporation
-
-3. What is MSI/MSI-X?
-
-Message Signaled Interrupt (MSI), as described in the PCI Local Bus
-Specification Revision 2.3 or later, is an optional feature, and a
-required feature for PCI Express devices. MSI enables a device function
-to request service by sending an Inbound Memory Write on its PCI bus to
-the FSB as a Message Signal Interrupt transaction. Because MSI is
-generated in the form of a Memory Write, all transaction conditions,
-such as a Retry, Master-Abort, Target-Abort or normal completion, are
-supported.
-
-A PCI device that supports MSI must also support pin IRQ assertion
-interrupt mechanism to provide backward compatibility for systems that
-do not support MSI. In systems which support MSI, the bus driver is
-responsible for initializing the message address and message data of
-the device function's MSI/MSI-X capability structure during device
-initial configuration.
-
-An MSI capable device function indicates MSI support by implementing
-the MSI/MSI-X capability structure in its PCI capability list. The
-device function may implement both the MSI capability structure and
-the MSI-X capability structure; however, the bus driver should not
-enable both.
-
-The MSI capability structure contains Message Control register,
-Message Address register and Message Data register. These registers
-provide the bus driver control over MSI. The Message Control register
-indicates the MSI capability supported by the device. The Message
-Address register specifies the target address and the Message Data
-register specifies the characteristics of the message. To request
-service, the device function writes the content of the Message Data
-register to the target address. The device and its software driver
-are prohibited from writing to these registers.
-
-The MSI-X capability structure is an optional extension to MSI. It
-uses an independent and separate capability structure. There are
-some key advantages to implementing the MSI-X capability structure
-over the MSI capability structure as described below.
-
- - Support a larger maximum number of vectors per function.
-
- - Provide the ability for system software to configure
- each vector with an independent message address and message
- data, specified by a table that resides in Memory Space.
-
- - MSI and MSI-X both support per-vector masking. Per-vector
- masking is an optional extension of MSI but a required
- feature for MSI-X. Per-vector masking provides the kernel the
- ability to mask/unmask a single MSI while running its
- interrupt service routine. If per-vector masking is
- not supported, then the device driver should provide the
- hardware/software synchronization to ensure that the device
- generates MSI when the driver wants it to do so.
-
-4. Why use MSI?
-
-As a benefit to the simplification of board design, MSI allows board
-designers to remove out-of-band interrupt routing. MSI is another
-step towards a legacy-free environment.
-
-Due to increasing pressure on chipset and processor packages to
-reduce pin count, the need for interrupt pins is expected to
-diminish over time. Devices, due to pin constraints, may implement
-messages to increase performance.
-
-PCI Express endpoints uses INTx emulation (in-band messages) instead
-of IRQ pin assertion. Using INTx emulation requires interrupt
-sharing among devices connected to the same node (PCI bridge) while
-MSI is unique (non-shared) and does not require BIOS configuration
-support. As a result, the PCI Express technology requires MSI
-support for better interrupt performance.
-
-Using MSI enables the device functions to support two or more
-vectors, which can be configured to target different CPUs to
-increase scalability.
-
-5. Configuring a driver to use MSI/MSI-X
-
-By default, the kernel will not enable MSI/MSI-X on all devices that
-support this capability. The CONFIG_PCI_MSI kernel option
-must be selected to enable MSI/MSI-X support.
-
-5.1 Including MSI/MSI-X support into the kernel
-
-To allow MSI/MSI-X capable device drivers to selectively enable
-MSI/MSI-X (using pci_enable_msi()/pci_enable_msix() as described
-below), the VECTOR based scheme needs to be enabled by setting
-CONFIG_PCI_MSI during kernel config.
-
-Since the target of the inbound message is the local APIC, providing
-CONFIG_X86_LOCAL_APIC must be enabled as well as CONFIG_PCI_MSI.
-
-5.2 Configuring for MSI support
-
-Due to the non-contiguous fashion in vector assignment of the
-existing Linux kernel, this version does not support multiple
-messages regardless of a device function is capable of supporting
-more than one vector. To enable MSI on a device function's MSI
-capability structure requires a device driver to call the function
-pci_enable_msi() explicitly.
-
-5.2.1 API pci_enable_msi
-
-int pci_enable_msi(struct pci_dev *dev)
-
-With this new API, a device driver that wants to have MSI
-enabled on its device function must call this API to enable MSI.
-A successful call will initialize the MSI capability structure
-with ONE vector, regardless of whether a device function is
-capable of supporting multiple messages. This vector replaces the
-pre-assigned dev->irq with a new MSI vector. To avoid a conflict
-of the new assigned vector with existing pre-assigned vector requires
-a device driver to call this API before calling request_irq().
-
-5.2.2 API pci_disable_msi
-
-void pci_disable_msi(struct pci_dev *dev)
-
-This API should always be used to undo the effect of pci_enable_msi()
-when a device driver is unloading. This API restores dev->irq with
-the pre-assigned IOAPIC vector and switches a device's interrupt
-mode to PCI pin-irq assertion/INTx emulation mode.
-
-Note that a device driver should always call free_irq() on the MSI vector
-that it has done request_irq() on before calling this API. Failure to do
-so results in a BUG_ON() and a device will be left with MSI enabled and
-leaks its vector.
-
-5.2.3 MSI mode vs. legacy mode diagram
-
-The below diagram shows the events which switch the interrupt
-mode on the MSI-capable device function between MSI mode and
-PIN-IRQ assertion mode.
-
- ------------ pci_enable_msi ------------------------
- | | <=============== | |
- | MSI MODE | | PIN-IRQ ASSERTION MODE |
- | | ===============> | |
- ------------ pci_disable_msi ------------------------
-
-
-Figure 1. MSI Mode vs. Legacy Mode
-
-In Figure 1, a device operates by default in legacy mode. Legacy
-in this context means PCI pin-irq assertion or PCI-Express INTx
-emulation. A successful MSI request (using pci_enable_msi()) switches
-a device's interrupt mode to MSI mode. A pre-assigned IOAPIC vector
-stored in dev->irq will be saved by the PCI subsystem and a new
-assigned MSI vector will replace dev->irq.
-
-To return back to its default mode, a device driver should always call
-pci_disable_msi() to undo the effect of pci_enable_msi(). Note that a
-device driver should always call free_irq() on the MSI vector it has
-done request_irq() on before calling pci_disable_msi(). Failure to do
-so results in a BUG_ON() and a device will be left with MSI enabled and
-leaks its vector. Otherwise, the PCI subsystem restores a device's
-dev->irq with a pre-assigned IOAPIC vector and marks the released
-MSI vector as unused.
-
-Once being marked as unused, there is no guarantee that the PCI
-subsystem will reserve this MSI vector for a device. Depending on
-the availability of current PCI vector resources and the number of
-MSI/MSI-X requests from other drivers, this MSI may be re-assigned.
-
-For the case where the PCI subsystem re-assigns this MSI vector to
-another driver, a request to switch back to MSI mode may result
-in being assigned a different MSI vector or a failure if no more
-vectors are available.
-
-5.3 Configuring for MSI-X support
-
-Due to the ability of the system software to configure each vector of
-the MSI-X capability structure with an independent message address
-and message data, the non-contiguous fashion in vector assignment of
-the existing Linux kernel has no impact on supporting multiple
-messages on an MSI-X capable device functions. To enable MSI-X on
-a device function's MSI-X capability structure requires its device
-driver to call the function pci_enable_msix() explicitly.
-
-The function pci_enable_msix(), once invoked, enables either
-all or nothing, depending on the current availability of PCI vector
-resources. If the PCI vector resources are available for the number
-of vectors requested by a device driver, this function will configure
-the MSI-X table of the MSI-X capability structure of a device with
-requested messages. To emphasize this reason, for example, a device
-may be capable for supporting the maximum of 32 vectors while its
-software driver usually may request 4 vectors. It is recommended
-that the device driver should call this function once during the
-initialization phase of the device driver.
-
-Unlike the function pci_enable_msi(), the function pci_enable_msix()
-does not replace the pre-assigned IOAPIC dev->irq with a new MSI
-vector because the PCI subsystem writes the 1:1 vector-to-entry mapping
-into the field vector of each element contained in a second argument.
-Note that the pre-assigned IOAPIC dev->irq is valid only if the device
-operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at
-using dev->irq by the device driver to request for interrupt service
-may result in unpredictable behavior.
-
-For each MSI-X vector granted, a device driver is responsible for calling
-other functions like request_irq(), enable_irq(), etc. to enable
-this vector with its corresponding interrupt service handler. It is
-a device driver's choice to assign all vectors with the same
-interrupt service handler or each vector with a unique interrupt
-service handler.
-
-5.3.1 Handling MMIO address space of MSI-X Table
-
-The PCI 3.0 specification has implementation notes that MMIO address
-space for a device's MSI-X structure should be isolated so that the
-software system can set different pages for controlling accesses to the
-MSI-X structure. The implementation of MSI support requires the PCI
-subsystem, not a device driver, to maintain full control of the MSI-X
-table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X
-table/MSI-X PBA. A device driver should not access the MMIO address
-space of the MSI-X table/MSI-X PBA.
-
-5.3.2 API pci_enable_msix
-
-int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
-
-This API enables a device driver to request the PCI subsystem
-to enable MSI-X messages on its hardware device. Depending on
-the availability of PCI vectors resources, the PCI subsystem enables
-either all or none of the requested vectors.
-
-Argument 'dev' points to the device (pci_dev) structure.
-
-Argument 'entries' is a pointer to an array of msix_entry structs.
-The number of entries is indicated in argument 'nvec'.
-struct msix_entry is defined in /driver/pci/msi.h:
-
-struct msix_entry {
- u16 vector; /* kernel uses to write alloc vector */
- u16 entry; /* driver uses to specify entry */
-};
-
-A device driver is responsible for initializing the field 'entry' of
-each element with a unique entry supported by MSI-X table. Otherwise,
--EINVAL will be returned as a result. A successful return of zero
-indicates the PCI subsystem completed initializing each of the requested
-entries of the MSI-X table with message address and message data.
-Last but not least, the PCI subsystem will write the 1:1
-vector-to-entry mapping into the field 'vector' of each element. A
-device driver is responsible for keeping track of allocated MSI-X
-vectors in its internal data structure.
-
-A return of zero indicates that the number of MSI-X vectors was
-successfully allocated. A return of greater than zero indicates
-MSI-X vector shortage. Or a return of less than zero indicates
-a failure. This failure may be a result of duplicate entries
-specified in second argument, or a result of no available vector,
-or a result of failing to initialize MSI-X table entries.
-
-5.3.3 API pci_disable_msix
-
-void pci_disable_msix(struct pci_dev *dev)
-
-This API should always be used to undo the effect of pci_enable_msix()
-when a device driver is unloading. Note that a device driver should
-always call free_irq() on all MSI-X vectors it has done request_irq()
-on before calling this API. Failure to do so results in a BUG_ON() and
-a device will be left with MSI-X enabled and leaks its vectors.
-
-5.3.4 MSI-X mode vs. legacy mode diagram
-
-The below diagram shows the events which switch the interrupt
-mode on the MSI-X capable device function between MSI-X mode and
-PIN-IRQ assertion mode (legacy).
-
- ------------ pci_enable_msix(,,n) ------------------------
- | | <=============== | |
- | MSI-X MODE | | PIN-IRQ ASSERTION MODE |
- | | ===============> | |
- ------------ pci_disable_msix ------------------------
-
-Figure 2. MSI-X Mode vs. Legacy Mode
-
-In Figure 2, a device operates by default in legacy mode. A
-successful MSI-X request (using pci_enable_msix()) switches a
-device's interrupt mode to MSI-X mode. A pre-assigned IOAPIC vector
-stored in dev->irq will be saved by the PCI subsystem; however,
-unlike MSI mode, the PCI subsystem will not replace dev->irq with
-assigned MSI-X vector because the PCI subsystem already writes the 1:1
-vector-to-entry mapping into the field 'vector' of each element
-specified in second argument.
-
-To return back to its default mode, a device driver should always call
-pci_disable_msix() to undo the effect of pci_enable_msix(). Note that
-a device driver should always call free_irq() on all MSI-X vectors it
-has done request_irq() on before calling pci_disable_msix(). Failure
-to do so results in a BUG_ON() and a device will be left with MSI-X
-enabled and leaks its vectors. Otherwise, the PCI subsystem switches a
-device function's interrupt mode from MSI-X mode to legacy mode and
-marks all allocated MSI-X vectors as unused.
-
-Once being marked as unused, there is no guarantee that the PCI
-subsystem will reserve these MSI-X vectors for a device. Depending on
-the availability of current PCI vector resources and the number of
-MSI/MSI-X requests from other drivers, these MSI-X vectors may be
-re-assigned.
-
-For the case where the PCI subsystem re-assigned these MSI-X vectors
-to other drivers, a request to switch back to MSI-X mode may result
-being assigned with another set of MSI-X vectors or a failure if no
-more vectors are available.
-
-5.4 Handling function implementing both MSI and MSI-X capabilities
-
-For the case where a function implements both MSI and MSI-X
-capabilities, the PCI subsystem enables a device to run either in MSI
-mode or MSI-X mode but not both. A device driver determines whether it
-wants MSI or MSI-X enabled on its hardware device. Once a device
-driver requests for MSI, for example, it is prohibited from requesting
-MSI-X; in other words, a device driver is not permitted to ping-pong
-between MSI mod MSI-X mode during a run-time.
-
-5.5 Hardware requirements for MSI/MSI-X support
-
-MSI/MSI-X support requires support from both system hardware and
-individual hardware device functions.
-
-5.5.1 Required x86 hardware support
-
-Since the target of MSI address is the local APIC CPU, enabling
-MSI/MSI-X support in the Linux kernel is dependent on whether existing
-system hardware supports local APIC. Users should verify that their
-system supports local APIC operation by testing that it runs when
-CONFIG_X86_LOCAL_APIC=y.
-
-In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set;
-however, in UP environment, users must manually set
-CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
-CONFIG_PCI_MSI enables the VECTOR based scheme and the option for
-MSI-capable device drivers to selectively enable MSI/MSI-X.
-
-Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI/MSI-X
-vector is allocated new during runtime and MSI/MSI-X support does not
-depend on BIOS support. This key independency enables MSI/MSI-X
-support on future IOxAPIC free platforms.
-
-5.5.2 Device hardware support
-
-The hardware device function supports MSI by indicating the
-MSI/MSI-X capability structure on its PCI capability list. By
-default, this capability structure will not be initialized by
-the kernel to enable MSI during the system boot. In other words,
-the device function is running on its default pin assertion mode.
-Note that in many cases the hardware supporting MSI have bugs,
-which may result in system hangs. The software driver of specific
-MSI-capable hardware is responsible for deciding whether to call
-pci_enable_msi or not. A return of zero indicates the kernel
-successfully initialized the MSI/MSI-X capability structure of the
-device function. The device function is now running on MSI/MSI-X mode.
-
-5.6 How to tell whether MSI/MSI-X is enabled on device function
-
-At the driver level, a return of zero from the function call of
-pci_enable_msi()/pci_enable_msix() indicates to a device driver that
-its device function is initialized successfully and ready to run in
-MSI/MSI-X mode.
-
-At the user level, users can use the command 'cat /proc/interrupts'
-to display the vectors allocated for devices and their interrupt
-MSI/MSI-X modes ("PCI-MSI"/"PCI-MSI-X"). Below shows MSI mode is
-enabled on a SCSI Adaptec 39320D Ultra320 controller.
-
- CPU0 CPU1
- 0: 324639 0 IO-APIC-edge timer
- 1: 1186 0 IO-APIC-edge i8042
- 2: 0 0 XT-PIC cascade
- 12: 2797 0 IO-APIC-edge i8042
- 14: 6543 0 IO-APIC-edge ide0
- 15: 1 0 IO-APIC-edge ide1
-169: 0 0 IO-APIC-level uhci-hcd
-185: 0 0 IO-APIC-level uhci-hcd
-193: 138 10 PCI-MSI aic79xx
-201: 30 0 PCI-MSI aic79xx
-225: 30 0 IO-APIC-level aic7xxx
-233: 30 0 IO-APIC-level aic7xxx
-NMI: 0 0
-LOC: 324553 325068
-ERR: 0
-MIS: 0
-
-6. MSI quirks
-
-Several PCI chipsets or devices are known to not support MSI.
-The PCI stack provides 3 possible levels of MSI disabling:
-* on a single device
-* on all devices behind a specific bridge
-* globally
-
-6.1. Disabling MSI on a single device
-
-Under some circumstances it might be required to disable MSI on a
-single device. This may be achieved by either not calling pci_enable_msi()
-or all, or setting the pci_dev->no_msi flag before (most of the time
-in a quirk).
-
-6.2. Disabling MSI below a bridge
-
-The vast majority of MSI quirks are required by PCI bridges not
-being able to route MSI between busses. In this case, MSI have to be
-disabled on all devices behind this bridge. It is achieves by setting
-the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge
-subordinate bus. There is no need to set the same flag on bridges that
-are below the broken bridge. When pci_enable_msi() is called to enable
-MSI on a device, pci_msi_supported() takes care of checking the NO_MSI
-flag in all parent busses of the device.
-
-Some bridges actually support dynamic MSI support enabling/disabling
-by changing some bits in their PCI configuration space (especially
-the Hypertransport chipsets such as the nVidia nForce and Serverworks
-HT2000). It may then be required to update the NO_MSI flag on the
-corresponding devices in the sysfs hierarchy. To enable MSI support
-on device "0000:00:0e", do:
-
- echo 1 > /sys/bus/pci/devices/0000:00:0e/msi_bus
-
-To disable MSI support, echo 0 instead of 1. Note that it should be
-used with caution since changing this value might break interrupts.
-
-6.3. Disabling MSI globally
-
-Some extreme cases may require to disable MSI globally on the system.
-For now, the only known case is a Serverworks PCI-X chipsets (MSI are
-not supported on several busses that are not all connected to the
-chipset in the Linux PCI hierarchy). In the vast majority of other
-cases, disabling only behind a specific bridge is enough.
-
-For debugging purpose, the user may also pass pci=nomsi on the kernel
-command-line to explicitly disable MSI globally. But, once the appro-
-priate quirks are added to the kernel, this option should not be
-required anymore.
-
-6.4. Finding why MSI cannot be enabled on a device
-
-Assuming that MSI are not enabled on a device, you should look at
-dmesg to find messages that quirks may output when disabling MSI
-on some devices, some bridges or even globally.
-Then, lspci -t gives the list of bridges above a device. Reading
-/sys/bus/pci/devices/0000:00:0e/msi_bus will tell you whether MSI
-are enabled (1) or disabled (0). In 0 is found in a single bridge
-msi_bus file above the device, MSI cannot be enabled.
-
-7. FAQ
-
-Q1. Are there any limitations on using the MSI?
-
-A1. If the PCI device supports MSI and conforms to the
-specification and the platform supports the APIC local bus,
-then using MSI should work.
-
-Q2. Will it work on all the Pentium processors (P3, P4, Xeon,
-AMD processors)? In P3 IPI's are transmitted on the APIC local
-bus and in P4 and Xeon they are transmitted on the system
-bus. Are there any implications with this?
-
-A2. MSI support enables a PCI device sending an inbound
-memory write (0xfeexxxxx as target address) on its PCI bus
-directly to the FSB. Since the message address has a
-redirection hint bit cleared, it should work.
-
-Q3. The target address 0xfeexxxxx will be translated by the
-Host Bridge into an interrupt message. Are there any
-limitations on the chipsets such as Intel 8xx, Intel e7xxx,
-or VIA?
-
-A3. If these chipsets support an inbound memory write with
-target address set as 0xfeexxxxx, as conformed to PCI
-specification 2.3 or latest, then it should work.
-
-Q4. From the driver point of view, if the MSI is lost because
-of errors occurring during inbound memory write, then it may
-wait forever. Is there a mechanism for it to recover?
-
-A4. Since the target of the transaction is an inbound memory
-write, all transaction termination conditions (Retry,
-Master-Abort, Target-Abort, or normal completion) are
-supported. A device sending an MSI must abide by all the PCI
-rules and conditions regarding that inbound memory write. So,
-if a retry is signaled it must retry, etc... We believe that
-the recommendation for Abort is also a retry (refer to PCI
-specification 2.3 or latest).
00-INDEX
- this file
+MSI-HOWTO.txt
+ - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
PCI-DMA-mapping.txt
- info for PCI drivers using DMA portably across all platforms
PCIEBUS-HOWTO.txt
--- /dev/null
+ The MSI Driver Guide HOWTO
+ Tom L Nguyen tom.l.nguyen@intel.com
+ 10/03/2003
+ Revised Feb 12, 2004 by Martine Silbermann
+ email: Martine.Silbermann@hp.com
+ Revised Jun 25, 2004 by Tom L Nguyen
+
+1. About this guide
+
+This guide describes the basics of Message Signaled Interrupts (MSI),
+the advantages of using MSI over traditional interrupt mechanisms,
+and how to enable your driver to use MSI or MSI-X. Also included is
+a Frequently Asked Questions (FAQ) section.
+
+1.1 Terminology
+
+PCI devices can be single-function or multi-function. In either case,
+when this text talks about enabling or disabling MSI on a "device
+function," it is referring to one specific PCI device and function and
+not to all functions on a PCI device (unless the PCI device has only
+one function).
+
+2. Copyright 2003 Intel Corporation
+
+3. What is MSI/MSI-X?
+
+Message Signaled Interrupt (MSI), as described in the PCI Local Bus
+Specification Revision 2.3 or later, is an optional feature, and a
+required feature for PCI Express devices. MSI enables a device function
+to request service by sending an Inbound Memory Write on its PCI bus to
+the FSB as a Message Signal Interrupt transaction. Because MSI is
+generated in the form of a Memory Write, all transaction conditions,
+such as a Retry, Master-Abort, Target-Abort or normal completion, are
+supported.
+
+A PCI device that supports MSI must also support pin IRQ assertion
+interrupt mechanism to provide backward compatibility for systems that
+do not support MSI. In systems which support MSI, the bus driver is
+responsible for initializing the message address and message data of
+the device function's MSI/MSI-X capability structure during device
+initial configuration.
+
+An MSI capable device function indicates MSI support by implementing
+the MSI/MSI-X capability structure in its PCI capability list. The
+device function may implement both the MSI capability structure and
+the MSI-X capability structure; however, the bus driver should not
+enable both.
+
+The MSI capability structure contains Message Control register,
+Message Address register and Message Data register. These registers
+provide the bus driver control over MSI. The Message Control register
+indicates the MSI capability supported by the device. The Message
+Address register specifies the target address and the Message Data
+register specifies the characteristics of the message. To request
+service, the device function writes the content of the Message Data
+register to the target address. The device and its software driver
+are prohibited from writing to these registers.
+
+The MSI-X capability structure is an optional extension to MSI. It
+uses an independent and separate capability structure. There are
+some key advantages to implementing the MSI-X capability structure
+over the MSI capability structure as described below.
+
+ - Support a larger maximum number of vectors per function.
+
+ - Provide the ability for system software to configure
+ each vector with an independent message address and message
+ data, specified by a table that resides in Memory Space.
+
+ - MSI and MSI-X both support per-vector masking. Per-vector
+ masking is an optional extension of MSI but a required
+ feature for MSI-X. Per-vector masking provides the kernel the
+ ability to mask/unmask a single MSI while running its
+ interrupt service routine. If per-vector masking is
+ not supported, then the device driver should provide the
+ hardware/software synchronization to ensure that the device
+ generates MSI when the driver wants it to do so.
+
+4. Why use MSI?
+
+As a benefit to the simplification of board design, MSI allows board
+designers to remove out-of-band interrupt routing. MSI is another
+step towards a legacy-free environment.
+
+Due to increasing pressure on chipset and processor packages to
+reduce pin count, the need for interrupt pins is expected to
+diminish over time. Devices, due to pin constraints, may implement
+messages to increase performance.
+
+PCI Express endpoints uses INTx emulation (in-band messages) instead
+of IRQ pin assertion. Using INTx emulation requires interrupt
+sharing among devices connected to the same node (PCI bridge) while
+MSI is unique (non-shared) and does not require BIOS configuration
+support. As a result, the PCI Express technology requires MSI
+support for better interrupt performance.
+
+Using MSI enables the device functions to support two or more
+vectors, which can be configured to target different CPUs to
+increase scalability.
+
+5. Configuring a driver to use MSI/MSI-X
+
+By default, the kernel will not enable MSI/MSI-X on all devices that
+support this capability. The CONFIG_PCI_MSI kernel option
+must be selected to enable MSI/MSI-X support.
+
+5.1 Including MSI/MSI-X support into the kernel
+
+To allow MSI/MSI-X capable device drivers to selectively enable
+MSI/MSI-X (using pci_enable_msi()/pci_enable_msix() as described
+below), the VECTOR based scheme needs to be enabled by setting
+CONFIG_PCI_MSI during kernel config.
+
+Since the target of the inbound message is the local APIC, providing
+CONFIG_X86_LOCAL_APIC must be enabled as well as CONFIG_PCI_MSI.
+
+5.2 Configuring for MSI support
+
+Due to the non-contiguous fashion in vector assignment of the
+existing Linux kernel, this version does not support multiple
+messages regardless of a device function is capable of supporting
+more than one vector. To enable MSI on a device function's MSI
+capability structure requires a device driver to call the function
+pci_enable_msi() explicitly.
+
+5.2.1 API pci_enable_msi
+
+int pci_enable_msi(struct pci_dev *dev)
+
+With this new API, a device driver that wants to have MSI
+enabled on its device function must call this API to enable MSI.
+A successful call will initialize the MSI capability structure
+with ONE vector, regardless of whether a device function is
+capable of supporting multiple messages. This vector replaces the
+pre-assigned dev->irq with a new MSI vector. To avoid a conflict
+of the new assigned vector with existing pre-assigned vector requires
+a device driver to call this API before calling request_irq().
+
+5.2.2 API pci_disable_msi
+
+void pci_disable_msi(struct pci_dev *dev)
+
+This API should always be used to undo the effect of pci_enable_msi()
+when a device driver is unloading. This API restores dev->irq with
+the pre-assigned IOAPIC vector and switches a device's interrupt
+mode to PCI pin-irq assertion/INTx emulation mode.
+
+Note that a device driver should always call free_irq() on the MSI vector
+that it has done request_irq() on before calling this API. Failure to do
+so results in a BUG_ON() and a device will be left with MSI enabled and
+leaks its vector.
+
+5.2.3 MSI mode vs. legacy mode diagram
+
+The below diagram shows the events which switch the interrupt
+mode on the MSI-capable device function between MSI mode and
+PIN-IRQ assertion mode.
+
+ ------------ pci_enable_msi ------------------------
+ | | <=============== | |
+ | MSI MODE | | PIN-IRQ ASSERTION MODE |
+ | | ===============> | |
+ ------------ pci_disable_msi ------------------------
+
+
+Figure 1. MSI Mode vs. Legacy Mode
+
+In Figure 1, a device operates by default in legacy mode. Legacy
+in this context means PCI pin-irq assertion or PCI-Express INTx
+emulation. A successful MSI request (using pci_enable_msi()) switches
+a device's interrupt mode to MSI mode. A pre-assigned IOAPIC vector
+stored in dev->irq will be saved by the PCI subsystem and a new
+assigned MSI vector will replace dev->irq.
+
+To return back to its default mode, a device driver should always call
+pci_disable_msi() to undo the effect of pci_enable_msi(). Note that a
+device driver should always call free_irq() on the MSI vector it has
+done request_irq() on before calling pci_disable_msi(). Failure to do
+so results in a BUG_ON() and a device will be left with MSI enabled and
+leaks its vector. Otherwise, the PCI subsystem restores a device's
+dev->irq with a pre-assigned IOAPIC vector and marks the released
+MSI vector as unused.
+
+Once being marked as unused, there is no guarantee that the PCI
+subsystem will reserve this MSI vector for a device. Depending on
+the availability of current PCI vector resources and the number of
+MSI/MSI-X requests from other drivers, this MSI may be re-assigned.
+
+For the case where the PCI subsystem re-assigns this MSI vector to
+another driver, a request to switch back to MSI mode may result
+in being assigned a different MSI vector or a failure if no more
+vectors are available.
+
+5.3 Configuring for MSI-X support
+
+Due to the ability of the system software to configure each vector of
+the MSI-X capability structure with an independent message address
+and message data, the non-contiguous fashion in vector assignment of
+the existing Linux kernel has no impact on supporting multiple
+messages on an MSI-X capable device functions. To enable MSI-X on
+a device function's MSI-X capability structure requires its device
+driver to call the function pci_enable_msix() explicitly.
+
+The function pci_enable_msix(), once invoked, enables either
+all or nothing, depending on the current availability of PCI vector
+resources. If the PCI vector resources are available for the number
+of vectors requested by a device driver, this function will configure
+the MSI-X table of the MSI-X capability structure of a device with
+requested messages. To emphasize this reason, for example, a device
+may be capable for supporting the maximum of 32 vectors while its
+software driver usually may request 4 vectors. It is recommended
+that the device driver should call this function once during the
+initialization phase of the device driver.
+
+Unlike the function pci_enable_msi(), the function pci_enable_msix()
+does not replace the pre-assigned IOAPIC dev->irq with a new MSI
+vector because the PCI subsystem writes the 1:1 vector-to-entry mapping
+into the field vector of each element contained in a second argument.
+Note that the pre-assigned IOAPIC dev->irq is valid only if the device
+operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at
+using dev->irq by the device driver to request for interrupt service
+may result in unpredictable behavior.
+
+For each MSI-X vector granted, a device driver is responsible for calling
+other functions like request_irq(), enable_irq(), etc. to enable
+this vector with its corresponding interrupt service handler. It is
+a device driver's choice to assign all vectors with the same
+interrupt service handler or each vector with a unique interrupt
+service handler.
+
+5.3.1 Handling MMIO address space of MSI-X Table
+
+The PCI 3.0 specification has implementation notes that MMIO address
+space for a device's MSI-X structure should be isolated so that the
+software system can set different pages for controlling accesses to the
+MSI-X structure. The implementation of MSI support requires the PCI
+subsystem, not a device driver, to maintain full control of the MSI-X
+table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X
+table/MSI-X PBA. A device driver should not access the MMIO address
+space of the MSI-X table/MSI-X PBA.
+
+5.3.2 API pci_enable_msix
+
+int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
+
+This API enables a device driver to request the PCI subsystem
+to enable MSI-X messages on its hardware device. Depending on
+the availability of PCI vectors resources, the PCI subsystem enables
+either all or none of the requested vectors.
+
+Argument 'dev' points to the device (pci_dev) structure.
+
+Argument 'entries' is a pointer to an array of msix_entry structs.
+The number of entries is indicated in argument 'nvec'.
+struct msix_entry is defined in /driver/pci/msi.h:
+
+struct msix_entry {
+ u16 vector; /* kernel uses to write alloc vector */
+ u16 entry; /* driver uses to specify entry */
+};
+
+A device driver is responsible for initializing the field 'entry' of
+each element with a unique entry supported by MSI-X table. Otherwise,
+-EINVAL will be returned as a result. A successful return of zero
+indicates the PCI subsystem completed initializing each of the requested
+entries of the MSI-X table with message address and message data.
+Last but not least, the PCI subsystem will write the 1:1
+vector-to-entry mapping into the field 'vector' of each element. A
+device driver is responsible for keeping track of allocated MSI-X
+vectors in its internal data structure.
+
+A return of zero indicates that the number of MSI-X vectors was
+successfully allocated. A return of greater than zero indicates
+MSI-X vector shortage. Or a return of less than zero indicates
+a failure. This failure may be a result of duplicate entries
+specified in second argument, or a result of no available vector,
+or a result of failing to initialize MSI-X table entries.
+
+5.3.3 API pci_disable_msix
+
+void pci_disable_msix(struct pci_dev *dev)
+
+This API should always be used to undo the effect of pci_enable_msix()
+when a device driver is unloading. Note that a device driver should
+always call free_irq() on all MSI-X vectors it has done request_irq()
+on before calling this API. Failure to do so results in a BUG_ON() and
+a device will be left with MSI-X enabled and leaks its vectors.
+
+5.3.4 MSI-X mode vs. legacy mode diagram
+
+The below diagram shows the events which switch the interrupt
+mode on the MSI-X capable device function between MSI-X mode and
+PIN-IRQ assertion mode (legacy).
+
+ ------------ pci_enable_msix(,,n) ------------------------
+ | | <=============== | |
+ | MSI-X MODE | | PIN-IRQ ASSERTION MODE |
+ | | ===============> | |
+ ------------ pci_disable_msix ------------------------
+
+Figure 2. MSI-X Mode vs. Legacy Mode
+
+In Figure 2, a device operates by default in legacy mode. A
+successful MSI-X request (using pci_enable_msix()) switches a
+device's interrupt mode to MSI-X mode. A pre-assigned IOAPIC vector
+stored in dev->irq will be saved by the PCI subsystem; however,
+unlike MSI mode, the PCI subsystem will not replace dev->irq with
+assigned MSI-X vector because the PCI subsystem already writes the 1:1
+vector-to-entry mapping into the field 'vector' of each element
+specified in second argument.
+
+To return back to its default mode, a device driver should always call
+pci_disable_msix() to undo the effect of pci_enable_msix(). Note that
+a device driver should always call free_irq() on all MSI-X vectors it
+has done request_irq() on before calling pci_disable_msix(). Failure
+to do so results in a BUG_ON() and a device will be left with MSI-X
+enabled and leaks its vectors. Otherwise, the PCI subsystem switches a
+device function's interrupt mode from MSI-X mode to legacy mode and
+marks all allocated MSI-X vectors as unused.
+
+Once being marked as unused, there is no guarantee that the PCI
+subsystem will reserve these MSI-X vectors for a device. Depending on
+the availability of current PCI vector resources and the number of
+MSI/MSI-X requests from other drivers, these MSI-X vectors may be
+re-assigned.
+
+For the case where the PCI subsystem re-assigned these MSI-X vectors
+to other drivers, a request to switch back to MSI-X mode may result
+being assigned with another set of MSI-X vectors or a failure if no
+more vectors are available.
+
+5.4 Handling function implementing both MSI and MSI-X capabilities
+
+For the case where a function implements both MSI and MSI-X
+capabilities, the PCI subsystem enables a device to run either in MSI
+mode or MSI-X mode but not both. A device driver determines whether it
+wants MSI or MSI-X enabled on its hardware device. Once a device
+driver requests for MSI, for example, it is prohibited from requesting
+MSI-X; in other words, a device driver is not permitted to ping-pong
+between MSI mod MSI-X mode during a run-time.
+
+5.5 Hardware requirements for MSI/MSI-X support
+
+MSI/MSI-X support requires support from both system hardware and
+individual hardware device functions.
+
+5.5.1 Required x86 hardware support
+
+Since the target of MSI address is the local APIC CPU, enabling
+MSI/MSI-X support in the Linux kernel is dependent on whether existing
+system hardware supports local APIC. Users should verify that their
+system supports local APIC operation by testing that it runs when
+CONFIG_X86_LOCAL_APIC=y.
+
+In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set;
+however, in UP environment, users must manually set
+CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
+CONFIG_PCI_MSI enables the VECTOR based scheme and the option for
+MSI-capable device drivers to selectively enable MSI/MSI-X.
+
+Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI/MSI-X
+vector is allocated new during runtime and MSI/MSI-X support does not
+depend on BIOS support. This key independency enables MSI/MSI-X
+support on future IOxAPIC free platforms.
+
+5.5.2 Device hardware support
+
+The hardware device function supports MSI by indicating the
+MSI/MSI-X capability structure on its PCI capability list. By
+default, this capability structure will not be initialized by
+the kernel to enable MSI during the system boot. In other words,
+the device function is running on its default pin assertion mode.
+Note that in many cases the hardware supporting MSI have bugs,
+which may result in system hangs. The software driver of specific
+MSI-capable hardware is responsible for deciding whether to call
+pci_enable_msi or not. A return of zero indicates the kernel
+successfully initialized the MSI/MSI-X capability structure of the
+device function. The device function is now running on MSI/MSI-X mode.
+
+5.6 How to tell whether MSI/MSI-X is enabled on device function
+
+At the driver level, a return of zero from the function call of
+pci_enable_msi()/pci_enable_msix() indicates to a device driver that
+its device function is initialized successfully and ready to run in
+MSI/MSI-X mode.
+
+At the user level, users can use the command 'cat /proc/interrupts'
+to display the vectors allocated for devices and their interrupt
+MSI/MSI-X modes ("PCI-MSI"/"PCI-MSI-X"). Below shows MSI mode is
+enabled on a SCSI Adaptec 39320D Ultra320 controller.
+
+ CPU0 CPU1
+ 0: 324639 0 IO-APIC-edge timer
+ 1: 1186 0 IO-APIC-edge i8042
+ 2: 0 0 XT-PIC cascade
+ 12: 2797 0 IO-APIC-edge i8042
+ 14: 6543 0 IO-APIC-edge ide0
+ 15: 1 0 IO-APIC-edge ide1
+169: 0 0 IO-APIC-level uhci-hcd
+185: 0 0 IO-APIC-level uhci-hcd
+193: 138 10 PCI-MSI aic79xx
+201: 30 0 PCI-MSI aic79xx
+225: 30 0 IO-APIC-level aic7xxx
+233: 30 0 IO-APIC-level aic7xxx
+NMI: 0 0
+LOC: 324553 325068
+ERR: 0
+MIS: 0
+
+6. MSI quirks
+
+Several PCI chipsets or devices are known to not support MSI.
+The PCI stack provides 3 possible levels of MSI disabling:
+* on a single device
+* on all devices behind a specific bridge
+* globally
+
+6.1. Disabling MSI on a single device
+
+Under some circumstances it might be required to disable MSI on a
+single device. This may be achieved by either not calling pci_enable_msi()
+or all, or setting the pci_dev->no_msi flag before (most of the time
+in a quirk).
+
+6.2. Disabling MSI below a bridge
+
+The vast majority of MSI quirks are required by PCI bridges not
+being able to route MSI between busses. In this case, MSI have to be
+disabled on all devices behind this bridge. It is achieves by setting
+the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge
+subordinate bus. There is no need to set the same flag on bridges that
+are below the broken bridge. When pci_enable_msi() is called to enable
+MSI on a device, pci_msi_supported() takes care of checking the NO_MSI
+flag in all parent busses of the device.
+
+Some bridges actually support dynamic MSI support enabling/disabling
+by changing some bits in their PCI configuration space (especially
+the Hypertransport chipsets such as the nVidia nForce and Serverworks
+HT2000). It may then be required to update the NO_MSI flag on the
+corresponding devices in the sysfs hierarchy. To enable MSI support
+on device "0000:00:0e", do:
+
+ echo 1 > /sys/bus/pci/devices/0000:00:0e/msi_bus
+
+To disable MSI support, echo 0 instead of 1. Note that it should be
+used with caution since changing this value might break interrupts.
+
+6.3. Disabling MSI globally
+
+Some extreme cases may require to disable MSI globally on the system.
+For now, the only known case is a Serverworks PCI-X chipsets (MSI are
+not supported on several busses that are not all connected to the
+chipset in the Linux PCI hierarchy). In the vast majority of other
+cases, disabling only behind a specific bridge is enough.
+
+For debugging purpose, the user may also pass pci=nomsi on the kernel
+command-line to explicitly disable MSI globally. But, once the appro-
+priate quirks are added to the kernel, this option should not be
+required anymore.
+
+6.4. Finding why MSI cannot be enabled on a device
+
+Assuming that MSI are not enabled on a device, you should look at
+dmesg to find messages that quirks may output when disabling MSI
+on some devices, some bridges or even globally.
+Then, lspci -t gives the list of bridges above a device. Reading
+/sys/bus/pci/devices/0000:00:0e/msi_bus will tell you whether MSI
+are enabled (1) or disabled (0). In 0 is found in a single bridge
+msi_bus file above the device, MSI cannot be enabled.
+
+7. FAQ
+
+Q1. Are there any limitations on using the MSI?
+
+A1. If the PCI device supports MSI and conforms to the
+specification and the platform supports the APIC local bus,
+then using MSI should work.
+
+Q2. Will it work on all the Pentium processors (P3, P4, Xeon,
+AMD processors)? In P3 IPI's are transmitted on the APIC local
+bus and in P4 and Xeon they are transmitted on the system
+bus. Are there any implications with this?
+
+A2. MSI support enables a PCI device sending an inbound
+memory write (0xfeexxxxx as target address) on its PCI bus
+directly to the FSB. Since the message address has a
+redirection hint bit cleared, it should work.
+
+Q3. The target address 0xfeexxxxx will be translated by the
+Host Bridge into an interrupt message. Are there any
+limitations on the chipsets such as Intel 8xx, Intel e7xxx,
+or VIA?
+
+A3. If these chipsets support an inbound memory write with
+target address set as 0xfeexxxxx, as conformed to PCI
+specification 2.3 or latest, then it should work.
+
+Q4. From the driver point of view, if the MSI is lost because
+of errors occurring during inbound memory write, then it may
+wait forever. Is there a mechanism for it to recover?
+
+A4. Since the target of the transaction is an inbound memory
+write, all transaction termination conditions (Retry,
+Master-Abort, Target-Abort, or normal completion) are
+supported. A device sending an MSI must abide by all the PCI
+rules and conditions regarding that inbound memory write. So,
+if a retry is signaled it must retry, etc... We believe that
+the recommendation for Abort is also a retry (refer to PCI
+specification 2.3 or latest).
+++ /dev/null
- Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
-
- Version 2.2.11 for Linux 2.2.19
- Version 2.4.11 for Linux 2.4.12
-
- PRODUCTION RELEASE
-
- 11 October 2001
-
- Leonard N. Zubkoff
- Dandelion Digital
- lnz@dandelion.com
-
- Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
-
-
- INTRODUCTION
-
-Mylex, Inc. designs and manufactures a variety of high performance PCI RAID
-controllers. Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
-California 94555, USA and can be reached at 510.796.6100 or on the World Wide
-Web at http://www.mylex.com. Mylex Technical Support can be reached by
-electronic mail at mylexsup@us.ibm.com, by voice at 510.608.2400, or by FAX at
-510.745.7715. Contact information for offices in Europe and Japan is available
-on their Web site.
-
-The latest information on Linux support for DAC960 PCI RAID Controllers, as
-well as the most recent release of this driver, will always be available from
-my Linux Home Page at URL "http://www.dandelion.com/Linux/". The Linux DAC960
-driver supports all current Mylex PCI RAID controllers including the new
-eXtremeRAID 2000/3000 and AcceleRAID 352/170/160 models which have an entirely
-new firmware interface from the older eXtremeRAID 1100, AcceleRAID 150/200/250,
-and DAC960PJ/PG/PU/PD/PL. See below for a complete controller list as well as
-minimum firmware version requirements. For simplicity, in most places this
-documentation refers to DAC960 generically rather than explicitly listing all
-the supported models.
-
-Driver bug reports should be sent via electronic mail to "lnz@dandelion.com".
-Please include with the bug report the complete configuration messages reported
-by the driver at startup, along with any subsequent system messages relevant to
-the controller's operation, and a detailed description of your system's
-hardware configuration. Driver bugs are actually quite rare; if you encounter
-problems with disks being marked offline, for example, please contact Mylex
-Technical Support as the problem is related to the hardware configuration
-rather than the Linux driver.
-
-Please consult the RAID controller documentation for detailed information
-regarding installation and configuration of the controllers. This document
-primarily provides information specific to the Linux support.
-
-
- DRIVER FEATURES
-
-The DAC960 RAID controllers are supported solely as high performance RAID
-controllers, not as interfaces to arbitrary SCSI devices. The Linux DAC960
-driver operates at the block device level, the same level as the SCSI and IDE
-drivers. Unlike other RAID controllers currently supported on Linux, the
-DAC960 driver is not dependent on the SCSI subsystem, and hence avoids all the
-complexity and unnecessary code that would be associated with an implementation
-as a SCSI driver. The DAC960 driver is designed for as high a performance as
-possible with no compromises or extra code for compatibility with lower
-performance devices. The DAC960 driver includes extensive error logging and
-online configuration management capabilities. Except for initial configuration
-of the controller and adding new disk drives, most everything can be handled
-from Linux while the system is operational.
-
-The DAC960 driver is architected to support up to 8 controllers per system.
-Each DAC960 parallel SCSI controller can support up to 15 disk drives per
-channel, for a maximum of 60 drives on a four channel controller; the fibre
-channel eXtremeRAID 3000 controller supports up to 125 disk drives per loop for
-a total of 250 drives. The drives installed on a controller are divided into
-one or more "Drive Groups", and then each Drive Group is subdivided further
-into 1 to 32 "Logical Drives". Each Logical Drive has a specific RAID Level
-and caching policy associated with it, and it appears to Linux as a single
-block device. Logical Drives are further subdivided into up to 7 partitions
-through the normal Linux and PC disk partitioning schemes. Logical Drives are
-also known as "System Drives", and Drive Groups are also called "Packs". Both
-terms are in use in the Mylex documentation; I have chosen to standardize on
-the more generic "Logical Drive" and "Drive Group".
-
-DAC960 RAID disk devices are named in the style of the obsolete Device File
-System (DEVFS). The device corresponding to Logical Drive D on Controller C
-is referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1
-through /dev/rd/cCdDp7. For example, partition 3 of Logical Drive 5 on
-Controller 2 is referred to as /dev/rd/c2d5p3. Note that unlike with SCSI
-disks the device names will not change in the event of a disk drive failure.
-The DAC960 driver is assigned major numbers 48 - 55 with one major number per
-controller. The 8 bits of minor number are divided into 5 bits for the Logical
-Drive and 3 bits for the partition.
-
-
- SUPPORTED DAC960/AcceleRAID/eXtremeRAID PCI RAID CONTROLLERS
-
-The following list comprises the supported DAC960, AcceleRAID, and eXtremeRAID
-PCI RAID Controllers as of the date of this document. It is recommended that
-anyone purchasing a Mylex PCI RAID Controller not in the following table
-contact the author beforehand to verify that it is or will be supported.
-
-eXtremeRAID 3000
- 1 Wide Ultra-2/LVD SCSI channel
- 2 External Fibre FC-AL channels
- 233MHz StrongARM SA 110 Processor
- 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
- 32MB/64MB ECC SDRAM Memory
-
-eXtremeRAID 2000
- 4 Wide Ultra-160 LVD SCSI channels
- 233MHz StrongARM SA 110 Processor
- 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
- 32MB/64MB ECC SDRAM Memory
-
-AcceleRAID 352
- 2 Wide Ultra-160 LVD SCSI channels
- 100MHz Intel i960RN RISC Processor
- 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
- 32MB/64MB ECC SDRAM Memory
-
-AcceleRAID 170
- 1 Wide Ultra-160 LVD SCSI channel
- 100MHz Intel i960RM RISC Processor
- 16MB/32MB/64MB ECC SDRAM Memory
-
-AcceleRAID 160 (AcceleRAID 170LP)
- 1 Wide Ultra-160 LVD SCSI channel
- 100MHz Intel i960RS RISC Processor
- Built in 16M ECC SDRAM Memory
- PCI Low Profile Form Factor - fit for 2U height
-
-eXtremeRAID 1100 (DAC1164P)
- 3 Wide Ultra-2/LVD SCSI channels
- 233MHz StrongARM SA 110 Processor
- 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
- 16MB/32MB/64MB Parity SDRAM Memory with Battery Backup
-
-AcceleRAID 250 (DAC960PTL1)
- Uses onboard Symbios SCSI chips on certain motherboards
- Also includes one onboard Wide Ultra-2/LVD SCSI Channel
- 66MHz Intel i960RD RISC Processor
- 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-AcceleRAID 200 (DAC960PTL0)
- Uses onboard Symbios SCSI chips on certain motherboards
- Includes no onboard SCSI Channels
- 66MHz Intel i960RD RISC Processor
- 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-AcceleRAID 150 (DAC960PRL)
- Uses onboard Symbios SCSI chips on certain motherboards
- Also includes one onboard Wide Ultra-2/LVD SCSI Channel
- 33MHz Intel i960RP RISC Processor
- 4MB Parity EDO Memory
-
-DAC960PJ 1/2/3 Wide Ultra SCSI-3 Channels
- 66MHz Intel i960RD RISC Processor
- 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-DAC960PG 1/2/3 Wide Ultra SCSI-3 Channels
- 33MHz Intel i960RP RISC Processor
- 4MB/8MB ECC EDO Memory
-
-DAC960PU 1/2/3 Wide Ultra SCSI-3 Channels
- Intel i960CF RISC Processor
- 4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-DAC960PD 1/2/3 Wide Fast SCSI-2 Channels
- Intel i960CF RISC Processor
- 4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-DAC960PL 1/2/3 Wide Fast SCSI-2 Channels
- Intel i960 RISC Processor
- 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-DAC960P 1/2/3 Wide Fast SCSI-2 Channels
- Intel i960 RISC Processor
- 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-For the eXtremeRAID 2000/3000 and AcceleRAID 352/170/160, firmware version
-6.00-01 or above is required.
-
-For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required.
-
-For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is
-required.
-
-For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
-
-For the DAC960PU, DAC960PD, DAC960PL, and DAC960P, either firmware version
-3.51-0-04 or above is required (for dual Flash ROM controllers), or firmware
-version 2.73-0-00 or above is required (for single Flash ROM controllers)
-
-Please note that not all SCSI disk drives are suitable for use with DAC960
-controllers, and only particular firmware versions of any given model may
-actually function correctly. Similarly, not all motherboards have a BIOS that
-properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
-DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
-If in doubt, contact Mylex RAID Technical Support (mylexsup@us.ibm.com) to
-verify compatibility. Mylex makes available a hard disk compatibility list at
-http://www.mylex.com/support/hdcomp/hd-lists.html.
-
-
- DRIVER INSTALLATION
-
-This distribution was prepared for Linux kernel version 2.2.19 or 2.4.12.
-
-To install the DAC960 RAID driver, you may use the following commands,
-replacing "/usr/src" with wherever you keep your Linux kernel source tree:
-
- cd /usr/src
- tar -xvzf DAC960-2.2.11.tar.gz (or DAC960-2.4.11.tar.gz)
- mv README.DAC960 linux/Documentation
- mv DAC960.[ch] linux/drivers/block
- patch -p0 < DAC960.patch (if DAC960.patch is included)
- cd linux
- make config
- make bzImage (or zImage)
-
-Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
-standard kernel, run lilo if appropriate, and reboot.
-
-To create the necessary devices in /dev, the "make_rd" script included in
-"DAC960-Utilities.tar.gz" from http://www.dandelion.com/Linux/ may be used.
-LILO 21 and FDISK v2.9 include DAC960 support; also included in this archive
-are patches to LILO 20 and FDISK v2.8 that add DAC960 support, along with
-statically linked executables of LILO and FDISK. This modified version of LILO
-will allow booting from a DAC960 controller and/or mounting the root file
-system from a DAC960.
-
-Red Hat Linux 6.0 and SuSE Linux 6.1 include support for Mylex PCI RAID
-controllers. Installing directly onto a DAC960 may be problematic from other
-Linux distributions until their installation utilities are updated.
-
-
- INSTALLATION NOTES
-
-Before installing Linux or adding DAC960 logical drives to an existing Linux
-system, the controller must first be configured to provide one or more logical
-drives using the BIOS Configuration Utility or DACCF. Please note that since
-there are only at most 6 usable partitions on each logical drive, systems
-requiring more partitions should subdivide a drive group into multiple logical
-drives, each of which can have up to 6 usable partitions. Also, note that with
-large disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63)
-rather than accepting the default 2GB BIOS Geometry (128/32); failing to so do
-will cause the logical drive geometry to have more than 65535 cylinders which
-will make it impossible for FDISK to be used properly. The 8GB BIOS Geometry
-can be enabled by configuring the DAC960 BIOS, which is accessible via Alt-M
-during the BIOS initialization sequence.
-
-For maximum performance and the most efficient E2FSCK performance, it is
-recommended that EXT2 file systems be built with a 4KB block size and 16 block
-stride to match the DAC960 controller's 64KB default stripe size. The command
-"mke2fs -b 4096 -R stride=16 <device>" is appropriate. Unless there will be a
-large number of small files on the file systems, it is also beneficial to add
-the "-i 16384" option to increase the bytes per inode parameter thereby
-reducing the file system metadata. Finally, on systems that will only be run
-with Linux 2.2 or later kernels it is beneficial to enable sparse superblocks
-with the "-s 1" option.
-
-
- DAC960 ANNOUNCEMENTS MAILING LIST
-
-The DAC960 Announcements Mailing List provides a forum for informing Linux
-users of new driver releases and other announcements regarding Linux support
-for DAC960 PCI RAID Controllers. To join the mailing list, send a message to
-"dac960-announce-request@dandelion.com" with the line "subscribe" in the
-message body.
-
-
- CONTROLLER CONFIGURATION AND STATUS MONITORING
-
-The DAC960 RAID controllers running firmware 4.06 or above include a Background
-Initialization facility so that system downtime is minimized both for initial
-installation and subsequent configuration of additional storage. The BIOS
-Configuration Utility (accessible via Alt-R during the BIOS initialization
-sequence) is used to quickly configure the controller, and then the logical
-drives that have been created are available for immediate use even while they
-are still being initialized by the controller. The primary need for online
-configuration and status monitoring is then to avoid system downtime when disk
-drives fail and must be replaced. Mylex's online monitoring and configuration
-utilities are being ported to Linux and will become available at some point in
-the future. Note that with a SAF-TE (SCSI Accessed Fault-Tolerant Enclosure)
-enclosure, the controller is able to rebuild failed drives automatically as
-soon as a drive replacement is made available.
-
-The primary interfaces for controller configuration and status monitoring are
-special files created in the /proc/rd/... hierarchy along with the normal
-system console logging mechanism. Whenever the system is operating, the DAC960
-driver queries each controller for status information every 10 seconds, and
-checks for additional conditions every 60 seconds. The initial status of each
-controller is always available for controller N in /proc/rd/cN/initial_status,
-and the current status as of the last status monitoring query is available in
-/proc/rd/cN/current_status. In addition, status changes are also logged by the
-driver to the system console and will appear in the log files maintained by
-syslog. The progress of asynchronous rebuild or consistency check operations
-is also available in /proc/rd/cN/current_status, and progress messages are
-logged to the system console at most every 60 seconds.
-
-Starting with the 2.2.3/2.0.3 versions of the driver, the status information
-available in /proc/rd/cN/initial_status and /proc/rd/cN/current_status has been
-augmented to include the vendor, model, revision, and serial number (if
-available) for each physical device found connected to the controller:
-
-***** DAC960 RAID Driver Version 2.2.3 of 19 August 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PRL PCI RAID Controller
- Firmware Version: 4.07-0-07, Channels: 1, Memory Size: 16MB
- PCI Bus: 1, Device: 4, Function: 1, I/O Address: Unassigned
- PCI Address: 0xFE300000 mapped at 0xA0800000, IRQ Channel: 21
- Controller Queue Depth: 128, Maximum Blocks per Command: 128
- Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
- Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
- SAF-TE Enclosure Management Enabled
- Physical Devices:
- 0:0 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 68016775HA
- Disk Status: Online, 17928192 blocks
- 0:1 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 68004E53HA
- Disk Status: Online, 17928192 blocks
- 0:2 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 13013935HA
- Disk Status: Online, 17928192 blocks
- 0:3 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 13016897HA
- Disk Status: Online, 17928192 blocks
- 0:4 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 68019905HA
- Disk Status: Online, 17928192 blocks
- 0:5 Vendor: IBM Model: DRVS09D Revision: 0270
- Serial Number: 68012753HA
- Disk Status: Online, 17928192 blocks
- 0:6 Vendor: ESG-SHV Model: SCA HSBP M6 Revision: 0.61
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 89640960 blocks, Write Thru
- No Rebuild or Consistency Check in Progress
-
-To simplify the monitoring process for custom software, the special file
-/proc/rd/status returns "OK" when all DAC960 controllers in the system are
-operating normally and no failures have occurred, or "ALERT" if any logical
-drives are offline or critical or any non-standby physical drives are dead.
-
-Configuration commands for controller N are available via the special file
-/proc/rd/cN/user_command. A human readable command can be written to this
-special file to initiate a configuration operation, and the results of the
-operation can then be read back from the special file in addition to being
-logged to the system console. The shell command sequence
-
- echo "<configuration-command>" > /proc/rd/c0/user_command
- cat /proc/rd/c0/user_command
-
-is typically used to execute configuration commands. The configuration
-commands are:
-
- flush-cache
-
- The "flush-cache" command flushes the controller's cache. The system
- automatically flushes the cache at shutdown or if the driver module is
- unloaded, so this command is only needed to be certain a write back cache
- is flushed to disk before the system is powered off by a command to a UPS.
- Note that the flush-cache command also stops an asynchronous rebuild or
- consistency check, so it should not be used except when the system is being
- halted.
-
- kill <channel>:<target-id>
-
- The "kill" command marks the physical drive <channel>:<target-id> as DEAD.
- This command is provided primarily for testing, and should not be used
- during normal system operation.
-
- make-online <channel>:<target-id>
-
- The "make-online" command changes the physical drive <channel>:<target-id>
- from status DEAD to status ONLINE. In cases where multiple physical drives
- have been killed simultaneously, this command may be used to bring all but
- one of them back online, after which a rebuild to the final drive is
- necessary.
-
- Warning: make-online should only be used on a dead physical drive that is
- an active part of a drive group, never on a standby drive. The command
- should never be used on a dead drive that is part of a critical logical
- drive; rebuild should be used if only a single drive is dead.
-
- make-standby <channel>:<target-id>
-
- The "make-standby" command changes physical drive <channel>:<target-id>
- from status DEAD to status STANDBY. It should only be used in cases where
- a dead drive was replaced after an automatic rebuild was performed onto a
- standby drive. It cannot be used to add a standby drive to the controller
- configuration if one was not created initially; the BIOS Configuration
- Utility must be used for that currently.
-
- rebuild <channel>:<target-id>
-
- The "rebuild" command initiates an asynchronous rebuild onto physical drive
- <channel>:<target-id>. It should only be used when a dead drive has been
- replaced.
-
- check-consistency <logical-drive-number>
-
- The "check-consistency" command initiates an asynchronous consistency check
- of <logical-drive-number> with automatic restoration. It can be used
- whenever it is desired to verify the consistency of the redundancy
- information.
-
- cancel-rebuild
- cancel-consistency-check
-
- The "cancel-rebuild" and "cancel-consistency-check" commands cancel any
- rebuild or consistency check operations previously initiated.
-
-
- EXAMPLE I - DRIVE FAILURE WITHOUT A STANDBY DRIVE
-
-The following annotated logs demonstrate the controller configuration and and
-online status monitoring capabilities of the Linux DAC960 Driver. The test
-configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
-DAC960PJ controller. The physical drives are configured into a single drive
-group without a standby drive, and the drive group has been configured into two
-logical drives, one RAID-5 and one RAID-6. Note that these logs are from an
-earlier version of the driver and the messages have changed somewhat with newer
-releases, but the functionality remains similar. First, here is the current
-status of the RAID configuration:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
- Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
- PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
- PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
- Controller Queue Depth: 128, Maximum Blocks per Command: 128
- Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
- Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
- No Rebuild or Consistency Check in Progress
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-The above messages indicate that everything is healthy, and /proc/rd/status
-returns "OK" indicating that there are no problems with any DAC960 controller
-in the system. For demonstration purposes, while I/O is active Physical Drive
-1:1 is now disconnected, simulating a drive failure. The failure is noted by
-the driver within 10 seconds of the controller's having detected it, and the
-driver logs the following console status messages indicating that Logical
-Drives 0 and 1 are now CRITICAL as a result of Physical Drive 1:1 being DEAD:
-
-DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:1 killed because of timeout on SCSI command
-DAC960#0: Physical Drive 1:1 is now DEAD
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
-
-The Sense Keys logged here are just Check Condition / Unit Attention conditions
-arising from a SCSI bus reset that is forced by the controller during its error
-recovery procedures. Concurrently with the above, the driver status available
-from /proc/rd also reflects the drive failure. The status message in
-/proc/rd/status has changed from "OK" to "ALERT":
-
-gwynedd:/u/lnz# cat /proc/rd/status
-ALERT
-
-and /proc/rd/c0/current_status has been updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Dead, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
- No Rebuild or Consistency Check in Progress
-
-Since there are no standby drives configured, the system can continue to access
-the logical drives in a performance degraded mode until the failed drive is
-replaced and a rebuild operation completed to restore the redundancy of the
-logical drives. Once Physical Drive 1:1 is replaced with a properly
-functioning drive, or if the physical drive was killed without having failed
-(e.g., due to electrical problems on the SCSI bus), the user can instruct the
-controller to initiate a rebuild operation onto the newly replaced drive:
-
-gwynedd:/u/lnz# echo "rebuild 1:1" > /proc/rd/c0/user_command
-gwynedd:/u/lnz# cat /proc/rd/c0/user_command
-Rebuild of Physical Drive 1:1 Initiated
-
-The echo command instructs the controller to initiate an asynchronous rebuild
-operation onto Physical Drive 1:1, and the status message that results from the
-operation is then available for reading from /proc/rd/c0/user_command, as well
-as being logged to the console by the driver.
-
-Within 10 seconds of this command the driver logs the initiation of the
-asynchronous rebuild operation:
-
-DAC960#0: Rebuild of Physical Drive 1:1 Initiated
-DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
-DAC960#0: Physical Drive 1:1 is now WRITE-ONLY
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 1% completed
-
-and /proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Write-Only, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
- Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 6% completed
-
-As the rebuild progresses, the current status in /proc/rd/c0/current_status is
-updated every 10 seconds:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Write-Only, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
- Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 15% completed
-
-and every minute a progress message is logged to the console by the driver:
-
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 32% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 63% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 94% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 94% completed
-
-Finally, the rebuild completes successfully. The driver logs the status of the
-logical and physical drives and the rebuild completion:
-
-DAC960#0: Rebuild Completed Successfully
-DAC960#0: Physical Drive 1:1 is now ONLINE
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
-
-/proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
- Rebuild Completed Successfully
-
-and /proc/rd/status indicates that everything is healthy once again:
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-
- EXAMPLE II - DRIVE FAILURE WITH A STANDBY DRIVE
-
-The following annotated logs demonstrate the controller configuration and and
-online status monitoring capabilities of the Linux DAC960 Driver. The test
-configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
-DAC960PJ controller. The physical drives are configured into a single drive
-group with a standby drive, and the drive group has been configured into two
-logical drives, one RAID-5 and one RAID-6. Note that these logs are from an
-earlier version of the driver and the messages have changed somewhat with newer
-releases, but the functionality remains similar. First, here is the current
-status of the RAID configuration:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
- Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
- PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
- PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
- Controller Queue Depth: 128, Maximum Blocks per Command: 128
- Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
- Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Online, 2201600 blocks
- 1:3 - Disk: Standby, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
- No Rebuild or Consistency Check in Progress
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-The above messages indicate that everything is healthy, and /proc/rd/status
-returns "OK" indicating that there are no problems with any DAC960 controller
-in the system. For demonstration purposes, while I/O is active Physical Drive
-1:2 is now disconnected, simulating a drive failure. The failure is noted by
-the driver within 10 seconds of the controller's having detected it, and the
-driver logs the following console status messages:
-
-DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:2 killed because of timeout on SCSI command
-DAC960#0: Physical Drive 1:2 is now DEAD
-DAC960#0: Physical Drive 1:2 killed because it was removed
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
-
-Since a standby drive is configured, the controller automatically begins
-rebuilding onto the standby drive:
-
-DAC960#0: Physical Drive 1:3 is now WRITE-ONLY
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
-
-Concurrently with the above, the driver status available from /proc/rd also
-reflects the drive failure and automatic rebuild. The status message in
-/proc/rd/status has changed from "OK" to "ALERT":
-
-gwynedd:/u/lnz# cat /proc/rd/status
-ALERT
-
-and /proc/rd/c0/current_status has been updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Dead, 2201600 blocks
- 1:3 - Disk: Write-Only, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
- Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
-
-As the rebuild progresses, the current status in /proc/rd/c0/current_status is
-updated every 10 seconds:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Dead, 2201600 blocks
- 1:3 - Disk: Write-Only, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
- Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
-
-and every minute a progress message is logged on the console by the driver:
-
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 76% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 66% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 84% completed
-
-Finally, the rebuild completes successfully. The driver logs the status of the
-logical and physical drives and the rebuild completion:
-
-DAC960#0: Rebuild Completed Successfully
-DAC960#0: Physical Drive 1:3 is now ONLINE
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
-
-/proc/rd/c0/current_status is updated:
-
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
- Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
- PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
- PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
- Controller Queue Depth: 128, Maximum Blocks per Command: 128
- Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
- Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Dead, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
- Rebuild Completed Successfully
-
-and /proc/rd/status indicates that everything is healthy once again:
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-Note that the absence of a viable standby drive does not create an "ALERT"
-status. Once dead Physical Drive 1:2 has been replaced, the controller must be
-told that this has occurred and that the newly replaced drive should become the
-new standby drive:
-
-gwynedd:/u/lnz# echo "make-standby 1:2" > /proc/rd/c0/user_command
-gwynedd:/u/lnz# cat /proc/rd/c0/user_command
-Make Standby of Physical Drive 1:2 Succeeded
-
-The echo command instructs the controller to make Physical Drive 1:2 into a
-standby drive, and the status message that results from the operation is then
-available for reading from /proc/rd/c0/user_command, as well as being logged to
-the console by the driver. Within 60 seconds of this command the driver logs:
-
-DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
-DAC960#0: Physical Drive 1:2 is now STANDBY
-DAC960#0: Make Standby of Physical Drive 1:2 Succeeded
-
-and /proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
- ...
- Physical Devices:
- 0:1 - Disk: Online, 2201600 blocks
- 0:2 - Disk: Online, 2201600 blocks
- 0:3 - Disk: Online, 2201600 blocks
- 1:1 - Disk: Online, 2201600 blocks
- 1:2 - Disk: Standby, 2201600 blocks
- 1:3 - Disk: Online, 2201600 blocks
- Logical Drives:
- /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
- /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
- Rebuild Completed Successfully
+++ /dev/null
-
-The Cyclades-Z must have firmware loaded onto the card before it will
-operate. This operation should be performed during system startup,
-
-The firmware, loader program and the latest device driver code are
-available from Cyclades at
- ftp://ftp.cyclades.com/pub/cyclades/cyclades-z/linux/
-
--- /dev/null
+00-INDEX
+ - this file
+README.DAC960
+ - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+cciss.txt
+ - info, major/minor #'s for Compaq's SMART Array Controllers.
+cpqarray.txt
+ - info on using Compaq's SMART2 Intelligent Disk Array Controllers.
+floppy.txt
+ - notes and driver options for the floppy disk driver.
+nbd.txt
+ - info on a TCP implementation of a network block device.
+paride.txt
+ - information about the parallel port IDE subsystem.
+ramdisk.txt
+ - short guide on how to set up and use the RAM disk.
--- /dev/null
+ Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
+
+ Version 2.2.11 for Linux 2.2.19
+ Version 2.4.11 for Linux 2.4.12
+
+ PRODUCTION RELEASE
+
+ 11 October 2001
+
+ Leonard N. Zubkoff
+ Dandelion Digital
+ lnz@dandelion.com
+
+ Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+
+ INTRODUCTION
+
+Mylex, Inc. designs and manufactures a variety of high performance PCI RAID
+controllers. Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
+California 94555, USA and can be reached at 510.796.6100 or on the World Wide
+Web at http://www.mylex.com. Mylex Technical Support can be reached by
+electronic mail at mylexsup@us.ibm.com, by voice at 510.608.2400, or by FAX at
+510.745.7715. Contact information for offices in Europe and Japan is available
+on their Web site.
+
+The latest information on Linux support for DAC960 PCI RAID Controllers, as
+well as the most recent release of this driver, will always be available from
+my Linux Home Page at URL "http://www.dandelion.com/Linux/". The Linux DAC960
+driver supports all current Mylex PCI RAID controllers including the new
+eXtremeRAID 2000/3000 and AcceleRAID 352/170/160 models which have an entirely
+new firmware interface from the older eXtremeRAID 1100, AcceleRAID 150/200/250,
+and DAC960PJ/PG/PU/PD/PL. See below for a complete controller list as well as
+minimum firmware version requirements. For simplicity, in most places this
+documentation refers to DAC960 generically rather than explicitly listing all
+the supported models.
+
+Driver bug reports should be sent via electronic mail to "lnz@dandelion.com".
+Please include with the bug report the complete configuration messages reported
+by the driver at startup, along with any subsequent system messages relevant to
+the controller's operation, and a detailed description of your system's
+hardware configuration. Driver bugs are actually quite rare; if you encounter
+problems with disks being marked offline, for example, please contact Mylex
+Technical Support as the problem is related to the hardware configuration
+rather than the Linux driver.
+
+Please consult the RAID controller documentation for detailed information
+regarding installation and configuration of the controllers. This document
+primarily provides information specific to the Linux support.
+
+
+ DRIVER FEATURES
+
+The DAC960 RAID controllers are supported solely as high performance RAID
+controllers, not as interfaces to arbitrary SCSI devices. The Linux DAC960
+driver operates at the block device level, the same level as the SCSI and IDE
+drivers. Unlike other RAID controllers currently supported on Linux, the
+DAC960 driver is not dependent on the SCSI subsystem, and hence avoids all the
+complexity and unnecessary code that would be associated with an implementation
+as a SCSI driver. The DAC960 driver is designed for as high a performance as
+possible with no compromises or extra code for compatibility with lower
+performance devices. The DAC960 driver includes extensive error logging and
+online configuration management capabilities. Except for initial configuration
+of the controller and adding new disk drives, most everything can be handled
+from Linux while the system is operational.
+
+The DAC960 driver is architected to support up to 8 controllers per system.
+Each DAC960 parallel SCSI controller can support up to 15 disk drives per
+channel, for a maximum of 60 drives on a four channel controller; the fibre
+channel eXtremeRAID 3000 controller supports up to 125 disk drives per loop for
+a total of 250 drives. The drives installed on a controller are divided into
+one or more "Drive Groups", and then each Drive Group is subdivided further
+into 1 to 32 "Logical Drives". Each Logical Drive has a specific RAID Level
+and caching policy associated with it, and it appears to Linux as a single
+block device. Logical Drives are further subdivided into up to 7 partitions
+through the normal Linux and PC disk partitioning schemes. Logical Drives are
+also known as "System Drives", and Drive Groups are also called "Packs". Both
+terms are in use in the Mylex documentation; I have chosen to standardize on
+the more generic "Logical Drive" and "Drive Group".
+
+DAC960 RAID disk devices are named in the style of the obsolete Device File
+System (DEVFS). The device corresponding to Logical Drive D on Controller C
+is referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1
+through /dev/rd/cCdDp7. For example, partition 3 of Logical Drive 5 on
+Controller 2 is referred to as /dev/rd/c2d5p3. Note that unlike with SCSI
+disks the device names will not change in the event of a disk drive failure.
+The DAC960 driver is assigned major numbers 48 - 55 with one major number per
+controller. The 8 bits of minor number are divided into 5 bits for the Logical
+Drive and 3 bits for the partition.
+
+
+ SUPPORTED DAC960/AcceleRAID/eXtremeRAID PCI RAID CONTROLLERS
+
+The following list comprises the supported DAC960, AcceleRAID, and eXtremeRAID
+PCI RAID Controllers as of the date of this document. It is recommended that
+anyone purchasing a Mylex PCI RAID Controller not in the following table
+contact the author beforehand to verify that it is or will be supported.
+
+eXtremeRAID 3000
+ 1 Wide Ultra-2/LVD SCSI channel
+ 2 External Fibre FC-AL channels
+ 233MHz StrongARM SA 110 Processor
+ 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+ 32MB/64MB ECC SDRAM Memory
+
+eXtremeRAID 2000
+ 4 Wide Ultra-160 LVD SCSI channels
+ 233MHz StrongARM SA 110 Processor
+ 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+ 32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 352
+ 2 Wide Ultra-160 LVD SCSI channels
+ 100MHz Intel i960RN RISC Processor
+ 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+ 32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 170
+ 1 Wide Ultra-160 LVD SCSI channel
+ 100MHz Intel i960RM RISC Processor
+ 16MB/32MB/64MB ECC SDRAM Memory
+
+AcceleRAID 160 (AcceleRAID 170LP)
+ 1 Wide Ultra-160 LVD SCSI channel
+ 100MHz Intel i960RS RISC Processor
+ Built in 16M ECC SDRAM Memory
+ PCI Low Profile Form Factor - fit for 2U height
+
+eXtremeRAID 1100 (DAC1164P)
+ 3 Wide Ultra-2/LVD SCSI channels
+ 233MHz StrongARM SA 110 Processor
+ 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots)
+ 16MB/32MB/64MB Parity SDRAM Memory with Battery Backup
+
+AcceleRAID 250 (DAC960PTL1)
+ Uses onboard Symbios SCSI chips on certain motherboards
+ Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+ 66MHz Intel i960RD RISC Processor
+ 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 200 (DAC960PTL0)
+ Uses onboard Symbios SCSI chips on certain motherboards
+ Includes no onboard SCSI Channels
+ 66MHz Intel i960RD RISC Processor
+ 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 150 (DAC960PRL)
+ Uses onboard Symbios SCSI chips on certain motherboards
+ Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+ 33MHz Intel i960RP RISC Processor
+ 4MB Parity EDO Memory
+
+DAC960PJ 1/2/3 Wide Ultra SCSI-3 Channels
+ 66MHz Intel i960RD RISC Processor
+ 4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+DAC960PG 1/2/3 Wide Ultra SCSI-3 Channels
+ 33MHz Intel i960RP RISC Processor
+ 4MB/8MB ECC EDO Memory
+
+DAC960PU 1/2/3 Wide Ultra SCSI-3 Channels
+ Intel i960CF RISC Processor
+ 4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PD 1/2/3 Wide Fast SCSI-2 Channels
+ Intel i960CF RISC Processor
+ 4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PL 1/2/3 Wide Fast SCSI-2 Channels
+ Intel i960 RISC Processor
+ 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960P 1/2/3 Wide Fast SCSI-2 Channels
+ Intel i960 RISC Processor
+ 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+For the eXtremeRAID 2000/3000 and AcceleRAID 352/170/160, firmware version
+6.00-01 or above is required.
+
+For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required.
+
+For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is
+required.
+
+For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
+
+For the DAC960PU, DAC960PD, DAC960PL, and DAC960P, either firmware version
+3.51-0-04 or above is required (for dual Flash ROM controllers), or firmware
+version 2.73-0-00 or above is required (for single Flash ROM controllers)
+
+Please note that not all SCSI disk drives are suitable for use with DAC960
+controllers, and only particular firmware versions of any given model may
+actually function correctly. Similarly, not all motherboards have a BIOS that
+properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
+DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
+If in doubt, contact Mylex RAID Technical Support (mylexsup@us.ibm.com) to
+verify compatibility. Mylex makes available a hard disk compatibility list at
+http://www.mylex.com/support/hdcomp/hd-lists.html.
+
+
+ DRIVER INSTALLATION
+
+This distribution was prepared for Linux kernel version 2.2.19 or 2.4.12.
+
+To install the DAC960 RAID driver, you may use the following commands,
+replacing "/usr/src" with wherever you keep your Linux kernel source tree:
+
+ cd /usr/src
+ tar -xvzf DAC960-2.2.11.tar.gz (or DAC960-2.4.11.tar.gz)
+ mv README.DAC960 linux/Documentation
+ mv DAC960.[ch] linux/drivers/block
+ patch -p0 < DAC960.patch (if DAC960.patch is included)
+ cd linux
+ make config
+ make bzImage (or zImage)
+
+Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
+standard kernel, run lilo if appropriate, and reboot.
+
+To create the necessary devices in /dev, the "make_rd" script included in
+"DAC960-Utilities.tar.gz" from http://www.dandelion.com/Linux/ may be used.
+LILO 21 and FDISK v2.9 include DAC960 support; also included in this archive
+are patches to LILO 20 and FDISK v2.8 that add DAC960 support, along with
+statically linked executables of LILO and FDISK. This modified version of LILO
+will allow booting from a DAC960 controller and/or mounting the root file
+system from a DAC960.
+
+Red Hat Linux 6.0 and SuSE Linux 6.1 include support for Mylex PCI RAID
+controllers. Installing directly onto a DAC960 may be problematic from other
+Linux distributions until their installation utilities are updated.
+
+
+ INSTALLATION NOTES
+
+Before installing Linux or adding DAC960 logical drives to an existing Linux
+system, the controller must first be configured to provide one or more logical
+drives using the BIOS Configuration Utility or DACCF. Please note that since
+there are only at most 6 usable partitions on each logical drive, systems
+requiring more partitions should subdivide a drive group into multiple logical
+drives, each of which can have up to 6 usable partitions. Also, note that with
+large disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63)
+rather than accepting the default 2GB BIOS Geometry (128/32); failing to so do
+will cause the logical drive geometry to have more than 65535 cylinders which
+will make it impossible for FDISK to be used properly. The 8GB BIOS Geometry
+can be enabled by configuring the DAC960 BIOS, which is accessible via Alt-M
+during the BIOS initialization sequence.
+
+For maximum performance and the most efficient E2FSCK performance, it is
+recommended that EXT2 file systems be built with a 4KB block size and 16 block
+stride to match the DAC960 controller's 64KB default stripe size. The command
+"mke2fs -b 4096 -R stride=16 <device>" is appropriate. Unless there will be a
+large number of small files on the file systems, it is also beneficial to add
+the "-i 16384" option to increase the bytes per inode parameter thereby
+reducing the file system metadata. Finally, on systems that will only be run
+with Linux 2.2 or later kernels it is beneficial to enable sparse superblocks
+with the "-s 1" option.
+
+
+ DAC960 ANNOUNCEMENTS MAILING LIST
+
+The DAC960 Announcements Mailing List provides a forum for informing Linux
+users of new driver releases and other announcements regarding Linux support
+for DAC960 PCI RAID Controllers. To join the mailing list, send a message to
+"dac960-announce-request@dandelion.com" with the line "subscribe" in the
+message body.
+
+
+ CONTROLLER CONFIGURATION AND STATUS MONITORING
+
+The DAC960 RAID controllers running firmware 4.06 or above include a Background
+Initialization facility so that system downtime is minimized both for initial
+installation and subsequent configuration of additional storage. The BIOS
+Configuration Utility (accessible via Alt-R during the BIOS initialization
+sequence) is used to quickly configure the controller, and then the logical
+drives that have been created are available for immediate use even while they
+are still being initialized by the controller. The primary need for online
+configuration and status monitoring is then to avoid system downtime when disk
+drives fail and must be replaced. Mylex's online monitoring and configuration
+utilities are being ported to Linux and will become available at some point in
+the future. Note that with a SAF-TE (SCSI Accessed Fault-Tolerant Enclosure)
+enclosure, the controller is able to rebuild failed drives automatically as
+soon as a drive replacement is made available.
+
+The primary interfaces for controller configuration and status monitoring are
+special files created in the /proc/rd/... hierarchy along with the normal
+system console logging mechanism. Whenever the system is operating, the DAC960
+driver queries each controller for status information every 10 seconds, and
+checks for additional conditions every 60 seconds. The initial status of each
+controller is always available for controller N in /proc/rd/cN/initial_status,
+and the current status as of the last status monitoring query is available in
+/proc/rd/cN/current_status. In addition, status changes are also logged by the
+driver to the system console and will appear in the log files maintained by
+syslog. The progress of asynchronous rebuild or consistency check operations
+is also available in /proc/rd/cN/current_status, and progress messages are
+logged to the system console at most every 60 seconds.
+
+Starting with the 2.2.3/2.0.3 versions of the driver, the status information
+available in /proc/rd/cN/initial_status and /proc/rd/cN/current_status has been
+augmented to include the vendor, model, revision, and serial number (if
+available) for each physical device found connected to the controller:
+
+***** DAC960 RAID Driver Version 2.2.3 of 19 August 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PRL PCI RAID Controller
+ Firmware Version: 4.07-0-07, Channels: 1, Memory Size: 16MB
+ PCI Bus: 1, Device: 4, Function: 1, I/O Address: Unassigned
+ PCI Address: 0xFE300000 mapped at 0xA0800000, IRQ Channel: 21
+ Controller Queue Depth: 128, Maximum Blocks per Command: 128
+ Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+ Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+ SAF-TE Enclosure Management Enabled
+ Physical Devices:
+ 0:0 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 68016775HA
+ Disk Status: Online, 17928192 blocks
+ 0:1 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 68004E53HA
+ Disk Status: Online, 17928192 blocks
+ 0:2 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 13013935HA
+ Disk Status: Online, 17928192 blocks
+ 0:3 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 13016897HA
+ Disk Status: Online, 17928192 blocks
+ 0:4 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 68019905HA
+ Disk Status: Online, 17928192 blocks
+ 0:5 Vendor: IBM Model: DRVS09D Revision: 0270
+ Serial Number: 68012753HA
+ Disk Status: Online, 17928192 blocks
+ 0:6 Vendor: ESG-SHV Model: SCA HSBP M6 Revision: 0.61
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 89640960 blocks, Write Thru
+ No Rebuild or Consistency Check in Progress
+
+To simplify the monitoring process for custom software, the special file
+/proc/rd/status returns "OK" when all DAC960 controllers in the system are
+operating normally and no failures have occurred, or "ALERT" if any logical
+drives are offline or critical or any non-standby physical drives are dead.
+
+Configuration commands for controller N are available via the special file
+/proc/rd/cN/user_command. A human readable command can be written to this
+special file to initiate a configuration operation, and the results of the
+operation can then be read back from the special file in addition to being
+logged to the system console. The shell command sequence
+
+ echo "<configuration-command>" > /proc/rd/c0/user_command
+ cat /proc/rd/c0/user_command
+
+is typically used to execute configuration commands. The configuration
+commands are:
+
+ flush-cache
+
+ The "flush-cache" command flushes the controller's cache. The system
+ automatically flushes the cache at shutdown or if the driver module is
+ unloaded, so this command is only needed to be certain a write back cache
+ is flushed to disk before the system is powered off by a command to a UPS.
+ Note that the flush-cache command also stops an asynchronous rebuild or
+ consistency check, so it should not be used except when the system is being
+ halted.
+
+ kill <channel>:<target-id>
+
+ The "kill" command marks the physical drive <channel>:<target-id> as DEAD.
+ This command is provided primarily for testing, and should not be used
+ during normal system operation.
+
+ make-online <channel>:<target-id>
+
+ The "make-online" command changes the physical drive <channel>:<target-id>
+ from status DEAD to status ONLINE. In cases where multiple physical drives
+ have been killed simultaneously, this command may be used to bring all but
+ one of them back online, after which a rebuild to the final drive is
+ necessary.
+
+ Warning: make-online should only be used on a dead physical drive that is
+ an active part of a drive group, never on a standby drive. The command
+ should never be used on a dead drive that is part of a critical logical
+ drive; rebuild should be used if only a single drive is dead.
+
+ make-standby <channel>:<target-id>
+
+ The "make-standby" command changes physical drive <channel>:<target-id>
+ from status DEAD to status STANDBY. It should only be used in cases where
+ a dead drive was replaced after an automatic rebuild was performed onto a
+ standby drive. It cannot be used to add a standby drive to the controller
+ configuration if one was not created initially; the BIOS Configuration
+ Utility must be used for that currently.
+
+ rebuild <channel>:<target-id>
+
+ The "rebuild" command initiates an asynchronous rebuild onto physical drive
+ <channel>:<target-id>. It should only be used when a dead drive has been
+ replaced.
+
+ check-consistency <logical-drive-number>
+
+ The "check-consistency" command initiates an asynchronous consistency check
+ of <logical-drive-number> with automatic restoration. It can be used
+ whenever it is desired to verify the consistency of the redundancy
+ information.
+
+ cancel-rebuild
+ cancel-consistency-check
+
+ The "cancel-rebuild" and "cancel-consistency-check" commands cancel any
+ rebuild or consistency check operations previously initiated.
+
+
+ EXAMPLE I - DRIVE FAILURE WITHOUT A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver. The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller. The physical drives are configured into a single drive
+group without a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6. Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar. First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+ Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+ PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+ PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+ Controller Queue Depth: 128, Maximum Blocks per Command: 128
+ Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+ Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+ No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system. For demonstration purposes, while I/O is active Physical Drive
+1:1 is now disconnected, simulating a drive failure. The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages indicating that Logical
+Drives 0 and 1 are now CRITICAL as a result of Physical Drive 1:1 being DEAD:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:1 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:1 is now DEAD
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+The Sense Keys logged here are just Check Condition / Unit Attention conditions
+arising from a SCSI bus reset that is forced by the controller during its error
+recovery procedures. Concurrently with the above, the driver status available
+from /proc/rd also reflects the drive failure. The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Dead, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+ No Rebuild or Consistency Check in Progress
+
+Since there are no standby drives configured, the system can continue to access
+the logical drives in a performance degraded mode until the failed drive is
+replaced and a rebuild operation completed to restore the redundancy of the
+logical drives. Once Physical Drive 1:1 is replaced with a properly
+functioning drive, or if the physical drive was killed without having failed
+(e.g., due to electrical problems on the SCSI bus), the user can instruct the
+controller to initiate a rebuild operation onto the newly replaced drive:
+
+gwynedd:/u/lnz# echo "rebuild 1:1" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Rebuild of Physical Drive 1:1 Initiated
+
+The echo command instructs the controller to initiate an asynchronous rebuild
+operation onto Physical Drive 1:1, and the status message that results from the
+operation is then available for reading from /proc/rd/c0/user_command, as well
+as being logged to the console by the driver.
+
+Within 10 seconds of this command the driver logs the initiation of the
+asynchronous rebuild operation:
+
+DAC960#0: Rebuild of Physical Drive 1:1 Initiated
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:1 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 1% completed
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Write-Only, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+ Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 6% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Write-Only, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+ Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 15% completed
+
+and every minute a progress message is logged to the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 32% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 63% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 94% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 94% completed
+
+Finally, the rebuild completes successfully. The driver logs the status of the
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:1 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+ Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+
+ EXAMPLE II - DRIVE FAILURE WITH A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver. The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller. The physical drives are configured into a single drive
+group with a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6. Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar. First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+ Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+ PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+ PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+ Controller Queue Depth: 128, Maximum Blocks per Command: 128
+ Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+ Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Online, 2201600 blocks
+ 1:3 - Disk: Standby, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+ No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system. For demonstration purposes, while I/O is active Physical Drive
+1:2 is now disconnected, simulating a drive failure. The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages:
+
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:2 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:2 is now DEAD
+DAC960#0: Physical Drive 1:2 killed because it was removed
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+Since a standby drive is configured, the controller automatically begins
+rebuilding onto the standby drive:
+
+DAC960#0: Physical Drive 1:3 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+Concurrently with the above, the driver status available from /proc/rd also
+reflects the drive failure and automatic rebuild. The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Dead, 2201600 blocks
+ 1:3 - Disk: Write-Only, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+ Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Dead, 2201600 blocks
+ 1:3 - Disk: Write-Only, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+ Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+
+and every minute a progress message is logged on the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 76% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 66% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 84% completed
+
+Finally, the rebuild completes successfully. The driver logs the status of the
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:3 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+ Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+ PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+ PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+ Controller Queue Depth: 128, Maximum Blocks per Command: 128
+ Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+ Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Dead, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+ Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+Note that the absence of a viable standby drive does not create an "ALERT"
+status. Once dead Physical Drive 1:2 has been replaced, the controller must be
+told that this has occurred and that the newly replaced drive should become the
+new standby drive:
+
+gwynedd:/u/lnz# echo "make-standby 1:2" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Make Standby of Physical Drive 1:2 Succeeded
+
+The echo command instructs the controller to make Physical Drive 1:2 into a
+standby drive, and the status message that results from the operation is then
+available for reading from /proc/rd/c0/user_command, as well as being logged to
+the console by the driver. Within 60 seconds of this command the driver logs:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:2 is now STANDBY
+DAC960#0: Make Standby of Physical Drive 1:2 Succeeded
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+ ...
+ Physical Devices:
+ 0:1 - Disk: Online, 2201600 blocks
+ 0:2 - Disk: Online, 2201600 blocks
+ 0:3 - Disk: Online, 2201600 blocks
+ 1:1 - Disk: Online, 2201600 blocks
+ 1:2 - Disk: Standby, 2201600 blocks
+ 1:3 - Disk: Online, 2201600 blocks
+ Logical Drives:
+ /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+ /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+ Rebuild Completed Successfully
--- /dev/null
+This driver is for Compaq's SMART Array Controllers.
+
+Supported Cards:
+----------------
+
+This driver is known to work with the following cards:
+
+ * SA 5300
+ * SA 5i
+ * SA 532
+ * SA 5312
+ * SA 641
+ * SA 642
+ * SA 6400
+ * SA 6400 U320 Expansion Module
+ * SA 6i
+ * SA P600
+ * SA P800
+ * SA E400
+ * SA P400i
+ * SA E200
+ * SA E200i
+ * SA E500
+ * SA P700m
+ * SA P212
+ * SA P410
+ * SA P410i
+ * SA P411
+ * SA P812
+ * SA P712m
+ * SA P711m
+
+Detecting drive failures:
+-------------------------
+
+To get the status of logical volumes and to detect physical drive
+failures, you can use the cciss_vol_status program found here:
+http://cciss.sourceforge.net/#cciss_utils
+
+Device Naming:
+--------------
+
+If nodes are not already created in the /dev/cciss directory, run as root:
+
+# cd /dev
+# ./MAKEDEV cciss
+
+You need some entries in /dev for the cciss device. The MAKEDEV script
+can make device nodes for you automatically. Currently the device setup
+is as follows:
+
+Major numbers:
+ 104 cciss0
+ 105 cciss1
+ 106 cciss2
+ 105 cciss3
+ 108 cciss4
+ 109 cciss5
+ 110 cciss6
+ 111 cciss7
+
+Minor numbers:
+ b7 b6 b5 b4 b3 b2 b1 b0
+ |----+----| |----+----|
+ | |
+ | +-------- Partition ID (0=wholedev, 1-15 partition)
+ |
+ +-------------------- Logical Volume number
+
+The device naming scheme is:
+/dev/cciss/c0d0 Controller 0, disk 0, whole device
+/dev/cciss/c0d0p1 Controller 0, disk 0, partition 1
+/dev/cciss/c0d0p2 Controller 0, disk 0, partition 2
+/dev/cciss/c0d0p3 Controller 0, disk 0, partition 3
+
+/dev/cciss/c1d1 Controller 1, disk 1, whole device
+/dev/cciss/c1d1p1 Controller 1, disk 1, partition 1
+/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2
+/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3
+
+SCSI tape drive and medium changer support
+------------------------------------------
+
+SCSI sequential access devices and medium changer devices are supported and
+appropriate device nodes are automatically created. (e.g.
+/dev/st0, /dev/st1, etc. See the "st" man page for more details.)
+You must enable "SCSI tape drive support for Smart Array 5xxx" and
+"SCSI support" in your kernel configuration to be able to use SCSI
+tape drives with your Smart Array 5xxx controller.
+
+Additionally, note that the driver will not engage the SCSI core at init
+time. The driver must be directed to dynamically engage the SCSI core via
+the /proc filesystem entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime. This is because at driver init time,
+the SCSI core may not yet be initialized (because the driver is a block
+driver) and attempting to register it with the SCSI core in such a case
+would cause a hang. This is best done via an initialization script
+(typically in /etc/init.d, but could vary depending on distribution).
+For example:
+
+ for x in /proc/driver/cciss/cciss[0-9]*
+ do
+ echo "engage scsi" > $x
+ done
+
+Once the SCSI core is engaged by the driver, it cannot be disengaged
+(except by unloading the driver, if it happens to be linked as a module.)
+
+Note also that if no sequential access devices or medium changers are
+detected, the SCSI core will not be engaged by the action of the above
+script.
+
+Hot plug support for SCSI tape drives
+-------------------------------------
+
+Hot plugging of SCSI tape drives is supported, with some caveats.
+The cciss driver must be informed that changes to the SCSI bus
+have been made. This may be done via the /proc filesystem.
+For example:
+
+ echo "rescan" > /proc/scsi/cciss0/1
+
+This causes the driver to query the adapter about changes to the
+physical SCSI buses and/or fibre channel arbitrated loop and the
+driver to make note of any new or removed sequential access devices
+or medium changers. The driver will output messages indicating what
+devices have been added or removed and the controller, bus, target and
+lun used to address the device. It then notifies the SCSI mid layer
+of these changes.
+
+Note that the naming convention of the /proc filesystem entries
+contains a number in addition to the driver name. (E.g. "cciss0"
+instead of just "cciss" which you might expect.)
+
+Note: ONLY sequential access devices and medium changers are presented
+as SCSI devices to the SCSI mid layer by the cciss driver. Specifically,
+physical SCSI disk drives are NOT presented to the SCSI mid layer. The
+physical SCSI disk drives are controlled directly by the array controller
+hardware and it is important to prevent the kernel from attempting to directly
+access these devices too, as if the array controller were merely a SCSI
+controller in the same way that we are allowing it to access SCSI tape drives.
+
+SCSI error handling for tape drives and medium changers
+-------------------------------------------------------
+
+The linux SCSI mid layer provides an error handling protocol which
+kicks into gear whenever a SCSI command fails to complete within a
+certain amount of time (which can vary depending on the command).
+The cciss driver participates in this protocol to some extent. The
+normal protocol is a four step process. First the device is told
+to abort the command. If that doesn't work, the device is reset.
+If that doesn't work, the SCSI bus is reset. If that doesn't work
+the host bus adapter is reset. Because the cciss driver is a block
+driver as well as a SCSI driver and only the tape drives and medium
+changers are presented to the SCSI mid layer, and unlike more
+straightforward SCSI drivers, disk i/o continues through the block
+side during the SCSI error recovery process, the cciss driver only
+implements the first two of these actions, aborting the command, and
+resetting the device. Additionally, most tape drives will not oblige
+in aborting commands, and sometimes it appears they will not even
+obey a reset command, though in most circumstances they will. In
+the case that the command cannot be aborted and the device cannot be
+reset, the device will be set offline.
+
+In the event the error handling code is triggered and a tape drive is
+successfully reset or the tardy command is successfully aborted, the
+tape drive may still not allow i/o to continue until some command
+is issued which positions the tape to a known position. Typically you
+must rewind the tape (by issuing "mt -f /dev/st0 rewind" for example)
+before i/o can proceed again to a tape drive which was reset.
+
--- /dev/null
+This driver is for Compaq's SMART2 Intelligent Disk Array Controllers.
+
+Supported Cards:
+----------------
+
+This driver is known to work with the following cards:
+
+ * SMART (EISA)
+ * SMART-2/E (EISA)
+ * SMART-2/P
+ * SMART-2DH
+ * SMART-2SL
+ * SMART-221
+ * SMART-3100ES
+ * SMART-3200
+ * Integrated Smart Array Controller
+ * SA 4200
+ * SA 4250ES
+ * SA 431
+ * RAID LC2 Controller
+
+It should also work with some really old Disk array adapters, but I am
+unable to test against these cards:
+
+ * IDA
+ * IDA-2
+ * IAES
+
+
+EISA Controllers:
+-----------------
+
+If you want to use an EISA controller you'll have to supply some
+modprobe/lilo parameters. If the driver is compiled into the kernel, must
+give it the controller's IO port address at boot time (it is not
+necessary to specify the IRQ). For example, if you had two SMART-2/E
+controllers, in EISA slots 1 and 2 you'd give it a boot argument like
+this:
+
+ smart2=0x1000,0x2000
+
+If you were loading the driver as a module, you'd give load it like this:
+
+ modprobe cpqarray eisa=0x1000,0x2000
+
+You can use EISA and PCI adapters at the same time.
+
+
+Device Naming:
+--------------
+
+You need some entries in /dev for the ida device. MAKEDEV in the /dev
+directory can make device nodes for you automatically. The device setup is
+as follows:
+
+Major numbers:
+ 72 ida0
+ 73 ida1
+ 74 ida2
+ 75 ida3
+ 76 ida4
+ 77 ida5
+ 78 ida6
+ 79 ida7
+
+Minor numbers:
+ b7 b6 b5 b4 b3 b2 b1 b0
+ |----+----| |----+----|
+ | |
+ | +-------- Partition ID (0=wholedev, 1-15 partition)
+ |
+ +-------------------- Logical Volume number
+
+The device naming scheme is:
+/dev/ida/c0d0 Controller 0, disk 0, whole device
+/dev/ida/c0d0p1 Controller 0, disk 0, partition 1
+/dev/ida/c0d0p2 Controller 0, disk 0, partition 2
+/dev/ida/c0d0p3 Controller 0, disk 0, partition 3
+
+/dev/ida/c1d1 Controller 1, disk 1, whole device
+/dev/ida/c1d1p1 Controller 1, disk 1, partition 1
+/dev/ida/c1d1p2 Controller 1, disk 1, partition 2
+/dev/ida/c1d1p3 Controller 1, disk 1, partition 3
+
+
+Changelog:
+==========
+
+10-28-2004 : General cleanup, syntax fixes for in-kernel driver version.
+ James Nelson <james4765@gmail.com>
+
+
+1999 : Original Document
--- /dev/null
+This file describes the floppy driver.
+
+FAQ list:
+=========
+
+ A FAQ list may be found in the fdutils package (see below), and also
+at <http://fdutils.linux.lu/faq.html>.
+
+
+LILO configuration options (Thinkpad users, read this)
+======================================================
+
+ The floppy driver is configured using the 'floppy=' option in
+lilo. This option can be typed at the boot prompt, or entered in the
+lilo configuration file.
+
+ Example: If your kernel is called linux-2.6.9, type the following line
+at the lilo boot prompt (if you have a thinkpad):
+
+ linux-2.6.9 floppy=thinkpad
+
+You may also enter the following line in /etc/lilo.conf, in the description
+of linux-2.6.9:
+
+ append = "floppy=thinkpad"
+
+ Several floppy related options may be given, example:
+
+ linux-2.6.9 floppy=daring floppy=two_fdc
+ append = "floppy=daring floppy=two_fdc"
+
+ If you give options both in the lilo config file and on the boot
+prompt, the option strings of both places are concatenated, the boot
+prompt options coming last. That's why there are also options to
+restore the default behavior.
+
+
+Module configuration options
+============================
+
+ If you use the floppy driver as a module, use the following syntax:
+modprobe floppy <options>
+
+Example:
+ modprobe floppy omnibook messages
+
+ If you need certain options enabled every time you load the floppy driver,
+you can put:
+
+ options floppy omnibook messages
+
+in /etc/modprobe.conf.
+
+
+ The floppy driver related options are:
+
+ floppy=asus_pci
+ Sets the bit mask to allow only units 0 and 1. (default)
+
+ floppy=daring
+ Tells the floppy driver that you have a well behaved floppy controller.
+ This allows more efficient and smoother operation, but may fail on
+ certain controllers. This may speed up certain operations.
+
+ floppy=0,daring
+ Tells the floppy driver that your floppy controller should be used
+ with caution.
+
+ floppy=one_fdc
+ Tells the floppy driver that you have only one floppy controller.
+ (default)
+
+ floppy=two_fdc
+ floppy=<address>,two_fdc
+ Tells the floppy driver that you have two floppy controllers.
+ The second floppy controller is assumed to be at <address>.
+ This option is not needed if the second controller is at address
+ 0x370, and if you use the 'cmos' option.
+
+ floppy=thinkpad
+ Tells the floppy driver that you have a Thinkpad. Thinkpads use an
+ inverted convention for the disk change line.
+
+ floppy=0,thinkpad
+ Tells the floppy driver that you don't have a Thinkpad.
+
+ floppy=omnibook
+ floppy=nodma
+ Tells the floppy driver not to use Dma for data transfers.
+ This is needed on HP Omnibooks, which don't have a workable
+ DMA channel for the floppy driver. This option is also useful
+ if you frequently get "Unable to allocate DMA memory" messages.
+ Indeed, dma memory needs to be continuous in physical memory,
+ and is thus harder to find, whereas non-dma buffers may be
+ allocated in virtual memory. However, I advise against this if
+ you have an FDC without a FIFO (8272A or 82072). 82072A and
+ later are OK. You also need at least a 486 to use nodma.
+ If you use nodma mode, I suggest you also set the FIFO
+ threshold to 10 or lower, in order to limit the number of data
+ transfer interrupts.
+
+ If you have a FIFO-able FDC, the floppy driver automatically
+ falls back on non DMA mode if no DMA-able memory can be found.
+ If you want to avoid this, explicitly ask for 'yesdma'.
+
+ floppy=yesdma
+ Tells the floppy driver that a workable DMA channel is available.
+ (default)
+
+ floppy=nofifo
+ Disables the FIFO entirely. This is needed if you get "Bus
+ master arbitration error" messages from your Ethernet card (or
+ from other devices) while accessing the floppy.
+
+ floppy=usefifo
+ Enables the FIFO. (default)
+
+ floppy=<threshold>,fifo_depth
+ Sets the FIFO threshold. This is mostly relevant in DMA
+ mode. If this is higher, the floppy driver tolerates more
+ interrupt latency, but it triggers more interrupts (i.e. it
+ imposes more load on the rest of the system). If this is
+ lower, the interrupt latency should be lower too (faster
+ processor). The benefit of a lower threshold is less
+ interrupts.
+
+ To tune the fifo threshold, switch on over/underrun messages
+ using 'floppycontrol --messages'. Then access a floppy
+ disk. If you get a huge amount of "Over/Underrun - retrying"
+ messages, then the fifo threshold is too low. Try with a
+ higher value, until you only get an occasional Over/Underrun.
+ It is a good idea to compile the floppy driver as a module
+ when doing this tuning. Indeed, it allows to try different
+ fifo values without rebooting the machine for each test. Note
+ that you need to do 'floppycontrol --messages' every time you
+ re-insert the module.
+
+ Usually, tuning the fifo threshold should not be needed, as
+ the default (0xa) is reasonable.
+
+ floppy=<drive>,<type>,cmos
+ Sets the CMOS type of <drive> to <type>. This is mandatory if
+ you have more than two floppy drives (only two can be
+ described in the physical CMOS), or if your BIOS uses
+ non-standard CMOS types. The CMOS types are:
+
+ 0 - Use the value of the physical CMOS
+ 1 - 5 1/4 DD
+ 2 - 5 1/4 HD
+ 3 - 3 1/2 DD
+ 4 - 3 1/2 HD
+ 5 - 3 1/2 ED
+ 6 - 3 1/2 ED
+ 16 - unknown or not installed
+
+ (Note: there are two valid types for ED drives. This is because 5 was
+ initially chosen to represent floppy *tapes*, and 6 for ED drives.
+ AMI ignored this, and used 5 for ED drives. That's why the floppy
+ driver handles both.)
+
+ floppy=unexpected_interrupts
+ Print a warning message when an unexpected interrupt is received.
+ (default)
+
+ floppy=no_unexpected_interrupts
+ floppy=L40SX
+ Don't print a message when an unexpected interrupt is received. This
+ is needed on IBM L40SX laptops in certain video modes. (There seems
+ to be an interaction between video and floppy. The unexpected
+ interrupts affect only performance, and can be safely ignored.)
+
+ floppy=broken_dcl
+ Don't use the disk change line, but assume that the disk was
+ changed whenever the device node is reopened. Needed on some
+ boxes where the disk change line is broken or unsupported.
+ This should be regarded as a stopgap measure, indeed it makes
+ floppy operation less efficient due to unneeded cache
+ flushings, and slightly more unreliable. Please verify your
+ cable, connection and jumper settings if you have any DCL
+ problems. However, some older drives, and also some laptops
+ are known not to have a DCL.
+
+ floppy=debug
+ Print debugging messages.
+
+ floppy=messages
+ Print informational messages for some operations (disk change
+ notifications, warnings about over and underruns, and about
+ autodetection).
+
+ floppy=silent_dcl_clear
+ Uses a less noisy way to clear the disk change line (which
+ doesn't involve seeks). Implied by 'daring' option.
+
+ floppy=<nr>,irq
+ Sets the floppy IRQ to <nr> instead of 6.
+
+ floppy=<nr>,dma
+ Sets the floppy DMA channel to <nr> instead of 2.
+
+ floppy=slow
+ Use PS/2 stepping rate:
+ " PS/2 floppies have much slower step rates than regular floppies.
+ It's been recommended that take about 1/4 of the default speed
+ in some more extreme cases."
+
+
+Supporting utilities and additional documentation:
+==================================================
+
+ Additional parameters of the floppy driver can be configured at
+runtime. Utilities which do this can be found in the fdutils package.
+This package also contains a new version of mtools which allows to
+access high capacity disks (up to 1992K on a high density 3 1/2 disk!).
+It also contains additional documentation about the floppy driver.
+
+The latest version can be found at fdutils homepage:
+ http://fdutils.linux.lu
+
+The fdutils releases can be found at:
+ http://fdutils.linux.lu/download.html
+ http://www.tux.org/pub/knaff/fdutils/
+ ftp://metalab.unc.edu/pub/Linux/utils/disk-management/
+
+Reporting problems about the floppy driver
+==========================================
+
+ If you have a question or a bug report about the floppy driver, mail
+me at Alain.Knaff@poboxes.com . If you post to Usenet, preferably use
+comp.os.linux.hardware. As the volume in these groups is rather high,
+be sure to include the word "floppy" (or "FLOPPY") in the subject
+line. If the reported problem happens when mounting floppy disks, be
+sure to mention also the type of the filesystem in the subject line.
+
+ Be sure to read the FAQ before mailing/posting any bug reports!
+
+ Alain
+
+Changelog
+=========
+
+10-30-2004 : Cleanup, updating, add reference to module configuration.
+ James Nelson <james4765@gmail.com>
+
+6-3-2000 : Original Document
--- /dev/null
+ Network Block Device (TCP version)
+
+ What is it: With this compiled in the kernel (or as a module), Linux
+ can use a remote server as one of its block devices. So every time
+ the client computer wants to read, e.g., /dev/nb0, it sends a
+ request over TCP to the server, which will reply with the data read.
+ This can be used for stations with low disk space (or even diskless -
+ if you boot from floppy) to borrow disk space from another computer.
+ Unlike NFS, it is possible to put any filesystem on it, etc. It should
+ even be possible to use NBD as a root filesystem (I've never tried),
+ but it requires a user-level program to be in the initrd to start.
+ It also allows you to run block-device in user land (making server
+ and client physically the same computer, communicating using loopback).
+
+ Current state: It currently works. Network block device is stable.
+ I originally thought that it was impossible to swap over TCP. It
+ turned out not to be true - swapping over TCP now works and seems
+ to be deadlock-free, but it requires heavy patches into Linux's
+ network layer.
+
+ For more information, or to download the nbd-client and nbd-server
+ tools, go to http://nbd.sf.net/.
+
+ Howto: To setup nbd, you can simply do the following:
+
+ First, serve a device or file from a remote server:
+
+ nbd-server <port-number> <device-or-file-to-serve-to-client>
+
+ e.g.,
+ root@server1 # nbd-server 1234 /dev/sdb1
+
+ (serves sdb1 partition on TCP port 1234)
+
+ Then, on the local (client) system:
+
+ nbd-client <server-name-or-IP> <server-port-number> /dev/nb[0-n]
+
+ e.g.,
+ root@client1 # nbd-client server1 1234 /dev/nb0
+
+ (creates the nb0 device on client1)
+
+ The nbd kernel module need only be installed on the client
+ system, as the nbd-server is completely in userspace. In fact,
+ the nbd-server has been successfully ported to other operating
+ systems, including Windows.
--- /dev/null
+
+ Linux and parallel port IDE devices
+
+PARIDE v1.03 (c) 1997-8 Grant Guenther <grant@torque.net>
+
+1. Introduction
+
+Owing to the simplicity and near universality of the parallel port interface
+to personal computers, many external devices such as portable hard-disk,
+CD-ROM, LS-120 and tape drives use the parallel port to connect to their
+host computer. While some devices (notably scanners) use ad-hoc methods
+to pass commands and data through the parallel port interface, most
+external devices are actually identical to an internal model, but with
+a parallel-port adapter chip added in. Some of the original parallel port
+adapters were little more than mechanisms for multiplexing a SCSI bus.
+(The Iomega PPA-3 adapter used in the ZIP drives is an example of this
+approach). Most current designs, however, take a different approach.
+The adapter chip reproduces a small ISA or IDE bus in the external device
+and the communication protocol provides operations for reading and writing
+device registers, as well as data block transfer functions. Sometimes,
+the device being addressed via the parallel cable is a standard SCSI
+controller like an NCR 5380. The "ditto" family of external tape
+drives use the ISA replicator to interface a floppy disk controller,
+which is then connected to a floppy-tape mechanism. The vast majority
+of external parallel port devices, however, are now based on standard
+IDE type devices, which require no intermediate controller. If one
+were to open up a parallel port CD-ROM drive, for instance, one would
+find a standard ATAPI CD-ROM drive, a power supply, and a single adapter
+that interconnected a standard PC parallel port cable and a standard
+IDE cable. It is usually possible to exchange the CD-ROM device with
+any other device using the IDE interface.
+
+The document describes the support in Linux for parallel port IDE
+devices. It does not cover parallel port SCSI devices, "ditto" tape
+drives or scanners. Many different devices are supported by the
+parallel port IDE subsystem, including:
+
+ MicroSolutions backpack CD-ROM
+ MicroSolutions backpack PD/CD
+ MicroSolutions backpack hard-drives
+ MicroSolutions backpack 8000t tape drive
+ SyQuest EZ-135, EZ-230 & SparQ drives
+ Avatar Shark
+ Imation Superdisk LS-120
+ Maxell Superdisk LS-120
+ FreeCom Power CD
+ Hewlett-Packard 5GB and 8GB tape drives
+ Hewlett-Packard 7100 and 7200 CD-RW drives
+
+as well as most of the clone and no-name products on the market.
+
+To support such a wide range of devices, PARIDE, the parallel port IDE
+subsystem, is actually structured in three parts. There is a base
+paride module which provides a registry and some common methods for
+accessing the parallel ports. The second component is a set of
+high-level drivers for each of the different types of supported devices:
+
+ pd IDE disk
+ pcd ATAPI CD-ROM
+ pf ATAPI disk
+ pt ATAPI tape
+ pg ATAPI generic
+
+(Currently, the pg driver is only used with CD-R drives).
+
+The high-level drivers function according to the relevant standards.
+The third component of PARIDE is a set of low-level protocol drivers
+for each of the parallel port IDE adapter chips. Thanks to the interest
+and encouragement of Linux users from many parts of the world,
+support is available for almost all known adapter protocols:
+
+ aten ATEN EH-100 (HK)
+ bpck Microsolutions backpack (US)
+ comm DataStor (old-type) "commuter" adapter (TW)
+ dstr DataStor EP-2000 (TW)
+ epat Shuttle EPAT (UK)
+ epia Shuttle EPIA (UK)
+ fit2 FIT TD-2000 (US)
+ fit3 FIT TD-3000 (US)
+ friq Freecom IQ cable (DE)
+ frpw Freecom Power (DE)
+ kbic KingByte KBIC-951A and KBIC-971A (TW)
+ ktti KT Technology PHd adapter (SG)
+ on20 OnSpec 90c20 (US)
+ on26 OnSpec 90c26 (US)
+
+
+2. Using the PARIDE subsystem
+
+While configuring the Linux kernel, you may choose either to build
+the PARIDE drivers into your kernel, or to build them as modules.
+
+In either case, you will need to select "Parallel port IDE device support"
+as well as at least one of the high-level drivers and at least one
+of the parallel port communication protocols. If you do not know
+what kind of parallel port adapter is used in your drive, you could
+begin by checking the file names and any text files on your DOS
+installation floppy. Alternatively, you can look at the markings on
+the adapter chip itself. That's usually sufficient to identify the
+correct device.
+
+You can actually select all the protocol modules, and allow the PARIDE
+subsystem to try them all for you.
+
+For the "brand-name" products listed above, here are the protocol
+and high-level drivers that you would use:
+
+ Manufacturer Model Driver Protocol
+
+ MicroSolutions CD-ROM pcd bpck
+ MicroSolutions PD drive pf bpck
+ MicroSolutions hard-drive pd bpck
+ MicroSolutions 8000t tape pt bpck
+ SyQuest EZ, SparQ pd epat
+ Imation Superdisk pf epat
+ Maxell Superdisk pf friq
+ Avatar Shark pd epat
+ FreeCom CD-ROM pcd frpw
+ Hewlett-Packard 5GB Tape pt epat
+ Hewlett-Packard 7200e (CD) pcd epat
+ Hewlett-Packard 7200e (CD-R) pg epat
+
+2.1 Configuring built-in drivers
+
+We recommend that you get to know how the drivers work and how to
+configure them as loadable modules, before attempting to compile a
+kernel with the drivers built-in.
+
+If you built all of your PARIDE support directly into your kernel,
+and you have just a single parallel port IDE device, your kernel should
+locate it automatically for you. If you have more than one device,
+you may need to give some command line options to your bootloader
+(eg: LILO), how to do that is beyond the scope of this document.
+
+The high-level drivers accept a number of command line parameters, all
+of which are documented in the source files in linux/drivers/block/paride.
+By default, each driver will automatically try all parallel ports it
+can find, and all protocol types that have been installed, until it finds
+a parallel port IDE adapter. Once it finds one, the probe stops. So,
+if you have more than one device, you will need to tell the drivers
+how to identify them. This requires specifying the port address, the
+protocol identification number and, for some devices, the drive's
+chain ID. While your system is booting, a number of messages are
+displayed on the console. Like all such messages, they can be
+reviewed with the 'dmesg' command. Among those messages will be
+some lines like:
+
+ paride: bpck registered as protocol 0
+ paride: epat registered as protocol 1
+
+The numbers will always be the same until you build a new kernel with
+different protocol selections. You should note these numbers as you
+will need them to identify the devices.
+
+If you happen to be using a MicroSolutions backpack device, you will
+also need to know the unit ID number for each drive. This is usually
+the last two digits of the drive's serial number (but read MicroSolutions'
+documentation about this).
+
+As an example, let's assume that you have a MicroSolutions PD/CD drive
+with unit ID number 36 connected to the parallel port at 0x378, a SyQuest
+EZ-135 connected to the chained port on the PD/CD drive and also an
+Imation Superdisk connected to port 0x278. You could give the following
+options on your boot command:
+
+ pd.drive0=0x378,1 pf.drive0=0x278,1 pf.drive1=0x378,0,36
+
+In the last option, pf.drive1 configures device /dev/pf1, the 0x378
+is the parallel port base address, the 0 is the protocol registration
+number and 36 is the chain ID.
+
+Please note: while PARIDE will work both with and without the
+PARPORT parallel port sharing system that is included by the
+"Parallel port support" option, PARPORT must be included and enabled
+if you want to use chains of devices on the same parallel port.
+
+2.2 Loading and configuring PARIDE as modules
+
+It is much faster and simpler to get to understand the PARIDE drivers
+if you use them as loadable kernel modules.
+
+Note 1: using these drivers with the "kerneld" automatic module loading
+system is not recommended for beginners, and is not documented here.
+
+Note 2: if you build PARPORT support as a loadable module, PARIDE must
+also be built as loadable modules, and PARPORT must be loaded before the
+PARIDE modules.
+
+To use PARIDE, you must begin by
+
+ insmod paride
+
+this loads a base module which provides a registry for the protocols,
+among other tasks.
+
+Then, load as many of the protocol modules as you think you might need.
+As you load each module, it will register the protocols that it supports,
+and print a log message to your kernel log file and your console. For
+example:
+
+ # insmod epat
+ paride: epat registered as protocol 0
+ # insmod kbic
+ paride: k951 registered as protocol 1
+ paride: k971 registered as protocol 2
+
+Finally, you can load high-level drivers for each kind of device that
+you have connected. By default, each driver will autoprobe for a single
+device, but you can support up to four similar devices by giving their
+individual co-ordinates when you load the driver.
+
+For example, if you had two no-name CD-ROM drives both using the
+KingByte KBIC-951A adapter, one on port 0x378 and the other on 0x3bc
+you could give the following command:
+
+ # insmod pcd drive0=0x378,1 drive1=0x3bc,1
+
+For most adapters, giving a port address and protocol number is sufficient,
+but check the source files in linux/drivers/block/paride for more
+information. (Hopefully someone will write some man pages one day !).
+
+As another example, here's what happens when PARPORT is installed, and
+a SyQuest EZ-135 is attached to port 0x378:
+
+ # insmod paride
+ paride: version 1.0 installed
+ # insmod epat
+ paride: epat registered as protocol 0
+ # insmod pd
+ pd: pd version 1.0, major 45, cluster 64, nice 0
+ pda: Sharing parport1 at 0x378
+ pda: epat 1.0, Shuttle EPAT chip c3 at 0x378, mode 5 (EPP-32), delay 1
+ pda: SyQuest EZ135A, 262144 blocks [128M], (512/16/32), removable media
+ pda: pda1
+
+Note that the last line is the output from the generic partition table
+scanner - in this case it reports that it has found a disk with one partition.
+
+2.3 Using a PARIDE device
+
+Once the drivers have been loaded, you can access PARIDE devices in the
+same way as their traditional counterparts. You will probably need to
+create the device "special files". Here is a simple script that you can
+cut to a file and execute:
+
+#!/bin/bash
+#
+# mkd -- a script to create the device special files for the PARIDE subsystem
+#
+function mkdev {
+ mknod $1 $2 $3 $4 ; chmod 0660 $1 ; chown root:disk $1
+}
+#
+function pd {
+ D=$( printf \\$( printf "x%03x" $[ $1 + 97 ] ) )
+ mkdev pd$D b 45 $[ $1 * 16 ]
+ for P in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do mkdev pd$D$P b 45 $[ $1 * 16 + $P ]
+ done
+}
+#
+cd /dev
+#
+for u in 0 1 2 3 ; do pd $u ; done
+for u in 0 1 2 3 ; do mkdev pcd$u b 46 $u ; done
+for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done
+for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done
+for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done
+for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done
+#
+# end of mkd
+
+With the device files and drivers in place, you can access PARIDE devices
+like any other Linux device. For example, to mount a CD-ROM in pcd0, use:
+
+ mount /dev/pcd0 /cdrom
+
+If you have a fresh Avatar Shark cartridge, and the drive is pda, you
+might do something like:
+
+ fdisk /dev/pda -- make a new partition table with
+ partition 1 of type 83
+
+ mke2fs /dev/pda1 -- to build the file system
+
+ mkdir /shark -- make a place to mount the disk
+
+ mount /dev/pda1 /shark
+
+Devices like the Imation superdisk work in the same way, except that
+they do not have a partition table. For example to make a 120MB
+floppy that you could share with a DOS system:
+
+ mkdosfs /dev/pf0
+ mount /dev/pf0 /mnt
+
+
+2.4 The pf driver
+
+The pf driver is intended for use with parallel port ATAPI disk
+devices. The most common devices in this category are PD drives
+and LS-120 drives. Traditionally, media for these devices are not
+partitioned. Consequently, the pf driver does not support partitioned
+media. This may be changed in a future version of the driver.
+
+2.5 Using the pt driver
+
+The pt driver for parallel port ATAPI tape drives is a minimal driver.
+It does not yet support many of the standard tape ioctl operations.
+For best performance, a block size of 32KB should be used. You will
+probably want to set the parallel port delay to 0, if you can.
+
+2.6 Using the pg driver
+
+The pg driver can be used in conjunction with the cdrecord program
+to create CD-ROMs. Please get cdrecord version 1.6.1 or later
+from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . To record CD-R media
+your parallel port should ideally be set to EPP mode, and the "port delay"
+should be set to 0. With those settings it is possible to record at 2x
+speed without any buffer underruns. If you cannot get the driver to work
+in EPP mode, try to use "bidirectional" or "PS/2" mode and 1x speeds only.
+
+
+3. Troubleshooting
+
+3.1 Use EPP mode if you can
+
+The most common problems that people report with the PARIDE drivers
+concern the parallel port CMOS settings. At this time, none of the
+PARIDE protocol modules support ECP mode, or any ECP combination modes.
+If you are able to do so, please set your parallel port into EPP mode
+using your CMOS setup procedure.
+
+3.2 Check the port delay
+
+Some parallel ports cannot reliably transfer data at full speed. To
+offset the errors, the PARIDE protocol modules introduce a "port
+delay" between each access to the i/o ports. Each protocol sets
+a default value for this delay. In most cases, the user can override
+the default and set it to 0 - resulting in somewhat higher transfer
+rates. In some rare cases (especially with older 486 systems) the
+default delays are not long enough. if you experience corrupt data
+transfers, or unexpected failures, you may wish to increase the
+port delay. The delay can be programmed using the "driveN" parameters
+to each of the high-level drivers. Please see the notes above, or
+read the comments at the beginning of the driver source files in
+linux/drivers/block/paride.
+
+3.3 Some drives need a printer reset
+
+There appear to be a number of "noname" external drives on the market
+that do not always power up correctly. We have noticed this with some
+drives based on OnSpec and older Freecom adapters. In these rare cases,
+the adapter can often be reinitialised by issuing a "printer reset" on
+the parallel port. As the reset operation is potentially disruptive in
+multiple device environments, the PARIDE drivers will not do it
+automatically. You can however, force a printer reset by doing:
+
+ insmod lp reset=1
+ rmmod lp
+
+If you have one of these marginal cases, you should probably build
+your paride drivers as modules, and arrange to do the printer reset
+before loading the PARIDE drivers.
+
+3.4 Use the verbose option and dmesg if you need help
+
+While a lot of testing has gone into these drivers to make them work
+as smoothly as possible, problems will arise. If you do have problems,
+please check all the obvious things first: does the drive work in
+DOS with the manufacturer's drivers ? If that doesn't yield any useful
+clues, then please make sure that only one drive is hooked to your system,
+and that either (a) PARPORT is enabled or (b) no other device driver
+is using your parallel port (check in /proc/ioports). Then, load the
+appropriate drivers (you can load several protocol modules if you want)
+as in:
+
+ # insmod paride
+ # insmod epat
+ # insmod bpck
+ # insmod kbic
+ ...
+ # insmod pd verbose=1
+
+(using the correct driver for the type of device you have, of course).
+The verbose=1 parameter will cause the drivers to log a trace of their
+activity as they attempt to locate your drive.
+
+Use 'dmesg' to capture a log of all the PARIDE messages (any messages
+beginning with paride:, a protocol module's name or a driver's name) and
+include that with your bug report. You can submit a bug report in one
+of two ways. Either send it directly to the author of the PARIDE suite,
+by e-mail to grant@torque.net, or join the linux-parport mailing list
+and post your report there.
+
+3.5 For more information or help
+
+You can join the linux-parport mailing list by sending a mail message
+to
+ linux-parport-request@torque.net
+
+with the single word
+
+ subscribe
+
+in the body of the mail message (not in the subject line). Please be
+sure that your mail program is correctly set up when you do this, as
+the list manager is a robot that will subscribe you using the reply
+address in your mail headers. REMOVE any anti-spam gimmicks you may
+have in your mail headers, when sending mail to the list server.
+
+You might also find some useful information on the linux-parport
+web pages (although they are not always up to date) at
+
+ http://www.torque.net/parport/
+
+
--- /dev/null
+Using the RAM disk block device with Linux
+------------------------------------------
+
+Contents:
+
+ 1) Overview
+ 2) Kernel Command Line Parameters
+ 3) Using "rdev -r"
+ 4) An Example of Creating a Compressed RAM Disk
+
+
+1) Overview
+-----------
+
+The RAM disk driver is a way to use main system memory as a block device. It
+is required for initrd, an initial filesystem used if you need to load modules
+in order to access the root filesystem (see Documentation/initrd.txt). It can
+also be used for a temporary filesystem for crypto work, since the contents
+are erased on reboot.
+
+The RAM disk dynamically grows as more space is required. It does this by using
+RAM from the buffer cache. The driver marks the buffers it is using as dirty
+so that the VM subsystem does not try to reclaim them later.
+
+The RAM disk supports up to 16 RAM disks by default, and can be reconfigured
+to support an unlimited number of RAM disks (at your own risk). Just change
+the configuration symbol BLK_DEV_RAM_COUNT in the Block drivers config menu
+and (re)build the kernel.
+
+To use RAM disk support with your system, run './MAKEDEV ram' from the /dev
+directory. RAM disks are all major number 1, and start with minor number 0
+for /dev/ram0, etc. If used, modern kernels use /dev/ram0 for an initrd.
+
+The new RAM disk also has the ability to load compressed RAM disk images,
+allowing one to squeeze more programs onto an average installation or
+rescue floppy disk.
+
+
+2) Kernel Command Line Parameters
+---------------------------------
+
+ ramdisk_size=N
+ ==============
+
+This parameter tells the RAM disk driver to set up RAM disks of N k size. The
+default is 4096 (4 MB) (8192 (8 MB) on S390).
+
+ ramdisk_blocksize=N
+ ===================
+
+This parameter tells the RAM disk driver how many bytes to use per block. The
+default is 1024 (BLOCK_SIZE).
+
+
+3) Using "rdev -r"
+------------------
+
+The usage of the word (two bytes) that "rdev -r" sets in the kernel image is
+as follows. The low 11 bits (0 -> 10) specify an offset (in 1 k blocks) of up
+to 2 MB (2^11) of where to find the RAM disk (this used to be the size). Bit
+14 indicates that a RAM disk is to be loaded, and bit 15 indicates whether a
+prompt/wait sequence is to be given before trying to read the RAM disk. Since
+the RAM disk dynamically grows as data is being written into it, a size field
+is not required. Bits 11 to 13 are not currently used and may as well be zero.
+These numbers are no magical secrets, as seen below:
+
+./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK 0x07FF
+./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000
+./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000
+
+Consider a typical two floppy disk setup, where you will have the
+kernel on disk one, and have already put a RAM disk image onto disk #2.
+
+Hence you want to set bits 0 to 13 as 0, meaning that your RAM disk
+starts at an offset of 0 kB from the beginning of the floppy.
+The command line equivalent is: "ramdisk_start=0"
+
+You want bit 14 as one, indicating that a RAM disk is to be loaded.
+The command line equivalent is: "load_ramdisk=1"
+
+You want bit 15 as one, indicating that you want a prompt/keypress
+sequence so that you have a chance to switch floppy disks.
+The command line equivalent is: "prompt_ramdisk=1"
+
+Putting that together gives 2^15 + 2^14 + 0 = 49152 for an rdev word.
+So to create disk one of the set, you would do:
+
+ /usr/src/linux# cat arch/i386/boot/zImage > /dev/fd0
+ /usr/src/linux# rdev /dev/fd0 /dev/fd0
+ /usr/src/linux# rdev -r /dev/fd0 49152
+
+If you make a boot disk that has LILO, then for the above, you would use:
+ append = "ramdisk_start=0 load_ramdisk=1 prompt_ramdisk=1"
+Since the default start = 0 and the default prompt = 1, you could use:
+ append = "load_ramdisk=1"
+
+
+4) An Example of Creating a Compressed RAM Disk
+----------------------------------------------
+
+To create a RAM disk image, you will need a spare block device to
+construct it on. This can be the RAM disk device itself, or an
+unused disk partition (such as an unmounted swap partition). For this
+example, we will use the RAM disk device, "/dev/ram0".
+
+Note: This technique should not be done on a machine with less than 8 MB
+of RAM. If using a spare disk partition instead of /dev/ram0, then this
+restriction does not apply.
+
+a) Decide on the RAM disk size that you want. Say 2 MB for this example.
+ Create it by writing to the RAM disk device. (This step is not currently
+ required, but may be in the future.) It is wise to zero out the
+ area (esp. for disks) so that maximal compression is achieved for
+ the unused blocks of the image that you are about to create.
+
+ dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
+
+b) Make a filesystem on it. Say ext2fs for this example.
+
+ mke2fs -vm0 /dev/ram0 2048
+
+c) Mount it, copy the files you want to it (eg: /etc/* /dev/* ...)
+ and unmount it again.
+
+d) Compress the contents of the RAM disk. The level of compression
+ will be approximately 50% of the space used by the files. Unused
+ space on the RAM disk will compress to almost nothing.
+
+ dd if=/dev/ram0 bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz
+
+e) Put the kernel onto the floppy
+
+ dd if=zImage of=/dev/fd0 bs=1k
+
+f) Put the RAM disk image onto the floppy, after the kernel. Use an offset
+ that is slightly larger than the kernel, so that you can put another
+ (possibly larger) kernel onto the same floppy later without overlapping
+ the RAM disk image. An offset of 400 kB for kernels about 350 kB in
+ size would be reasonable. Make sure offset+size of ram_image.gz is
+ not larger than the total space on your floppy (usually 1440 kB).
+
+ dd if=/tmp/ram_image.gz of=/dev/fd0 bs=1k seek=400
+
+g) Use "rdev" to set the boot device, RAM disk offset, prompt flag, etc.
+ For prompt_ramdisk=1, load_ramdisk=1, ramdisk_start=400, one would
+ have 2^15 + 2^14 + 400 = 49552.
+
+ rdev /dev/fd0 /dev/fd0
+ rdev -r /dev/fd0 49552
+
+That is it. You now have your boot/root compressed RAM disk floppy. Some
+users may wish to combine steps (d) and (f) by using a pipe.
+
+--------------------------------------------------------------------------
+ Paul Gortmaker 12/95
+
+Changelog:
+----------
+
+10-22-04 : Updated to reflect changes in command line options, remove
+ obsolete references, general cleanup.
+ James Nelson (james4765@gmail.com)
+
+
+12-95 : Original Document
+++ /dev/null
-This driver is for Compaq's SMART Array Controllers.
-
-Supported Cards:
-----------------
-
-This driver is known to work with the following cards:
-
- * SA 5300
- * SA 5i
- * SA 532
- * SA 5312
- * SA 641
- * SA 642
- * SA 6400
- * SA 6400 U320 Expansion Module
- * SA 6i
- * SA P600
- * SA P800
- * SA E400
- * SA P400i
- * SA E200
- * SA E200i
- * SA E500
- * SA P700m
- * SA P212
- * SA P410
- * SA P410i
- * SA P411
- * SA P812
- * SA P712m
- * SA P711m
-
-Detecting drive failures:
--------------------------
-
-To get the status of logical volumes and to detect physical drive
-failures, you can use the cciss_vol_status program found here:
-http://cciss.sourceforge.net/#cciss_utils
-
-Device Naming:
---------------
-
-If nodes are not already created in the /dev/cciss directory, run as root:
-
-# cd /dev
-# ./MAKEDEV cciss
-
-You need some entries in /dev for the cciss device. The MAKEDEV script
-can make device nodes for you automatically. Currently the device setup
-is as follows:
-
-Major numbers:
- 104 cciss0
- 105 cciss1
- 106 cciss2
- 105 cciss3
- 108 cciss4
- 109 cciss5
- 110 cciss6
- 111 cciss7
-
-Minor numbers:
- b7 b6 b5 b4 b3 b2 b1 b0
- |----+----| |----+----|
- | |
- | +-------- Partition ID (0=wholedev, 1-15 partition)
- |
- +-------------------- Logical Volume number
-
-The device naming scheme is:
-/dev/cciss/c0d0 Controller 0, disk 0, whole device
-/dev/cciss/c0d0p1 Controller 0, disk 0, partition 1
-/dev/cciss/c0d0p2 Controller 0, disk 0, partition 2
-/dev/cciss/c0d0p3 Controller 0, disk 0, partition 3
-
-/dev/cciss/c1d1 Controller 1, disk 1, whole device
-/dev/cciss/c1d1p1 Controller 1, disk 1, partition 1
-/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2
-/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3
-
-SCSI tape drive and medium changer support
-------------------------------------------
-
-SCSI sequential access devices and medium changer devices are supported and
-appropriate device nodes are automatically created. (e.g.
-/dev/st0, /dev/st1, etc. See the "st" man page for more details.)
-You must enable "SCSI tape drive support for Smart Array 5xxx" and
-"SCSI support" in your kernel configuration to be able to use SCSI
-tape drives with your Smart Array 5xxx controller.
-
-Additionally, note that the driver will not engage the SCSI core at init
-time. The driver must be directed to dynamically engage the SCSI core via
-the /proc filesystem entry which the "block" side of the driver creates as
-/proc/driver/cciss/cciss* at runtime. This is because at driver init time,
-the SCSI core may not yet be initialized (because the driver is a block
-driver) and attempting to register it with the SCSI core in such a case
-would cause a hang. This is best done via an initialization script
-(typically in /etc/init.d, but could vary depending on distribution).
-For example:
-
- for x in /proc/driver/cciss/cciss[0-9]*
- do
- echo "engage scsi" > $x
- done
-
-Once the SCSI core is engaged by the driver, it cannot be disengaged
-(except by unloading the driver, if it happens to be linked as a module.)
-
-Note also that if no sequential access devices or medium changers are
-detected, the SCSI core will not be engaged by the action of the above
-script.
-
-Hot plug support for SCSI tape drives
--------------------------------------
-
-Hot plugging of SCSI tape drives is supported, with some caveats.
-The cciss driver must be informed that changes to the SCSI bus
-have been made. This may be done via the /proc filesystem.
-For example:
-
- echo "rescan" > /proc/scsi/cciss0/1
-
-This causes the driver to query the adapter about changes to the
-physical SCSI buses and/or fibre channel arbitrated loop and the
-driver to make note of any new or removed sequential access devices
-or medium changers. The driver will output messages indicating what
-devices have been added or removed and the controller, bus, target and
-lun used to address the device. It then notifies the SCSI mid layer
-of these changes.
-
-Note that the naming convention of the /proc filesystem entries
-contains a number in addition to the driver name. (E.g. "cciss0"
-instead of just "cciss" which you might expect.)
-
-Note: ONLY sequential access devices and medium changers are presented
-as SCSI devices to the SCSI mid layer by the cciss driver. Specifically,
-physical SCSI disk drives are NOT presented to the SCSI mid layer. The
-physical SCSI disk drives are controlled directly by the array controller
-hardware and it is important to prevent the kernel from attempting to directly
-access these devices too, as if the array controller were merely a SCSI
-controller in the same way that we are allowing it to access SCSI tape drives.
-
-SCSI error handling for tape drives and medium changers
--------------------------------------------------------
-
-The linux SCSI mid layer provides an error handling protocol which
-kicks into gear whenever a SCSI command fails to complete within a
-certain amount of time (which can vary depending on the command).
-The cciss driver participates in this protocol to some extent. The
-normal protocol is a four step process. First the device is told
-to abort the command. If that doesn't work, the device is reset.
-If that doesn't work, the SCSI bus is reset. If that doesn't work
-the host bus adapter is reset. Because the cciss driver is a block
-driver as well as a SCSI driver and only the tape drives and medium
-changers are presented to the SCSI mid layer, and unlike more
-straightforward SCSI drivers, disk i/o continues through the block
-side during the SCSI error recovery process, the cciss driver only
-implements the first two of these actions, aborting the command, and
-resetting the device. Additionally, most tape drives will not oblige
-in aborting commands, and sometimes it appears they will not even
-obey a reset command, though in most circumstances they will. In
-the case that the command cannot be aborted and the device cannot be
-reset, the device will be set offline.
-
-In the event the error handling code is triggered and a tape drive is
-successfully reset or the tardy command is successfully aborted, the
-tape drive may still not allow i/o to continue until some command
-is issued which positions the tape to a known position. Typically you
-must rewind the tape (by issuing "mt -f /dev/st0 rewind" for example)
-before i/o can proceed again to a tape drive which was reset.
-
+++ /dev/null
-NOTE: This is an unmaintained driver. It is not guaranteed to work due to
-changes made in the tty layer in 2.6. If you wish to take over maintenance of
-this driver, contact Michael Warfield <mhw@wittsend.com>.
-
-Changelog:
-----------
-11-01-2001: Original Document
-
-10-29-2004: Minor misspelling & format fix, update status of driver.
- James Nelson <james4765@gmail.com>
-
-Computone Intelliport II/Plus Multiport Serial Driver
------------------------------------------------------
-
-Release Notes For Linux Kernel 2.2 and higher.
-These notes are for the drivers which have already been integrated into the
-kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
-
-Version: 1.2.14
-Date: 11/01/2001
-Historical Author: Andrew Manison <amanison@america.net>
-Primary Author: Doug McNash
-Support: support@computone.com
-Fixes and Updates: Mike Warfield <mhw@wittsend.com>
-
-This file assumes that you are using the Computone drivers which are
-integrated into the kernel sources. For updating the drivers or installing
-drivers into kernels which do not already have Computone drivers, please
-refer to the instructions in the README.computone file in the driver patch.
-
-
-1. INTRODUCTION
-
-This driver supports the entire family of Intelliport II/Plus controllers
-with the exception of the MicroChannel controllers. It does not support
-products previous to the Intelliport II.
-
-This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.4.14; it will probably not work with earlier v1.X kernels,.
-
-
-2. QUICK INSTALLATION
-
-Hardware - If you have an ISA card, find a free interrupt and io port.
- List those in use with `cat /proc/interrupts` and
- `cat /proc/ioports`. Set the card dip switches to a free
- address. You may need to configure your BIOS to reserve an
- irq for an ISA card. PCI and EISA parameters are set
- automagically. Insert card into computer with the power off
- before or after drivers installation.
-
- Note the hardware address from the Computone ISA cards installed into
- the system. These are required for editing ip2.c or editing
- /etc/modprobe.conf, or for specification on the modprobe
- command line.
-
- Note that the /etc/modules.conf should be used for older (pre-2.6)
- kernels.
-
-Software -
-
-Module installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
- Select (m) module for CONFIG_COMPUTONE under character
- devices. CONFIG_PCI and CONFIG_MODULES also may need to be set.
-c) Set address on ISA cards then:
- edit /usr/src/linux/drivers/char/ip2.c if needed
- or
- edit /etc/modprobe.conf if needed (module).
- or both to match this setting.
-d) Run "make modules"
-e) Run "make modules_install"
-f) Run "/sbin/depmod -a"
-g) install driver using `modprobe ip2 <options>` (options listed below)
-h) run ip2mkdev (either the script below or the binary version)
-
-
-Kernel installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
- Select (y) kernel for CONFIG_COMPUTONE under character
- devices. CONFIG_PCI may need to be set if you have PCI bus.
-c) Set address on ISA cards then:
- edit /usr/src/linux/drivers/char/ip2.c
- (Optional - may be specified on kernel command line now)
-d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
-f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
- or copy to a floppy disk and boot from that floppy disk.
-g) Reboot using this kernel
-h) run ip2mkdev (either the script below or the binary version)
-
-Kernel command line options:
-
-When compiling the driver into the kernel, io and irq may be
-compiled into the driver by editing ip2.c and setting the values for
-io and irq in the appropriate array. An alternative is to specify
-a command line parameter to the kernel at boot up.
-
- ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
-
-Note that this order is very different from the specifications for the
-modload parameters which have separate IRQ and IO specifiers.
-
-The io port also selects PCI (1) and EISA (2) boards.
-
- io=0 No board
- io=1 PCI board
- io=2 EISA board
- else ISA board io address
-
-You only need to specify the boards which are present.
-
- Examples:
-
- 2 PCI boards:
-
- ip2=1,0,1,0
-
- 1 ISA board at 0x310 irq 5:
-
- ip2=0x310,5
-
-This can be added to and "append" option in lilo.conf similar to this:
-
- append="ip2=1,0,1,0"
-
-
-3. INSTALLATION
-
-Previously, the driver sources were packaged with a set of patch files
-to update the character drivers' makefile and configuration file, and other
-kernel source files. A build script (ip2build) was included which applies
-the patches if needed, and build any utilities needed.
-What you receive may be a single patch file in conventional kernel
-patch format build script. That form can also be applied by
-running patch -p1 < ThePatchFile. Otherwise run ip2build.
-
-The driver can be installed as a module (recommended) or built into the
-kernel. This is selected as for other drivers through the `make config`
-command from the root of the Linux source tree. If the driver is built
-into the kernel you will need to edit the file ip2.c to match the boards
-you are installing. See that file for instructions. If the driver is
-installed as a module the configuration can also be specified on the
-modprobe command line as follows:
-
- modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4
-
-where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11,
-12,15) and addr1-4 are the base addresses for up to four controllers. If
-the irqs are not specified the driver uses the default in ip2.c (which
-selects polled mode). If no base addresses are specified the defaults in
-ip2.c are used. If you are autoloading the driver module with kerneld or
-kmod the base addresses and interrupt number must also be set in ip2.c
-and recompile or just insert and options line in /etc/modprobe.conf or both.
-The options line is equivalent to the command line and takes precedence over
-what is in ip2.c.
-
-/etc/modprobe.conf sample:
- options ip2 io=1,0x328 irq=1,10
- alias char-major-71 ip2
- alias char-major-72 ip2
- alias char-major-73 ip2
-
-The equivalent in ip2.c:
-
-static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 };
-
-The equivalent for the kernel command line (in lilo.conf):
-
- append="ip2=1,1,0x328,10"
-
-
-Note: Both io and irq should be updated to reflect YOUR system. An "io"
- address of 1 or 2 indicates a PCI or EISA card in the board table.
- The PCI or EISA irq will be assigned automatically.
-
-Specifying an invalid or in-use irq will default the driver into
-running in polled mode for that card. If all irq entries are 0 then
-all cards will operate in polled mode.
-
-If you select the driver as part of the kernel run :
-
- make zlilo (or whatever you do to create a bootable kernel)
-
-If you selected a module run :
-
- make modules && make modules_install
-
-The utility ip2mkdev (see 5 and 7 below) creates all the device nodes
-required by the driver. For a device to be created it must be configured
-in the driver and the board must be installed. Only devices corresponding
-to real IntelliPort II ports are created. With multiple boards and expansion
-boxes this will leave gaps in the sequence of device names. ip2mkdev uses
-Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
-cuf0 - cuf255 for callout devices.
-
-
-4. USING THE DRIVERS
-
-As noted above, the driver implements the ports in accordance with Linux
-conventions, and the devices should be interchangeable with the standard
-serial devices. (This is a key point for problem reporting: please make
-sure that what you are trying do works on the ttySx/cuax ports first; then
-tell us what went wrong with the ip2 ports!)
-
-Higher speeds can be obtained using the setserial utility which remaps
-38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed.
-Intelliport II installations using the PowerPort expansion module can
-use the custom speed setting to select the highest speeds: 153,600 bps,
-230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for
-custom baud rate configuration is fixed at 921,600 for cards/expansion
-modules with ST654's and 115200 for those with Cirrus CD1400's. This
-corresponds to the maximum bit rates those chips are capable.
-For example if the baud base is 921600 and the baud divisor is 18 then
-the custom rate is 921600/18 = 51200 bps. See the setserial man page for
-complete details. Of course if stty accepts the higher rates now you can
-use that as well as the standard ioctls().
-
-
-5. ip2mkdev and assorted utilities...
-
-Several utilities, including the source for a binary ip2mkdev utility are
-available under .../drivers/char/ip2. These can be build by changing to
-that directory and typing "make" after the kernel has be built. If you do
-not wish to compile the binary utilities, the shell script below can be
-cut out and run as "ip2mkdev" to create the necessary device files. To
-use the ip2mkdev script, you must have procfs enabled and the proc file
-system mounted on /proc.
-
-
-6. NOTES
-
-This is a release version of the driver, but it is impossible to test it
-in all configurations of Linux. If there is any anomalous behaviour that
-does not match the standard serial port's behaviour please let us know.
-
-
-7. ip2mkdev shell script
-
-Previously, this script was simply attached here. It is now attached as a
-shar archive to make it easier to extract the script from the documentation.
-To create the ip2mkdev shell script change to a convenient directory (/tmp
-works just fine) and run the following command:
-
- unshar Documentation/computone.txt
- (This file)
-
-You should now have a file ip2mkdev in your current working directory with
-permissions set to execute. Running that script with then create the
-necessary devices for the Computone boards, interfaces, and ports which
-are present on you system at the time it is run.
-
-
-#!/bin/sh
-# This is a shell archive (produced by GNU sharutils 4.2.1).
-# To extract the files from this archive, save it to some FILE, remove
-# everything before the `!/bin/sh' line above, then type `sh FILE'.
-#
-# Made on 2001-10-29 10:32 EST by <mhw@alcove.wittsend.com>.
-# Source directory was `/home2/src/tmp'.
-#
-# Existing files will *not* be overwritten unless `-c' is specified.
-#
-# This shar contains:
-# length mode name
-# ------ ---------- ------------------------------------------
-# 4251 -rwxr-xr-x ip2mkdev
-#
-save_IFS="${IFS}"
-IFS="${IFS}:"
-gettext_dir=FAILED
-locale_dir=FAILED
-first_param="$1"
-for dir in $PATH
-do
- if test "$gettext_dir" = FAILED && test -f $dir/gettext \
- && ($dir/gettext --version >/dev/null 2>&1)
- then
- set `$dir/gettext --version 2>&1`
- if test "$3" = GNU
- then
- gettext_dir=$dir
- fi
- fi
- if test "$locale_dir" = FAILED && test -f $dir/shar \
- && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
- then
- locale_dir=`$dir/shar --print-text-domain-dir`
- fi
-done
-IFS="$save_IFS"
-if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
-then
- echo=echo
-else
- TEXTDOMAINDIR=$locale_dir
- export TEXTDOMAINDIR
- TEXTDOMAIN=sharutils
- export TEXTDOMAIN
- echo="$gettext_dir/gettext -s"
-fi
-if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
- shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
-elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
- shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
-elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
- shar_touch='touch -am $3$4$5$6$2 "$8"'
-else
- shar_touch=:
- echo
- $echo 'WARNING: not restoring timestamps. Consider getting and'
- $echo "installing GNU \`touch', distributed in GNU File Utilities..."
- echo
-fi
-rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
-#
-if mkdir _sh17581; then
- $echo 'x -' 'creating lock directory'
-else
- $echo 'failed to create lock directory'
- exit 1
-fi
-# ============= ip2mkdev ==============
-if test -f 'ip2mkdev' && test "$first_param" != -c; then
- $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
-else
- $echo 'x -' extracting 'ip2mkdev' '(text)'
- sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
-#!/bin/sh -
-#
-# ip2mkdev
-#
-# Make or remove devices as needed for Computone Intelliport drivers
-#
-# First rule! If the dev file exists and you need it, don't mess
-# with it. That prevents us from screwing up open ttys, ownership
-# and permissions on a running system!
-#
-# This script will NOT remove devices that no longer exist if their
-# board or interface box has been removed. If you want to get rid
-# of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
-# before running this script. Running this script will then recreate
-# all the valid devices.
-#
-# Michael H. Warfield
-# /\/\|=mhw=|\/\/
-# mhw@wittsend.com
-#
-# Updated 10/29/2000 for version 1.2.13 naming convention
-# under devfs. /\/\|=mhw=|\/\/
-#
-# Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/
-#
-X
-if test -d /dev/ip2 ; then
-# This is devfs mode... We don't do anything except create symlinks
-# from the real devices to the old names!
-X cd /dev
-X echo "Creating symbolic links to devfs devices"
-X for i in `ls ip2` ; do
-X if test ! -L ip2$i ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f ip2$i
-X ln -s ip2/$i ip2$i
-X fi
-X done
-X for i in `( cd tts ; ls F* )` ; do
-X if test ! -L tty$i ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f tty$i
-X ln -s tts/$i tty$i
-X fi
-X done
-X for i in `( cd cua ; ls F* )` ; do
-X DEVNUMBER=`expr $i : 'F\(.*\)'`
-X if test ! -L cuf$DEVNUMBER ; then
-X # Remove it incase it wasn't a symlink (old device)
-X rm -f cuf$DEVNUMBER
-X ln -s cua/$i cuf$DEVNUMBER
-X fi
-X done
-X exit 0
-fi
-X
-if test ! -f /proc/tty/drivers
-then
-X echo "\
-Unable to check driver status.
-Make sure proc file system is mounted."
-X
-X exit 255
-fi
-X
-if test ! -f /proc/tty/driver/ip2
-then
-X echo "\
-Unable to locate ip2 proc file.
-Attempting to load driver"
-X
-X if /sbin/insmod ip2
-X then
-X if test ! -f /proc/tty/driver/ip2
-X then
-X echo "\
-Unable to locate ip2 proc file after loading driver.
-Driver initialization failure or driver version error.
-"
-X exit 255
-X fi
-X else
-X echo "Unable to load ip2 driver."
-X exit 255
-X fi
-fi
-X
-# Ok... So we got the driver loaded and we can locate the procfs files.
-# Next we need our major numbers.
-X
-TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
-CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
-BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ ]*.*/\1/' < /proc/tty/driver/ip2`
-X
-echo "\
-TTYMAJOR = $TTYMAJOR
-CUAMAJOR = $CUAMAJOR
-BRDMAJOR = $BRDMAJOR
-"
-X
-# Ok... Now we should know our major numbers, if appropriate...
-# Now we need our boards and start the device loops.
-X
-grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
-do
-X # The test for blank "type" will catch the stats lead-in lines
-X # if they exist in the file
-X if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
-X then
-X continue
-X fi
-X
-X BOARDNO=`expr "$number" : '\([0-9]\):'`
-X PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
-X MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
-X
-X if test "$BOARDNO" = "" -o "$PORTS" = ""
-X then
-# This may be a bug. We should at least get this much information
-X echo "Unable to process board line"
-X continue
-X fi
-X
-X if test "$MINORS" = ""
-X then
-# Silently skip this one. This board seems to have no boxes
-X continue
-X fi
-X
-X echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
-X
-X if test "$BRDMAJOR" != ""
-X then
-X BRDMINOR=`expr $BOARDNO \* 4`
-X STSMINOR=`expr $BRDMINOR + 1`
-X if test ! -c /dev/ip2ipl$BOARDNO ; then
-X mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
-X fi
-X if test ! -c /dev/ip2stat$BOARDNO ; then
-X mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
-X fi
-X fi
-X
-X if test "$TTYMAJOR" != ""
-X then
-X PORTNO=$BOARDBASE
-X
-X for PORTNO in $MINORS
-X do
-X if test ! -c /dev/ttyF$PORTNO ; then
-X # We got the hardware but no device - make it
-X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
-X fi
-X done
-X fi
-X
-X if test "$CUAMAJOR" != ""
-X then
-X PORTNO=$BOARDBASE
-X
-X for PORTNO in $MINORS
-X do
-X if test ! -c /dev/cuf$PORTNO ; then
-X # We got the hardware but no device - make it
-X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
-X fi
-X done
-X fi
-done
-X
-Xexit 0
-SHAR_EOF
- (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") &&
- chmod 0755 'ip2mkdev' ||
- $echo 'restore of' 'ip2mkdev' 'failed'
- if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
- && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
- md5sum -c << SHAR_EOF >/dev/null 2>&1 \
- || $echo 'ip2mkdev:' 'MD5 check failed'
-cb5717134509f38bad9fde6b1f79b4a4 ip2mkdev
-SHAR_EOF
- else
- shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
- test 4251 -eq "$shar_count" ||
- $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!"
- fi
-fi
-rm -fr _sh17581
-exit 0
+++ /dev/null
-This driver is for Compaq's SMART2 Intelligent Disk Array Controllers.
-
-Supported Cards:
-----------------
-
-This driver is known to work with the following cards:
-
- * SMART (EISA)
- * SMART-2/E (EISA)
- * SMART-2/P
- * SMART-2DH
- * SMART-2SL
- * SMART-221
- * SMART-3100ES
- * SMART-3200
- * Integrated Smart Array Controller
- * SA 4200
- * SA 4250ES
- * SA 431
- * RAID LC2 Controller
-
-It should also work with some really old Disk array adapters, but I am
-unable to test against these cards:
-
- * IDA
- * IDA-2
- * IAES
-
-
-EISA Controllers:
------------------
-
-If you want to use an EISA controller you'll have to supply some
-modprobe/lilo parameters. If the driver is compiled into the kernel, must
-give it the controller's IO port address at boot time (it is not
-necessary to specify the IRQ). For example, if you had two SMART-2/E
-controllers, in EISA slots 1 and 2 you'd give it a boot argument like
-this:
-
- smart2=0x1000,0x2000
-
-If you were loading the driver as a module, you'd give load it like this:
-
- modprobe cpqarray eisa=0x1000,0x2000
-
-You can use EISA and PCI adapters at the same time.
-
-
-Device Naming:
---------------
-
-You need some entries in /dev for the ida device. MAKEDEV in the /dev
-directory can make device nodes for you automatically. The device setup is
-as follows:
-
-Major numbers:
- 72 ida0
- 73 ida1
- 74 ida2
- 75 ida3
- 76 ida4
- 77 ida5
- 78 ida6
- 79 ida7
-
-Minor numbers:
- b7 b6 b5 b4 b3 b2 b1 b0
- |----+----| |----+----|
- | |
- | +-------- Partition ID (0=wholedev, 1-15 partition)
- |
- +-------------------- Logical Volume number
-
-The device naming scheme is:
-/dev/ida/c0d0 Controller 0, disk 0, whole device
-/dev/ida/c0d0p1 Controller 0, disk 0, partition 1
-/dev/ida/c0d0p2 Controller 0, disk 0, partition 2
-/dev/ida/c0d0p3 Controller 0, disk 0, partition 3
-
-/dev/ida/c1d1 Controller 1, disk 1, whole device
-/dev/ida/c1d1p1 Controller 1, disk 1, partition 1
-/dev/ida/c1d1p2 Controller 1, disk 1, partition 2
-/dev/ida/c1d1p3 Controller 1, disk 1, partition 3
-
-
-Changelog:
-==========
-
-10-28-2004 : General cleanup, syntax fixes for in-kernel driver version.
- James Nelson <james4765@gmail.com>
-
-
-1999 : Original Document
+++ /dev/null
-NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at
-http://www.digi.com for PCI cards. They no longer maintain this driver,
-and have no 2.6 driver for ISA cards.
-
-This driver requires a number of user-space tools. They can be acquired from
-http://www.digi.com, but only works with 2.4 kernels.
-
-
-The Digi Intl. epca driver.
-----------------------------
-The Digi Intl. epca driver for Linux supports the following boards:
-
-Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve
-Digi EISA/Xem, PCI/Xem, PCI/Xr
-
-Limitations:
-------------
-Currently the driver only autoprobes for supported PCI boards.
-
-The Linux MAKEDEV command does not support generating the Digiboard
-Devices. Users executing digiConfig to setup EISA and PC series cards
-will have their device nodes automatically constructed (cud?? for ~CLOCAL,
-and ttyD?? for CLOCAL). Users wishing to boot their board from the LILO
-prompt, or those users booting PCI cards may use buildDIGI to construct
-the necessary nodes.
-
-Notes:
-------
-This driver may be configured via LILO. For users who have already configured
-their driver using digiConfig, configuring from LILO will override previous
-settings. Multiple boards may be configured by issuing multiple LILO command
-lines. For examples see the bottom of this document.
-
-Device names start at 0 and continue up. Beware of this as previous Digi
-drivers started device names with 1.
-
-PCI boards are auto-detected and configured by the driver. PCI boards will
-be allocated device numbers (internally) beginning with the lowest PCI slot
-first. In other words a PCI card in slot 3 will always have higher device
-nodes than a PCI card in slot 1.
-
-LILO config examples:
----------------------
-Using LILO's APPEND command, a string of comma separated identifiers or
-integers can be used to configure supported boards. The six values in order
-are:
-
- Enable/Disable this card or Override,
- Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2),
- EISA/Xem (3), PC/64Xe (4), PC/Xi (5),
- Enable/Disable alternate pin arrangement,
- Number of ports on this card,
- I/O Port where card is configured (in HEX if using string identifiers),
- Base of memory window (in HEX if using string identifiers),
-
-NOTE : PCI boards are auto-detected and configured. Do not attempt to
-configure PCI boards with the LILO append command. If you wish to override
-previous configuration data (As set by digiConfig), but you do not wish to
-configure any specific card (Example if there are PCI cards in the system)
-the following override command will accomplish this:
--> append="digi=2"
-
-Samples:
- append="digiepca=E,PC/Xe,D,16,200,D0000"
- or
- append="digi=1,0,0,16,512,851968"
-
-Supporting Tools:
------------------
-Supporting tools include digiDload, digiConfig, buildPCI, and ditty. See
-drivers/char/README.epca for more details. Note,
-this driver REQUIRES that digiDload be executed prior to it being used.
-Failure to do this will result in an ENODEV error.
-
-Documentation:
---------------
-Complete documentation for this product may be found in the tool package.
-
-Sources of information and support:
------------------------------------
-Digi Intl. support site for this product:
-
--> http://www.digi.com
-
-Acknowledgments:
-----------------
-Much of this work (And even text) was derived from a similar document
-supporting the original public domain DigiBoard driver Copyright (C)
-1994,1995 Troy De Jongh. Many thanks to Christoph Lameter
-(christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored
-and contributed to the original document.
-
-Changelog:
-----------
-10-29-04: Update status of driver, remove dead links in document
- James Nelson <james4765@gmail.com>
-
-2000 (?) Original Document
+++ /dev/null
-This file describes the floppy driver.
-
-FAQ list:
-=========
-
- A FAQ list may be found in the fdutils package (see below), and also
-at <http://fdutils.linux.lu/faq.html>.
-
-
-LILO configuration options (Thinkpad users, read this)
-======================================================
-
- The floppy driver is configured using the 'floppy=' option in
-lilo. This option can be typed at the boot prompt, or entered in the
-lilo configuration file.
-
- Example: If your kernel is called linux-2.6.9, type the following line
-at the lilo boot prompt (if you have a thinkpad):
-
- linux-2.6.9 floppy=thinkpad
-
-You may also enter the following line in /etc/lilo.conf, in the description
-of linux-2.6.9:
-
- append = "floppy=thinkpad"
-
- Several floppy related options may be given, example:
-
- linux-2.6.9 floppy=daring floppy=two_fdc
- append = "floppy=daring floppy=two_fdc"
-
- If you give options both in the lilo config file and on the boot
-prompt, the option strings of both places are concatenated, the boot
-prompt options coming last. That's why there are also options to
-restore the default behavior.
-
-
-Module configuration options
-============================
-
- If you use the floppy driver as a module, use the following syntax:
-modprobe floppy <options>
-
-Example:
- modprobe floppy omnibook messages
-
- If you need certain options enabled every time you load the floppy driver,
-you can put:
-
- options floppy omnibook messages
-
-in /etc/modprobe.conf.
-
-
- The floppy driver related options are:
-
- floppy=asus_pci
- Sets the bit mask to allow only units 0 and 1. (default)
-
- floppy=daring
- Tells the floppy driver that you have a well behaved floppy controller.
- This allows more efficient and smoother operation, but may fail on
- certain controllers. This may speed up certain operations.
-
- floppy=0,daring
- Tells the floppy driver that your floppy controller should be used
- with caution.
-
- floppy=one_fdc
- Tells the floppy driver that you have only one floppy controller.
- (default)
-
- floppy=two_fdc
- floppy=<address>,two_fdc
- Tells the floppy driver that you have two floppy controllers.
- The second floppy controller is assumed to be at <address>.
- This option is not needed if the second controller is at address
- 0x370, and if you use the 'cmos' option.
-
- floppy=thinkpad
- Tells the floppy driver that you have a Thinkpad. Thinkpads use an
- inverted convention for the disk change line.
-
- floppy=0,thinkpad
- Tells the floppy driver that you don't have a Thinkpad.
-
- floppy=omnibook
- floppy=nodma
- Tells the floppy driver not to use Dma for data transfers.
- This is needed on HP Omnibooks, which don't have a workable
- DMA channel for the floppy driver. This option is also useful
- if you frequently get "Unable to allocate DMA memory" messages.
- Indeed, dma memory needs to be continuous in physical memory,
- and is thus harder to find, whereas non-dma buffers may be
- allocated in virtual memory. However, I advise against this if
- you have an FDC without a FIFO (8272A or 82072). 82072A and
- later are OK. You also need at least a 486 to use nodma.
- If you use nodma mode, I suggest you also set the FIFO
- threshold to 10 or lower, in order to limit the number of data
- transfer interrupts.
-
- If you have a FIFO-able FDC, the floppy driver automatically
- falls back on non DMA mode if no DMA-able memory can be found.
- If you want to avoid this, explicitly ask for 'yesdma'.
-
- floppy=yesdma
- Tells the floppy driver that a workable DMA channel is available.
- (default)
-
- floppy=nofifo
- Disables the FIFO entirely. This is needed if you get "Bus
- master arbitration error" messages from your Ethernet card (or
- from other devices) while accessing the floppy.
-
- floppy=usefifo
- Enables the FIFO. (default)
-
- floppy=<threshold>,fifo_depth
- Sets the FIFO threshold. This is mostly relevant in DMA
- mode. If this is higher, the floppy driver tolerates more
- interrupt latency, but it triggers more interrupts (i.e. it
- imposes more load on the rest of the system). If this is
- lower, the interrupt latency should be lower too (faster
- processor). The benefit of a lower threshold is less
- interrupts.
-
- To tune the fifo threshold, switch on over/underrun messages
- using 'floppycontrol --messages'. Then access a floppy
- disk. If you get a huge amount of "Over/Underrun - retrying"
- messages, then the fifo threshold is too low. Try with a
- higher value, until you only get an occasional Over/Underrun.
- It is a good idea to compile the floppy driver as a module
- when doing this tuning. Indeed, it allows to try different
- fifo values without rebooting the machine for each test. Note
- that you need to do 'floppycontrol --messages' every time you
- re-insert the module.
-
- Usually, tuning the fifo threshold should not be needed, as
- the default (0xa) is reasonable.
-
- floppy=<drive>,<type>,cmos
- Sets the CMOS type of <drive> to <type>. This is mandatory if
- you have more than two floppy drives (only two can be
- described in the physical CMOS), or if your BIOS uses
- non-standard CMOS types. The CMOS types are:
-
- 0 - Use the value of the physical CMOS
- 1 - 5 1/4 DD
- 2 - 5 1/4 HD
- 3 - 3 1/2 DD
- 4 - 3 1/2 HD
- 5 - 3 1/2 ED
- 6 - 3 1/2 ED
- 16 - unknown or not installed
-
- (Note: there are two valid types for ED drives. This is because 5 was
- initially chosen to represent floppy *tapes*, and 6 for ED drives.
- AMI ignored this, and used 5 for ED drives. That's why the floppy
- driver handles both.)
-
- floppy=unexpected_interrupts
- Print a warning message when an unexpected interrupt is received.
- (default)
-
- floppy=no_unexpected_interrupts
- floppy=L40SX
- Don't print a message when an unexpected interrupt is received. This
- is needed on IBM L40SX laptops in certain video modes. (There seems
- to be an interaction between video and floppy. The unexpected
- interrupts affect only performance, and can be safely ignored.)
-
- floppy=broken_dcl
- Don't use the disk change line, but assume that the disk was
- changed whenever the device node is reopened. Needed on some
- boxes where the disk change line is broken or unsupported.
- This should be regarded as a stopgap measure, indeed it makes
- floppy operation less efficient due to unneeded cache
- flushings, and slightly more unreliable. Please verify your
- cable, connection and jumper settings if you have any DCL
- problems. However, some older drives, and also some laptops
- are known not to have a DCL.
-
- floppy=debug
- Print debugging messages.
-
- floppy=messages
- Print informational messages for some operations (disk change
- notifications, warnings about over and underruns, and about
- autodetection).
-
- floppy=silent_dcl_clear
- Uses a less noisy way to clear the disk change line (which
- doesn't involve seeks). Implied by 'daring' option.
-
- floppy=<nr>,irq
- Sets the floppy IRQ to <nr> instead of 6.
-
- floppy=<nr>,dma
- Sets the floppy DMA channel to <nr> instead of 2.
-
- floppy=slow
- Use PS/2 stepping rate:
- " PS/2 floppies have much slower step rates than regular floppies.
- It's been recommended that take about 1/4 of the default speed
- in some more extreme cases."
-
-
-Supporting utilities and additional documentation:
-==================================================
-
- Additional parameters of the floppy driver can be configured at
-runtime. Utilities which do this can be found in the fdutils package.
-This package also contains a new version of mtools which allows to
-access high capacity disks (up to 1992K on a high density 3 1/2 disk!).
-It also contains additional documentation about the floppy driver.
-
-The latest version can be found at fdutils homepage:
- http://fdutils.linux.lu
-
-The fdutils releases can be found at:
- http://fdutils.linux.lu/download.html
- http://www.tux.org/pub/knaff/fdutils/
- ftp://metalab.unc.edu/pub/Linux/utils/disk-management/
-
-Reporting problems about the floppy driver
-==========================================
-
- If you have a question or a bug report about the floppy driver, mail
-me at Alain.Knaff@poboxes.com . If you post to Usenet, preferably use
-comp.os.linux.hardware. As the volume in these groups is rather high,
-be sure to include the word "floppy" (or "FLOPPY") in the subject
-line. If the reported problem happens when mounting floppy disks, be
-sure to mention also the type of the filesystem in the subject line.
-
- Be sure to read the FAQ before mailing/posting any bug reports!
-
- Alain
-
-Changelog
-=========
-
-10-30-2004 : Cleanup, updating, add reference to module configuration.
- James Nelson <james4765@gmail.com>
-
-6-3-2000 : Original Document
+++ /dev/null
-HAYES ESP DRIVER VERSION 2.1
-
-A big thanks to the people at Hayes, especially Alan Adamson. Their support
-has enabled me to provide enhancements to the driver.
-
-Please report your experiences with this driver to me (arobinso@nyx.net). I
-am looking for both positive and negative feedback.
-
-*** IMPORTANT CHANGES FOR 2.1 ***
-Support for PIO mode. Five situations will cause PIO mode to be used:
-1) A multiport card is detected. PIO mode will always be used. (8 port cards
-do not support DMA).
-2) The DMA channel is set to an invalid value (anything other than 1 or 3).
-3) The DMA buffer/channel could not be allocated. The port will revert to PIO
-mode until it is reopened.
-4) Less than a specified number of bytes need to be transferred to/from the
-FIFOs. PIO mode will be used for that transfer only.
-5) A port needs to do a DMA transfer and another port is already using the
-DMA channel. PIO mode will be used for that transfer only.
-
-Since the Hayes ESP seems to conflict with other cards (notably sound cards)
-when using DMA, DMA is turned off by default. To use DMA, it must be turned
-on explicitly, either with the "dma=" option described below or with
-setserial. A multiport card can be forced into DMA mode by using setserial;
-however, most multiport cards don't support DMA.
-
-The latest version of setserial allows the enhanced configuration of the ESP
-card to be viewed and modified.
-***
-
-This package contains the files needed to compile a module to support the Hayes
-ESP card. The drivers are basically a modified version of the serial drivers.
-
-Features:
-
-- Uses the enhanced mode of the ESP card, allowing a wider range of
- interrupts and features than compatibility mode
-- Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs,
- reducing CPU load
-- Supports primary and secondary ports
-
-
-If the driver is compiled as a module, the IRQs to use can be specified by
-using the irq= option. The format is:
-
-irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380]
-
-The address in brackets is the base address of the card. The IRQ of
-nonexistent cards can be set to 0. If an IRQ of a card that does exist is set
-to 0, the driver will attempt to guess at the correct IRQ. For example, to set
-the IRQ of the card at address 0x300 to 12, the insmod command would be:
-
-insmod esp irq=0,0,0,0,0,0,12,0
-
-The custom divisor can be set by using the divisor= option. The format is the
-same as for the irq= option. Each divisor value is a series of hex digits,
-with each digit representing the divisor to use for a corresponding port. The
-divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value
-will automatically set the spd_cust flag. To calculate the divisor to use for
-a certain baud rate, divide the port's base baud (generally 921600) by the
-desired rate. For example, to set the divisor of the primary port at 0x300 to
-4 and the divisor of the secondary port at 0x308 to 8, the insmod command would
-be:
-
-insmod esp divisor=0,0,0,0,0,0,0x84,0
-
-The dma= option can be used to set the DMA channel. The channel can be either
-1 or 3. Specifying any other value will force the driver to use PIO mode.
-For example, to set the DMA channel to 3, the insmod command would be:
-
-insmod esp dma=3
-
-The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger
-levels. They specify when the ESP card should send an interrupt. Larger
-values will decrease the number of interrupts; however, a value too high may
-result in data loss. Valid values are 1 through 1023, with 768 being the
-default. For example, to set the receive trigger level to 512 bytes and the
-transmit trigger level to 700 bytes, the insmod command would be:
-
-insmod esp rx_trigger=512 tx_trigger=700
-
-The flow_off= and flow_on= options can be used to set the hardware flow off/
-flow on levels. The flow on level must be lower than the flow off level, and
-the flow off level should be higher than rx_trigger. Valid values are 1
-through 1023, with 1016 being the default flow off level and 944 being the
-default flow on level. For example, to set the flow off level to 1000 bytes
-and the flow on level to 935 bytes, the insmod command would be:
-
-insmod esp flow_off=1000 flow_on=935
-
-The rx_timeout= option can be used to set the receive timeout value. This
-value indicates how long after receiving the last character that the ESP card
-should wait before signalling an interrupt. Valid values are 0 though 255,
-with 128 being the default. A value too high will increase latency, and a
-value too low will cause unnecessary interrupts. For example, to set the
-receive timeout to 255, the insmod command would be:
-
-insmod esp rx_timeout=255
-
-The pio_threshold= option sets the threshold (in number of characters) for
-using PIO mode instead of DMA mode. For example, if this value is 32,
-transfers of 32 bytes or less will always use PIO mode.
-
-insmod esp pio_threshold=32
-
-Multiple options can be listed on the insmod command line by separating each
-option with a space. For example:
-
-insmod esp dma=3 trigger=512
-
-The esp module can be automatically loaded when needed. To cause this to
-happen, add the following lines to /etc/modprobe.conf (replacing the last line
-with options for your configuration):
-
-alias char-major-57 esp
-alias char-major-58 esp
-options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0
-
-You may also need to run 'depmod -a'.
-
-Devices must be created manually. To create the devices, note the output from
-the module after it is inserted. The output will appear in the location where
-kernel messages usually appear (usually /var/adm/messages). Create two devices
-for each 'tty' mentioned, one with major of 57 and the other with major of 58.
-The minor number should be the same as the tty number reported. The commands
-would be (replace ? with the tty number):
-
-mknod /dev/ttyP? c 57 ?
-mknod /dev/cup? c 58 ?
-
-For example, if the following line appears:
-
-Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port
-
-...two devices should be created:
-
-mknod /dev/ttyP8 c 57 8
-mknod /dev/cup8 c 58 8
-
-You may need to set the permissions on the devices:
-
-chmod 666 /dev/ttyP*
-chmod 666 /dev/cup*
-
-The ESP module and the serial module should not conflict (they can be used at
-the same time). After the ESP module has been loaded the ports on the ESP card
-will no longer be accessible by the serial driver.
-
-If I/O errors are experienced when accessing the port, check for IRQ and DMA
-conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and
-DMAs currently in use).
-
-Enjoy!
-Andrew J. Robinson <arobinso@nyx.net>
+++ /dev/null
-Ioctl Numbers
-19 October 1999
-Michael Elizabeth Chastain
-<mec@shout.net>
-
-If you are adding new ioctl's to the kernel, you should use the _IO
-macros defined in <linux/ioctl.h>:
-
- _IO an ioctl with no parameters
- _IOW an ioctl with write parameters (copy_from_user)
- _IOR an ioctl with read parameters (copy_to_user)
- _IOWR an ioctl with both write and read parameters.
-
-'Write' and 'read' are from the user's point of view, just like the
-system calls 'write' and 'read'. For example, a SET_FOO ioctl would
-be _IOW, although the kernel would actually read data from user space;
-a GET_FOO ioctl would be _IOR, although the kernel would actually write
-data to user space.
-
-The first argument to _IO, _IOW, _IOR, or _IOWR is an identifying letter
-or number from the table below. Because of the large number of drivers,
-many drivers share a partial letter with other drivers.
-
-If you are writing a driver for a new device and need a letter, pick an
-unused block with enough room for expansion: 32 to 256 ioctl commands.
-You can register the block by patching this file and submitting the
-patch to Linus Torvalds. Or you can e-mail me at <mec@shout.net> and
-I'll register one for you.
-
-The second argument to _IO, _IOW, _IOR, or _IOWR is a sequence number
-to distinguish ioctls from each other. The third argument to _IOW,
-_IOR, or _IOWR is the type of the data going into the kernel or coming
-out of the kernel (e.g. 'int' or 'struct foo'). NOTE! Do NOT use
-sizeof(arg) as the third argument as this results in your ioctl thinking
-it passes an argument of type size_t.
-
-Some devices use their major number as the identifier; this is OK, as
-long as it is unique. Some devices are irregular and don't follow any
-convention at all.
-
-Following this convention is good because:
-
-(1) Keeping the ioctl's globally unique helps error checking:
- if a program calls an ioctl on the wrong device, it will get an
- error rather than some unexpected behaviour.
-
-(2) The 'strace' build procedure automatically finds ioctl numbers
- defined with _IO, _IOW, _IOR, or _IOWR.
-
-(3) 'strace' can decode numbers back into useful names when the
- numbers are unique.
-
-(4) People looking for ioctls can grep for them more easily when
- this convention is used to define the ioctl numbers.
-
-(5) When following the convention, the driver code can use generic
- code to copy the parameters between user and kernel space.
-
-This table lists ioctls visible from user land for Linux/i386. It contains
-most drivers up to 2.3.14, but I know I am missing some.
-
-Code Seq# Include File Comments
-========================================================
-0x00 00-1F linux/fs.h conflict!
-0x00 00-1F scsi/scsi_ioctl.h conflict!
-0x00 00-1F linux/fb.h conflict!
-0x00 00-1F linux/wavefront.h conflict!
-0x02 all linux/fd.h
-0x03 all linux/hdreg.h
-0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these.
-0x06 all linux/lp.h
-0x09 all linux/md.h
-0x12 all linux/fs.h
- linux/blkpg.h
-0x1b all InfiniBand Subsystem <http://www.openib.org/>
-0x20 all drivers/cdrom/cm206.h
-0x22 all scsi/sg.h
-'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
-'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
- <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
-'8' all SNP8023 advanced NIC card
- <mailto:mcr@solidum.com>
-'A' 00-1F linux/apm_bios.h
-'B' C0-FF advanced bbus
- <mailto:maassen@uni-freiburg.de>
-'C' all linux/soundcard.h
-'D' all asm-s390/dasd.h
-'E' all linux/input.h
-'F' all linux/fb.h
-'H' all linux/hiddev.h
-'I' all linux/isdn.h
-'J' 00-1F drivers/scsi/gdth_ioctl.h
-'K' all linux/kd.h
-'L' 00-1F linux/loop.h
-'L' 20-2F driver/usb/misc/vstusb.h
-'L' E0-FF linux/ppdd.h encrypted disk device driver
- <http://linux01.gwdg.de/~alatham/ppdd.html>
-'M' all linux/soundcard.h
-'N' 00-1F drivers/usb/scanner.h
-'P' all linux/soundcard.h
-'Q' all linux/soundcard.h
-'R' 00-1F linux/random.h
-'S' all linux/cdrom.h conflict!
-'S' 80-81 scsi/scsi_ioctl.h conflict!
-'S' 82-FF scsi/scsi.h conflict!
-'T' all linux/soundcard.h conflict!
-'T' all asm-i386/ioctls.h conflict!
-'U' 00-EF linux/drivers/usb/usb.h
-'V' all linux/vt.h
-'W' 00-1F linux/watchdog.h conflict!
-'W' 00-1F linux/wanrouter.h conflict!
-'X' all linux/xfs_fs.h
-'Y' all linux/cyclades.h
-'[' 00-07 linux/usb/usbtmc.h USB Test and Measurement Devices
- <mailto:gregkh@suse.de>
-'a' all ATM on linux
- <http://lrcwww.epfl.ch/linux-atm/magic.html>
-'b' 00-FF bit3 vme host bridge
- <mailto:natalia@nikhefk.nikhef.nl>
-'c' 00-7F linux/comstats.h conflict!
-'c' 00-7F linux/coda.h conflict!
-'c' 80-9F asm-s390/chsc.h
-'d' 00-FF linux/char/drm/drm/h conflict!
-'d' 00-DF linux/video_decoder.h conflict!
-'d' F0-FF linux/digi1.h
-'e' all linux/digi1.h conflict!
-'e' 00-1F linux/video_encoder.h conflict!
-'e' 00-1F net/irda/irtty.h conflict!
-'f' 00-1F linux/ext2_fs.h
-'h' 00-7F Charon filesystem
- <mailto:zapman@interlan.net>
-'i' 00-3F linux/i2o.h
-'j' 00-3F linux/joystick.h
-'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
- <http://mikonos.dia.unisa.it/tcfs>
-'l' 40-7F linux/udf_fs_i.h in development:
- <http://sourceforge.net/projects/linux-udf/>
-'m' all linux/mtio.h conflict!
-'m' all linux/soundcard.h conflict!
-'m' all linux/synclink.h conflict!
-'m' 00-1F net/irda/irmod.h conflict!
-'n' 00-7F linux/ncp_fs.h
-'n' E0-FF video/matrox.h matroxfb
-'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
-'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this)
-'p' 00-3F linux/mc146818rtc.h conflict!
-'p' 40-7F linux/nvram.h
-'p' 80-9F user-space parport
- <mailto:tim@cyberelk.net>
-'q' 00-1F linux/serio.h
-'q' 80-FF Internet PhoneJACK, Internet LineJACK
- <http://www.quicknet.net>
-'r' 00-1F linux/msdos_fs.h
-'s' all linux/cdk.h
-'t' 00-7F linux/if_ppp.h
-'t' 80-8F linux/isdn_ppp.h
-'u' 00-1F linux/smb_fs.h
-'v' 00-1F linux/ext2_fs.h conflict!
-'v' all linux/videodev.h conflict!
-'w' all CERN SCI driver
-'y' 00-1F packet based user level communications
- <mailto:zapman@interlan.net>
-'z' 00-3F CAN bus card
- <mailto:hdstich@connectu.ulm.circular.de>
-'z' 40-7F CAN bus card
- <mailto:oe@port.de>
-0x80 00-1F linux/fb.h
-0x81 00-1F linux/videotext.h
-0x89 00-06 asm-i386/sockios.h
-0x89 0B-DF linux/sockios.h
-0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
-0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
-0x8B all linux/wireless.h
-0x8C 00-3F WiNRADiO driver
- <http://www.proximity.com.au/~brian/winradio/>
-0x90 00 drivers/cdrom/sbpcd.h
-0x93 60-7F linux/auto_fs.h
-0x99 00-0F 537-Addinboard driver
- <mailto:buk@buks.ipn.de>
-0xA0 all linux/sdp/sdp.h Industrial Device Project
- <mailto:kenji@bitgate.com>
-0xA3 80-8F Port ACL in development:
- <mailto:tlewis@mindspring.com>
-0xA3 90-9F linux/dtlk.h
-0xAB 00-1F linux/nbd.h
-0xAC 00-1F linux/raw.h
-0xAD 00 Netfilter device in development:
- <mailto:rusty@rustcorp.com.au>
-0xAE all linux/kvm.h Kernel-based Virtual Machine
- <mailto:kvm-devel@lists.sourceforge.net>
-0xB0 all RATIO devices in development:
- <mailto:vgo@ratio.de>
-0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
-0xCB 00-1F CBM serial IEC bus in development:
- <mailto:michael.klein@puffin.lb.shuttle.de>
-0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
- <mailto:aherrman@de.ibm.com>
-0xF3 00-3F video/sisfb.h sisfb (in development)
- <mailto:thomas@winischhofer.net>
-0xF4 00-1F video/mbxfb.h mbxfb
- <mailto:raph@8d.com>
--- /dev/null
+00-INDEX
+ - this file
+cdrom.txt
+ - summary of CDROM ioctl calls
+hdio.txt
+ - summary of HDIO_ ioctl calls
+ioctl-decoding.txt
+ - how to decode the bits of an IOCTL code
+ioctl-number.txt
+ - how to implement and register device/driver ioctl calls
--- /dev/null
+Ioctl Numbers
+19 October 1999
+Michael Elizabeth Chastain
+<mec@shout.net>
+
+If you are adding new ioctl's to the kernel, you should use the _IO
+macros defined in <linux/ioctl.h>:
+
+ _IO an ioctl with no parameters
+ _IOW an ioctl with write parameters (copy_from_user)
+ _IOR an ioctl with read parameters (copy_to_user)
+ _IOWR an ioctl with both write and read parameters.
+
+'Write' and 'read' are from the user's point of view, just like the
+system calls 'write' and 'read'. For example, a SET_FOO ioctl would
+be _IOW, although the kernel would actually read data from user space;
+a GET_FOO ioctl would be _IOR, although the kernel would actually write
+data to user space.
+
+The first argument to _IO, _IOW, _IOR, or _IOWR is an identifying letter
+or number from the table below. Because of the large number of drivers,
+many drivers share a partial letter with other drivers.
+
+If you are writing a driver for a new device and need a letter, pick an
+unused block with enough room for expansion: 32 to 256 ioctl commands.
+You can register the block by patching this file and submitting the
+patch to Linus Torvalds. Or you can e-mail me at <mec@shout.net> and
+I'll register one for you.
+
+The second argument to _IO, _IOW, _IOR, or _IOWR is a sequence number
+to distinguish ioctls from each other. The third argument to _IOW,
+_IOR, or _IOWR is the type of the data going into the kernel or coming
+out of the kernel (e.g. 'int' or 'struct foo'). NOTE! Do NOT use
+sizeof(arg) as the third argument as this results in your ioctl thinking
+it passes an argument of type size_t.
+
+Some devices use their major number as the identifier; this is OK, as
+long as it is unique. Some devices are irregular and don't follow any
+convention at all.
+
+Following this convention is good because:
+
+(1) Keeping the ioctl's globally unique helps error checking:
+ if a program calls an ioctl on the wrong device, it will get an
+ error rather than some unexpected behaviour.
+
+(2) The 'strace' build procedure automatically finds ioctl numbers
+ defined with _IO, _IOW, _IOR, or _IOWR.
+
+(3) 'strace' can decode numbers back into useful names when the
+ numbers are unique.
+
+(4) People looking for ioctls can grep for them more easily when
+ this convention is used to define the ioctl numbers.
+
+(5) When following the convention, the driver code can use generic
+ code to copy the parameters between user and kernel space.
+
+This table lists ioctls visible from user land for Linux/i386. It contains
+most drivers up to 2.3.14, but I know I am missing some.
+
+Code Seq# Include File Comments
+========================================================
+0x00 00-1F linux/fs.h conflict!
+0x00 00-1F scsi/scsi_ioctl.h conflict!
+0x00 00-1F linux/fb.h conflict!
+0x00 00-1F linux/wavefront.h conflict!
+0x02 all linux/fd.h
+0x03 all linux/hdreg.h
+0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these.
+0x06 all linux/lp.h
+0x09 all linux/md.h
+0x12 all linux/fs.h
+ linux/blkpg.h
+0x1b all InfiniBand Subsystem <http://www.openib.org/>
+0x20 all drivers/cdrom/cm206.h
+0x22 all scsi/sg.h
+'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
+'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
+ <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
+'8' all SNP8023 advanced NIC card
+ <mailto:mcr@solidum.com>
+'A' 00-1F linux/apm_bios.h
+'B' C0-FF advanced bbus
+ <mailto:maassen@uni-freiburg.de>
+'C' all linux/soundcard.h
+'D' all asm-s390/dasd.h
+'E' all linux/input.h
+'F' all linux/fb.h
+'H' all linux/hiddev.h
+'I' all linux/isdn.h
+'J' 00-1F drivers/scsi/gdth_ioctl.h
+'K' all linux/kd.h
+'L' 00-1F linux/loop.h
+'L' 20-2F driver/usb/misc/vstusb.h
+'L' E0-FF linux/ppdd.h encrypted disk device driver
+ <http://linux01.gwdg.de/~alatham/ppdd.html>
+'M' all linux/soundcard.h
+'N' 00-1F drivers/usb/scanner.h
+'P' all linux/soundcard.h
+'Q' all linux/soundcard.h
+'R' 00-1F linux/random.h
+'S' all linux/cdrom.h conflict!
+'S' 80-81 scsi/scsi_ioctl.h conflict!
+'S' 82-FF scsi/scsi.h conflict!
+'T' all linux/soundcard.h conflict!
+'T' all asm-i386/ioctls.h conflict!
+'U' 00-EF linux/drivers/usb/usb.h
+'V' all linux/vt.h
+'W' 00-1F linux/watchdog.h conflict!
+'W' 00-1F linux/wanrouter.h conflict!
+'X' all linux/xfs_fs.h
+'Y' all linux/cyclades.h
+'[' 00-07 linux/usb/usbtmc.h USB Test and Measurement Devices
+ <mailto:gregkh@suse.de>
+'a' all ATM on linux
+ <http://lrcwww.epfl.ch/linux-atm/magic.html>
+'b' 00-FF bit3 vme host bridge
+ <mailto:natalia@nikhefk.nikhef.nl>
+'c' 00-7F linux/comstats.h conflict!
+'c' 00-7F linux/coda.h conflict!
+'c' 80-9F asm-s390/chsc.h
+'d' 00-FF linux/char/drm/drm/h conflict!
+'d' 00-DF linux/video_decoder.h conflict!
+'d' F0-FF linux/digi1.h
+'e' all linux/digi1.h conflict!
+'e' 00-1F linux/video_encoder.h conflict!
+'e' 00-1F net/irda/irtty.h conflict!
+'f' 00-1F linux/ext2_fs.h
+'h' 00-7F Charon filesystem
+ <mailto:zapman@interlan.net>
+'i' 00-3F linux/i2o.h
+'j' 00-3F linux/joystick.h
+'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
+ <http://mikonos.dia.unisa.it/tcfs>
+'l' 40-7F linux/udf_fs_i.h in development:
+ <http://sourceforge.net/projects/linux-udf/>
+'m' all linux/mtio.h conflict!
+'m' all linux/soundcard.h conflict!
+'m' all linux/synclink.h conflict!
+'m' 00-1F net/irda/irmod.h conflict!
+'n' 00-7F linux/ncp_fs.h
+'n' E0-FF video/matrox.h matroxfb
+'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
+'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this)
+'p' 00-3F linux/mc146818rtc.h conflict!
+'p' 40-7F linux/nvram.h
+'p' 80-9F user-space parport
+ <mailto:tim@cyberelk.net>
+'q' 00-1F linux/serio.h
+'q' 80-FF Internet PhoneJACK, Internet LineJACK
+ <http://www.quicknet.net>
+'r' 00-1F linux/msdos_fs.h
+'s' all linux/cdk.h
+'t' 00-7F linux/if_ppp.h
+'t' 80-8F linux/isdn_ppp.h
+'u' 00-1F linux/smb_fs.h
+'v' 00-1F linux/ext2_fs.h conflict!
+'v' all linux/videodev.h conflict!
+'w' all CERN SCI driver
+'y' 00-1F packet based user level communications
+ <mailto:zapman@interlan.net>
+'z' 00-3F CAN bus card
+ <mailto:hdstich@connectu.ulm.circular.de>
+'z' 40-7F CAN bus card
+ <mailto:oe@port.de>
+0x80 00-1F linux/fb.h
+0x81 00-1F linux/videotext.h
+0x89 00-06 asm-i386/sockios.h
+0x89 0B-DF linux/sockios.h
+0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
+0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
+0x8B all linux/wireless.h
+0x8C 00-3F WiNRADiO driver
+ <http://www.proximity.com.au/~brian/winradio/>
+0x90 00 drivers/cdrom/sbpcd.h
+0x93 60-7F linux/auto_fs.h
+0x99 00-0F 537-Addinboard driver
+ <mailto:buk@buks.ipn.de>
+0xA0 all linux/sdp/sdp.h Industrial Device Project
+ <mailto:kenji@bitgate.com>
+0xA3 80-8F Port ACL in development:
+ <mailto:tlewis@mindspring.com>
+0xA3 90-9F linux/dtlk.h
+0xAB 00-1F linux/nbd.h
+0xAC 00-1F linux/raw.h
+0xAD 00 Netfilter device in development:
+ <mailto:rusty@rustcorp.com.au>
+0xAE all linux/kvm.h Kernel-based Virtual Machine
+ <mailto:kvm-devel@lists.sourceforge.net>
+0xB0 all RATIO devices in development:
+ <mailto:vgo@ratio.de>
+0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
+0xCB 00-1F CBM serial IEC bus in development:
+ <mailto:michael.klein@puffin.lb.shuttle.de>
+0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
+ <mailto:aherrman@de.ibm.com>
+0xF3 00-3F video/sisfb.h sisfb (in development)
+ <mailto:thomas@winischhofer.net>
+0xF4 00-1F video/mbxfb.h mbxfb
+ <mailto:raph@8d.com>
Possible values are:
isolate - enable device isolation (each device, as far
as possible, will get its own protection
- domain)
+ domain) [default]
+ share - put every device behind one IOMMU into the
+ same protection domain
fullflush - enable flushing of IO/TLB entries when
they are unmapped. Otherwise they are
flushed before they will be reused, which
digiepca= [HW,SERIAL]
See drivers/char/README.epca and
- Documentation/digiepca.txt.
+ Documentation/serial/digiepca.txt.
disable_mtrr_cleanup [X86]
enable_mtrr_cleanup [X86]
See header of drivers/scsi/fdomain.c.
floppy= [HW]
- See Documentation/floppy.txt.
+ See Documentation/blockdev/floppy.txt.
force_pal_cache_flush
[IA-64] Avoid check_sal_cache_flush which may hang on
the same attribute, the last one is used.
load_ramdisk= [RAM] List of ramdisks to load from floppy
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
lockd.nlm_grace_period=P [NFS] Assign grace period.
Format: <integer>
it is equivalent to "nosmp", which also disables
the IO APIC.
- max_addr=[KMG] [KNL,BOOT,ia64] All physical memory greater than or
- equal to this physical address is ignored.
+ max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater than
+ or equal to this physical address is ignored.
max_luns= [SCSI] Maximum number of LUNs to probe.
Should be between 1 and 2^32-1.
mga= [HW,DRM]
+ min_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory below this
+ physical address is ignored.
+
mminit_loglevel=
[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
parameter allows control of the logging verbosity for
pcd. [PARIDE]
See header of drivers/block/paride/pcd.c.
- See also Documentation/paride.txt.
+ See also Documentation/blockdev/paride.txt.
pci=option[,option...] [PCI] various PCI subsystem options:
off [X86] don't probe for the PCI bus
pcmv= [HW,PCMCIA] BadgePAD 4
pd. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pdcchassis= [PARISC,HW] Disable/Enable PDC Chassis Status codes at
boot time.
See arch/parisc/kernel/pdc_chassis.c
pf. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pg. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pirq= [SMP,APIC] Manual mp-table setup
See Documentation/x86/i386/IO-APIC.txt.
prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
before loading.
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for; one of (bare|imps|exps|lifebook|any).
<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
pt. [PARIDE]
- See Documentation/paride.txt.
+ See Documentation/blockdev/paride.txt.
pty.legacy_count=
[KNL] Number of legacy pty's. Overwrites compiled-in
See Documentation/md.txt.
ramdisk_blocksize= [RAM]
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
ramdisk_size= [RAM] Sizes of RAM disks in kilobytes
- See Documentation/ramdisk.txt.
+ See Documentation/blockdev/ramdisk.txt.
rcupdate.blimit= [KNL,BOOT]
Set maximum number of finished RCU callbacks to process
See Documentation/sonypi.txt
specialix= [HW,SERIAL] Specialix multi-serial port adapter
- See Documentation/specialix.txt.
+ See Documentation/serial/specialix.txt.
spia_io_base= [HW,MTD]
spia_fio_base=
# less /proc/lock_stat
-01 lock_stat version 0.2
+01 lock_stat version 0.3
02 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
03 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total
04 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05
-06 &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60
-07 &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38
-08 --------------------------
-09 &inode->i_data.tree_lock 0 [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190
-10
-11 ...............................................................................................................................................................................................
-12
-13 dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24
-14 -----------
-15 dcache_lock 180 [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230
-16 dcache_lock 165 [<ffffffff802c002a>] d_alloc+0x15a/0x210
-17 dcache_lock 33 [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70
-18 dcache_lock 1 [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130
+06 &mm->mmap_sem-W: 233 538 18446744073708 22924.27 607243.51 1342 45806 1.71 8595.89 1180582.34
+07 &mm->mmap_sem-R: 205 587 18446744073708 28403.36 731975.00 1940 412426 0.58 187825.45 6307502.88
+08 ---------------
+09 &mm->mmap_sem 487 [<ffffffff8053491f>] do_page_fault+0x466/0x928
+10 &mm->mmap_sem 179 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d
+11 &mm->mmap_sem 279 [<ffffffff80210a57>] sys_mmap+0x75/0xce
+12 &mm->mmap_sem 76 [<ffffffff802a490b>] sys_munmap+0x32/0x59
+13 ---------------
+14 &mm->mmap_sem 270 [<ffffffff80210a57>] sys_mmap+0x75/0xce
+15 &mm->mmap_sem 431 [<ffffffff8053491f>] do_page_fault+0x466/0x928
+16 &mm->mmap_sem 138 [<ffffffff802a490b>] sys_munmap+0x32/0x59
+17 &mm->mmap_sem 145 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d
+18
+19 ...............................................................................................................................................................................................
+20
+21 dcache_lock: 621 623 0.52 118.26 1053.02 6745 91930 0.29 316.29 118423.41
+22 -----------
+23 dcache_lock 179 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54
+24 dcache_lock 113 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb
+25 dcache_lock 99 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44
+26 dcache_lock 104 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a
+27 -----------
+28 dcache_lock 192 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54
+29 dcache_lock 98 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44
+30 dcache_lock 72 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb
+31 dcache_lock 112 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a
This excerpt shows the first two lock class statistics. Line 01 shows the
output version - each time the format changes this will be updated. Line 02-04
-show the header with column descriptions. Lines 05-10 and 13-18 show the actual
+show the header with column descriptions. Lines 05-18 and 20-31 show the actual
statistics. These statistics come in two parts; the actual stats separated by a
-short separator (line 08, 14) from the contention points.
+short separator (line 08, 13) from the contention points.
-The first lock (05-10) is a read/write lock, and shows two lines above the
+The first lock (05-18) is a read/write lock, and shows two lines above the
short separator. The contention points don't match the column descriptors,
-they have two: contentions and [<IP>] symbol.
+they have two: contentions and [<IP>] symbol. The second set of contention
+points are the points we're contending with.
+The integer part of the time values is in us.
View the top contending locks:
+++ /dev/null
-=============================================================================
- MOXA Smartio/Industio Family Device Driver Installation Guide
- for Linux Kernel 2.4.x, 2.6.x
- Copyright (C) 2008, Moxa Inc.
-=============================================================================
-Date: 01/21/2008
-
-Content
-
-1. Introduction
-2. System Requirement
-3. Installation
- 3.1 Hardware installation
- 3.2 Driver files
- 3.3 Device naming convention
- 3.4 Module driver configuration
- 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x.
- 3.6 Custom configuration
- 3.7 Verify driver installation
-4. Utilities
-5. Setserial
-6. Troubleshooting
-
------------------------------------------------------------------------------
-1. Introduction
-
- The Smartio/Industio/UPCI family Linux driver supports following multiport
- boards.
-
- - 2 ports multiport board
- CP-102U, CP-102UL, CP-102UF
- CP-132U-I, CP-132UL,
- CP-132, CP-132I, CP132S, CP-132IS,
- CI-132, CI-132I, CI-132IS,
- (C102H, C102HI, C102HIS, C102P, CP-102, CP-102S)
-
- - 4 ports multiport board
- CP-104EL,
- CP-104UL, CP-104JU,
- CP-134U, CP-134U-I,
- C104H/PCI, C104HS/PCI,
- CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL,
- C104H, C104HS,
- CI-104J, CI-104JS,
- CI-134, CI-134I, CI-134IS,
- (C114HI, CT-114I, C104P)
- POS-104UL,
- CB-114,
- CB-134I
-
- - 8 ports multiport board
- CP-118EL, CP-168EL,
- CP-118U, CP-168U,
- C168H/PCI,
- C168H, C168HS,
- (C168P),
- CB-108
-
- This driver and installation procedure have been developed upon Linux Kernel
- 2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order
- to maintain compatibility, this version has also been properly tested with
- RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem
- occurs, please contact Moxa at support@moxa.com.tw.
-
- In addition to device driver, useful utilities are also provided in this
- version. They are
- - msdiag Diagnostic program for displaying installed Moxa
- Smartio/Industio boards.
- - msmon Monitor program to observe data count and line status signals.
- - msterm A simple terminal program which is useful in testing serial
- ports.
- - io-irq.exe Configuration program to setup ISA boards. Please note that
- this program can only be executed under DOS.
-
- All the drivers and utilities are published in form of source code under
- GNU General Public License in this version. Please refer to GNU General
- Public License announcement in each source code file for more detail.
-
- In Moxa's Web sites, you may always find latest driver at http://web.moxa.com.
-
- This version of driver can be installed as Loadable Module (Module driver)
- or built-in into kernel (Static driver). You may refer to following
- installation procedure for suitable one. Before you install the driver,
- please refer to hardware installation procedure in the User's Manual.
-
- We assume the user should be familiar with following documents.
- - Serial-HOWTO
- - Kernel-HOWTO
-
------------------------------------------------------------------------------
-2. System Requirement
- - Hardware platform: Intel x86 machine
- - Kernel version: 2.4.x or 2.6.x
- - gcc version 2.72 or later
- - Maximum 4 boards can be installed in combination
-
------------------------------------------------------------------------------
-3. Installation
-
- 3.1 Hardware installation
- 3.2 Driver files
- 3.3 Device naming convention
- 3.4 Module driver configuration
- 3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x.
- 3.6 Custom configuration
- 3.7 Verify driver installation
-
-
- 3.1 Hardware installation
-
- There are two types of buses, ISA and PCI, for Smartio/Industio
- family multiport board.
-
- ISA board
- ---------
- You'll have to configure CAP address, I/O address, Interrupt Vector
- as well as IRQ before installing this driver. Please refer to hardware
- installation procedure in User's Manual before proceed any further.
- Please make sure the JP1 is open after the ISA board is set properly.
-
- PCI/UPCI board
- --------------
- You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
- with other ISA devices. Please refer to hardware installation
- procedure in User's Manual in advance.
-
- PCI IRQ Sharing
- -----------
- Each port within the same multiport board shares the same IRQ. Up to
- 4 Moxa Smartio/Industio PCI Family multiport boards can be installed
- together on one system and they can share the same IRQ.
-
-
- 3.2 Driver files
-
- The driver file may be obtained from ftp, CD-ROM or floppy disk. The
- first step, anyway, is to copy driver file "mxser.tgz" into specified
- directory. e.g. /moxa. The execute commands as below.
-
- # cd /
- # mkdir moxa
- # cd /moxa
- # tar xvf /dev/fd0
-
- or
-
- # cd /
- # mkdir moxa
- # cd /moxa
- # cp /mnt/cdrom/<driver directory>/mxser.tgz .
- # tar xvfz mxser.tgz
-
-
- 3.3 Device naming convention
-
- You may find all the driver and utilities files in /moxa/mxser.
- Following installation procedure depends on the model you'd like to
- run the driver. If you prefer module driver, please refer to 3.4.
- If static driver is required, please refer to 3.5.
-
- Dialin and callout port
- -----------------------
- This driver remains traditional serial device properties. There are
- two special file name for each serial port. One is dial-in port
- which is named "ttyMxx". For callout port, the naming convention
- is "cumxx".
-
- Device naming when more than 2 boards installed
- -----------------------------------------------
- Naming convention for each Smartio/Industio multiport board is
- pre-defined as below.
-
- Board Num. Dial-in Port Callout port
- 1st board ttyM0 - ttyM7 cum0 - cum7
- 2nd board ttyM8 - ttyM15 cum8 - cum15
- 3rd board ttyM16 - ttyM23 cum16 - cum23
- 4th board ttyM24 - ttym31 cum24 - cum31
-
-
- !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- Under Kernel 2.6 the cum Device is Obsolete. So use ttyM*
- device instead.
- !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- Board sequence
- --------------
- This driver will activate ISA boards according to the parameter set
- in the driver. After all specified ISA board activated, PCI board
- will be installed in the system automatically driven.
- Therefore the board number is sorted by the CAP address of ISA boards.
- For PCI boards, their sequence will be after ISA boards and C168H/PCI
- has higher priority than C104H/PCI boards.
-
- 3.4 Module driver configuration
- Module driver is easiest way to install. If you prefer static driver
- installation, please skip this paragraph.
-
-
- ------------- Prepare to use the MOXA driver--------------------
- 3.4.1 Create tty device with correct major number
- Before using MOXA driver, your system must have the tty devices
- which are created with driver's major number. We offer one shell
- script "msmknod" to simplify the procedure.
- This step is only needed to be executed once. But you still
- need to do this procedure when:
- a. You change the driver's major number. Please refer the "3.7"
- section.
- b. Your total installed MOXA boards number is changed. Maybe you
- add/delete one MOXA board.
- c. You want to change the tty name. This needs to modify the
- shell script "msmknod"
-
- The procedure is:
- # cd /moxa/mxser/driver
- # ./msmknod
-
- This shell script will require the major number for dial-in
- device and callout device to create tty device. You also need
- to specify the total installed MOXA board number. Default major
- numbers for dial-in device and callout device are 30, 35. If
- you need to change to other number, please refer section "3.7"
- for more detailed procedure.
- Msmknod will delete any special files occupying the same device
- naming.
-
- 3.4.2 Build the MOXA driver and utilities
- Before using the MOXA driver and utilities, you need compile the
- all the source code. This step is only need to be executed once.
- But you still re-compile the source code if you modify the source
- code. For example, if you change the driver's major number (see
- "3.7" section), then you need to do this step again.
-
- Find "Makefile" in /moxa/mxser, then run
-
- # make clean; make install
-
- !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
- For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1:
- # make clean; make installsp1
-
- For Red Hat Enterprise Linux AS4/ES4/WS4:
- # make clean; make installsp2
- !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
-
- The driver files "mxser.o" and utilities will be properly compiled
- and copied to system directories respectively.
-
- ------------- Load MOXA driver--------------------
- 3.4.3 Load the MOXA driver
-
- # modprobe mxser <argument>
-
- will activate the module driver. You may run "lsmod" to check
- if "mxser" is activated. If the MOXA board is ISA board, the
- <argument> is needed. Please refer to section "3.4.5" for more
- information.
-
-
- ------------- Load MOXA driver on boot --------------------
- 3.4.4 For the above description, you may manually execute
- "modprobe mxser" to activate this driver and run
- "rmmod mxser" to remove it.
- However, it's better to have a boot time configuration to
- eliminate manual operation. Boot time configuration can be
- achieved by rc file. We offer one "rc.mxser" file to simplify
- the procedure under "moxa/mxser/driver".
-
- But if you use ISA board, please modify the "modprobe ..." command
- to add the argument (see "3.4.5" section). After modifying the
- rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser"
- manually to make sure the modification is ok. If any error
- encountered, please try to modify again. If the modification is
- completed, follow the below step.
-
- Run following command for setting rc files.
-
- # cd /moxa/mxser/driver
- # cp ./rc.mxser /etc/rc.d
- # cd /etc/rc.d
-
- Check "rc.serial" is existed or not. If "rc.serial" doesn't exist,
- create it by vi, run "chmod 755 rc.serial" to change the permission.
- Add "/etc/rc.d/rc.mxser" in last line,
-
- Reboot and check if moxa.o activated by "lsmod" command.
-
- 3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system,
- you'll have to add parameter to specify CAP address of given
- board while activating "mxser.o". The format for parameters are
- as follows.
-
- modprobe mxser ioaddr=0x???,0x???,0x???,0x???
- | | | |
- | | | +- 4th ISA board
- | | +------ 3rd ISA board
- | +------------ 2nd ISA board
- +------------------- 1st ISA board
-
- 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x
-
- Note: To use static driver, you must install the linux kernel
- source package.
-
- 3.5.1 Backup the built-in driver in the kernel.
- # cd /usr/src/linux/drivers/char
- # mv mxser.c mxser.c.old
-
- For Red Hat 7.x user, you need to create link:
- # cd /usr/src
- # ln -s linux-2.4 linux
-
- 3.5.2 Create link
- # cd /usr/src/linux/drivers/char
- # ln -s /moxa/mxser/driver/mxser.c mxser.c
-
- 3.5.3 Add CAP address list for ISA boards. For PCI boards user,
- please skip this step.
-
- In module mode, the CAP address for ISA board is given by
- parameter. In static driver configuration, you'll have to
- assign it within driver's source code. If you will not
- install any ISA boards, you may skip to next portion.
- The instructions to modify driver source code are as
- below.
- a. # cd /moxa/mxser/driver
- # vi mxser.c
- b. Find the array mxserBoardCAP[] as below.
-
- static int mxserBoardCAP[]
- = {0x00, 0x00, 0x00, 0x00};
-
- c. Change the address within this array using vi. For
- example, to driver 2 ISA boards with CAP address
- 0x280 and 0x180 as 1st and 2nd board. Just to change
- the source code as follows.
-
- static int mxserBoardCAP[]
- = {0x280, 0x180, 0x00, 0x00};
-
- 3.5.4 Setup kernel configuration
-
- Configure the kernel:
-
- # cd /usr/src/linux
- # make menuconfig
-
- You will go into a menu-driven system. Please select [Character
- devices][Non-standard serial port support], enable the [Moxa
- SmartIO support] driver with "[*]" for built-in (not "[M]"), then
- select [Exit] to exit this program.
-
- 3.5.5 Rebuild kernel
- The following are for Linux kernel rebuilding, for your
- reference only.
- For appropriate details, please refer to the Linux document.
-
- a. cd /usr/src/linux
- b. make clean /* take a few minutes */
- c. make dep /* take a few minutes */
- d. make bzImage /* take probably 10-20 minutes */
- e. make install /* copy boot image to correct position */
- f. Please make sure the boot kernel (vmlinuz) is in the
- correct position.
- g. If you use 'lilo' utility, you should check /etc/lilo.conf
- 'image' item specified the path which is the 'vmlinuz' path,
- or you will load wrong (or old) boot kernel image (vmlinuz).
- After checking /etc/lilo.conf, please run "lilo".
-
- Note that if the result of "make bzImage" is ERROR, then you have to
- go back to Linux configuration Setup. Type "make menuconfig" in
- directory /usr/src/linux.
-
-
- 3.5.6 Make tty device and special file
- # cd /moxa/mxser/driver
- # ./msmknod
-
- 3.5.7 Make utility
- # cd /moxa/mxser/utility
- # make clean; make install
-
- 3.5.8 Reboot
-
-
-
- 3.6 Custom configuration
- Although this driver already provides you default configuration, you
- still can change the device name and major number. The instruction to
- change these parameters are shown as below.
-
- Change Device name
- ------------------
- If you'd like to use other device names instead of default naming
- convention, all you have to do is to modify the internal code
- within the shell script "msmknod". First, you have to open "msmknod"
- by vi. Locate each line contains "ttyM" and "cum" and change them
- to the device name you desired. "msmknod" creates the device names
- you need next time executed.
-
- Change Major number
- -------------------
- If major number 30 and 35 had been occupied, you may have to select
- 2 free major numbers for this driver. There are 3 steps to change
- major numbers.
-
- 3.6.1 Find free major numbers
- In /proc/devices, you may find all the major numbers occupied
- in the system. Please select 2 major numbers that are available.
- e.g. 40, 45.
- 3.6.2 Create special files
- Run /moxa/mxser/driver/msmknod to create special files with
- specified major numbers.
- 3.6.3 Modify driver with new major number
- Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
- contains "MXSERMAJOR". Change the content as below.
- #define MXSERMAJOR 40
- #define MXSERCUMAJOR 45
- 3.6.4 Run "make clean; make install" in /moxa/mxser/driver.
-
- 3.7 Verify driver installation
- You may refer to /var/log/messages to check the latest status
- log reported by this driver whenever it's activated.
-
------------------------------------------------------------------------------
-4. Utilities
- There are 3 utilities contained in this driver. They are msdiag, msmon and
- msterm. These 3 utilities are released in form of source code. They should
- be compiled into executable file and copied into /usr/bin.
-
- Before using these utilities, please load driver (refer 3.4 & 3.5) and
- make sure you had run the "msmknod" utility.
-
- msdiag - Diagnostic
- --------------------
- This utility provides the function to display what Moxa Smartio/Industio
- board found by driver in the system.
-
- msmon - Port Monitoring
- -----------------------
- This utility gives the user a quick view about all the MOXA ports'
- activities. One can easily learn each port's total received/transmitted
- (Rx/Tx) character count since the time when the monitoring is started.
- Rx/Tx throughputs per second are also reported in interval basis (e.g.
- the last 5 seconds) and in average basis (since the time the monitoring
- is started). You can reset all ports' count by <HOME> key. <+> <->
- (plus/minus) keys to change the displaying time interval. Press <ENTER>
- on the port, that cursor stay, to view the port's communication
- parameters, signal status, and input/output queue.
-
- msterm - Terminal Emulation
- ---------------------------
- This utility provides data sending and receiving ability of all tty ports,
- especially for MOXA ports. It is quite useful for testing simple
- application, for example, sending AT command to a modem connected to the
- port or used as a terminal for login purpose. Note that this is only a
- dumb terminal emulation without handling full screen operation.
-
------------------------------------------------------------------------------
-5. Setserial
-
- Supported Setserial parameters are listed as below.
-
- uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
- close_delay set the amount of time(in 1/100 of a second) that DTR
- should be kept low while being closed.
- closing_wait set the amount of time(in 1/100 of a second) that the
- serial port should wait for data to be drained while
- being closed, before the receiver is disable.
- spd_hi Use 57.6kb when the application requests 38.4kb.
- spd_vhi Use 115.2kb when the application requests 38.4kb.
- spd_shi Use 230.4kb when the application requests 38.4kb.
- spd_warp Use 460.8kb when the application requests 38.4kb.
- spd_normal Use 38.4kb when the application requests 38.4kb.
- spd_cust Use the custom divisor to set the speed when the
- application requests 38.4kb.
- divisor This option set the custom divison.
- baud_base This option set the base baud rate.
-
------------------------------------------------------------------------------
-6. Troubleshooting
-
- The boot time error messages and solutions are stated as clearly as
- possible. If all the possible solutions fail, please contact our technical
- support team to get more help.
-
-
- Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board
- and after are ignored.
- Solution:
- To avoid this problem, please unplug fifth and after board, because Moxa
- driver supports up to 4 boards.
-
- Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
- Solution:
- Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
- which device causes the situation, please check /proc/interrupts to find
- free IRQ and simply change another free IRQ for Moxa board.
-
- Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
- Solution:
- Each port within the same multiport board shares the same IRQ. Please set
- one IRQ (IRQ doesn't equal to zero) for one Moxa board.
-
- Error msg: No interrupt vector be set for Moxa ISA board(CAP=xxx).
- Solution:
- Moxa ISA board needs an interrupt vector.Please refer to user's manual
- "Hardware Installation" chapter to set interrupt vector.
-
- Error msg: Couldn't install MOXA Smartio/Industio family driver!
- Solution:
- Load Moxa driver fail, the major number may conflict with other devices.
- Please refer to previous section 3.7 to change a free major number for
- Moxa driver.
-
- Error msg: Couldn't install MOXA Smartio/Industio family callout driver!
- Solution:
- Load Moxa callout driver fail, the callout device major number may
- conflict with other devices. Please refer to previous section 3.7 to
- change a free callout device major number for Moxa driver.
-
-
------------------------------------------------------------------------------
-
+++ /dev/null
- Network Block Device (TCP version)
-
- What is it: With this compiled in the kernel (or as a module), Linux
- can use a remote server as one of its block devices. So every time
- the client computer wants to read, e.g., /dev/nb0, it sends a
- request over TCP to the server, which will reply with the data read.
- This can be used for stations with low disk space (or even diskless -
- if you boot from floppy) to borrow disk space from another computer.
- Unlike NFS, it is possible to put any filesystem on it, etc. It should
- even be possible to use NBD as a root filesystem (I've never tried),
- but it requires a user-level program to be in the initrd to start.
- It also allows you to run block-device in user land (making server
- and client physically the same computer, communicating using loopback).
-
- Current state: It currently works. Network block device is stable.
- I originally thought that it was impossible to swap over TCP. It
- turned out not to be true - swapping over TCP now works and seems
- to be deadlock-free, but it requires heavy patches into Linux's
- network layer.
-
- For more information, or to download the nbd-client and nbd-server
- tools, go to http://nbd.sf.net/.
-
- Howto: To setup nbd, you can simply do the following:
-
- First, serve a device or file from a remote server:
-
- nbd-server <port-number> <device-or-file-to-serve-to-client>
-
- e.g.,
- root@server1 # nbd-server 1234 /dev/sdb1
-
- (serves sdb1 partition on TCP port 1234)
-
- Then, on the local (client) system:
-
- nbd-client <server-name-or-IP> <server-port-number> /dev/nb[0-n]
-
- e.g.,
- root@client1 # nbd-client server1 1234 /dev/nb0
-
- (creates the nb0 device on client1)
-
- The nbd kernel module need only be installed on the client
- system, as the nbd-server is completely in userspace. In fact,
- the nbd-server has been successfully ported to other operating
- systems, including Windows.
static void adjust_link(struct net_device *dev);
Next, you need to know the device name of the PHY connected to this device.
- The name will look something like, "phy0:0", where the first number is the
+ The name will look something like, "0:00", where the first number is the
bus id, and the second is the PHY's address on that bus. Typically,
the bus is responsible for making its ID unique.
+++ /dev/null
-
- Linux and parallel port IDE devices
-
-PARIDE v1.03 (c) 1997-8 Grant Guenther <grant@torque.net>
-
-1. Introduction
-
-Owing to the simplicity and near universality of the parallel port interface
-to personal computers, many external devices such as portable hard-disk,
-CD-ROM, LS-120 and tape drives use the parallel port to connect to their
-host computer. While some devices (notably scanners) use ad-hoc methods
-to pass commands and data through the parallel port interface, most
-external devices are actually identical to an internal model, but with
-a parallel-port adapter chip added in. Some of the original parallel port
-adapters were little more than mechanisms for multiplexing a SCSI bus.
-(The Iomega PPA-3 adapter used in the ZIP drives is an example of this
-approach). Most current designs, however, take a different approach.
-The adapter chip reproduces a small ISA or IDE bus in the external device
-and the communication protocol provides operations for reading and writing
-device registers, as well as data block transfer functions. Sometimes,
-the device being addressed via the parallel cable is a standard SCSI
-controller like an NCR 5380. The "ditto" family of external tape
-drives use the ISA replicator to interface a floppy disk controller,
-which is then connected to a floppy-tape mechanism. The vast majority
-of external parallel port devices, however, are now based on standard
-IDE type devices, which require no intermediate controller. If one
-were to open up a parallel port CD-ROM drive, for instance, one would
-find a standard ATAPI CD-ROM drive, a power supply, and a single adapter
-that interconnected a standard PC parallel port cable and a standard
-IDE cable. It is usually possible to exchange the CD-ROM device with
-any other device using the IDE interface.
-
-The document describes the support in Linux for parallel port IDE
-devices. It does not cover parallel port SCSI devices, "ditto" tape
-drives or scanners. Many different devices are supported by the
-parallel port IDE subsystem, including:
-
- MicroSolutions backpack CD-ROM
- MicroSolutions backpack PD/CD
- MicroSolutions backpack hard-drives
- MicroSolutions backpack 8000t tape drive
- SyQuest EZ-135, EZ-230 & SparQ drives
- Avatar Shark
- Imation Superdisk LS-120
- Maxell Superdisk LS-120
- FreeCom Power CD
- Hewlett-Packard 5GB and 8GB tape drives
- Hewlett-Packard 7100 and 7200 CD-RW drives
-
-as well as most of the clone and no-name products on the market.
-
-To support such a wide range of devices, PARIDE, the parallel port IDE
-subsystem, is actually structured in three parts. There is a base
-paride module which provides a registry and some common methods for
-accessing the parallel ports. The second component is a set of
-high-level drivers for each of the different types of supported devices:
-
- pd IDE disk
- pcd ATAPI CD-ROM
- pf ATAPI disk
- pt ATAPI tape
- pg ATAPI generic
-
-(Currently, the pg driver is only used with CD-R drives).
-
-The high-level drivers function according to the relevant standards.
-The third component of PARIDE is a set of low-level protocol drivers
-for each of the parallel port IDE adapter chips. Thanks to the interest
-and encouragement of Linux users from many parts of the world,
-support is available for almost all known adapter protocols:
-
- aten ATEN EH-100 (HK)
- bpck Microsolutions backpack (US)
- comm DataStor (old-type) "commuter" adapter (TW)
- dstr DataStor EP-2000 (TW)
- epat Shuttle EPAT (UK)
- epia Shuttle EPIA (UK)
- fit2 FIT TD-2000 (US)
- fit3 FIT TD-3000 (US)
- friq Freecom IQ cable (DE)
- frpw Freecom Power (DE)
- kbic KingByte KBIC-951A and KBIC-971A (TW)
- ktti KT Technology PHd adapter (SG)
- on20 OnSpec 90c20 (US)
- on26 OnSpec 90c26 (US)
-
-
-2. Using the PARIDE subsystem
-
-While configuring the Linux kernel, you may choose either to build
-the PARIDE drivers into your kernel, or to build them as modules.
-
-In either case, you will need to select "Parallel port IDE device support"
-as well as at least one of the high-level drivers and at least one
-of the parallel port communication protocols. If you do not know
-what kind of parallel port adapter is used in your drive, you could
-begin by checking the file names and any text files on your DOS
-installation floppy. Alternatively, you can look at the markings on
-the adapter chip itself. That's usually sufficient to identify the
-correct device.
-
-You can actually select all the protocol modules, and allow the PARIDE
-subsystem to try them all for you.
-
-For the "brand-name" products listed above, here are the protocol
-and high-level drivers that you would use:
-
- Manufacturer Model Driver Protocol
-
- MicroSolutions CD-ROM pcd bpck
- MicroSolutions PD drive pf bpck
- MicroSolutions hard-drive pd bpck
- MicroSolutions 8000t tape pt bpck
- SyQuest EZ, SparQ pd epat
- Imation Superdisk pf epat
- Maxell Superdisk pf friq
- Avatar Shark pd epat
- FreeCom CD-ROM pcd frpw
- Hewlett-Packard 5GB Tape pt epat
- Hewlett-Packard 7200e (CD) pcd epat
- Hewlett-Packard 7200e (CD-R) pg epat
-
-2.1 Configuring built-in drivers
-
-We recommend that you get to know how the drivers work and how to
-configure them as loadable modules, before attempting to compile a
-kernel with the drivers built-in.
-
-If you built all of your PARIDE support directly into your kernel,
-and you have just a single parallel port IDE device, your kernel should
-locate it automatically for you. If you have more than one device,
-you may need to give some command line options to your bootloader
-(eg: LILO), how to do that is beyond the scope of this document.
-
-The high-level drivers accept a number of command line parameters, all
-of which are documented in the source files in linux/drivers/block/paride.
-By default, each driver will automatically try all parallel ports it
-can find, and all protocol types that have been installed, until it finds
-a parallel port IDE adapter. Once it finds one, the probe stops. So,
-if you have more than one device, you will need to tell the drivers
-how to identify them. This requires specifying the port address, the
-protocol identification number and, for some devices, the drive's
-chain ID. While your system is booting, a number of messages are
-displayed on the console. Like all such messages, they can be
-reviewed with the 'dmesg' command. Among those messages will be
-some lines like:
-
- paride: bpck registered as protocol 0
- paride: epat registered as protocol 1
-
-The numbers will always be the same until you build a new kernel with
-different protocol selections. You should note these numbers as you
-will need them to identify the devices.
-
-If you happen to be using a MicroSolutions backpack device, you will
-also need to know the unit ID number for each drive. This is usually
-the last two digits of the drive's serial number (but read MicroSolutions'
-documentation about this).
-
-As an example, let's assume that you have a MicroSolutions PD/CD drive
-with unit ID number 36 connected to the parallel port at 0x378, a SyQuest
-EZ-135 connected to the chained port on the PD/CD drive and also an
-Imation Superdisk connected to port 0x278. You could give the following
-options on your boot command:
-
- pd.drive0=0x378,1 pf.drive0=0x278,1 pf.drive1=0x378,0,36
-
-In the last option, pf.drive1 configures device /dev/pf1, the 0x378
-is the parallel port base address, the 0 is the protocol registration
-number and 36 is the chain ID.
-
-Please note: while PARIDE will work both with and without the
-PARPORT parallel port sharing system that is included by the
-"Parallel port support" option, PARPORT must be included and enabled
-if you want to use chains of devices on the same parallel port.
-
-2.2 Loading and configuring PARIDE as modules
-
-It is much faster and simpler to get to understand the PARIDE drivers
-if you use them as loadable kernel modules.
-
-Note 1: using these drivers with the "kerneld" automatic module loading
-system is not recommended for beginners, and is not documented here.
-
-Note 2: if you build PARPORT support as a loadable module, PARIDE must
-also be built as loadable modules, and PARPORT must be loaded before the
-PARIDE modules.
-
-To use PARIDE, you must begin by
-
- insmod paride
-
-this loads a base module which provides a registry for the protocols,
-among other tasks.
-
-Then, load as many of the protocol modules as you think you might need.
-As you load each module, it will register the protocols that it supports,
-and print a log message to your kernel log file and your console. For
-example:
-
- # insmod epat
- paride: epat registered as protocol 0
- # insmod kbic
- paride: k951 registered as protocol 1
- paride: k971 registered as protocol 2
-
-Finally, you can load high-level drivers for each kind of device that
-you have connected. By default, each driver will autoprobe for a single
-device, but you can support up to four similar devices by giving their
-individual co-ordinates when you load the driver.
-
-For example, if you had two no-name CD-ROM drives both using the
-KingByte KBIC-951A adapter, one on port 0x378 and the other on 0x3bc
-you could give the following command:
-
- # insmod pcd drive0=0x378,1 drive1=0x3bc,1
-
-For most adapters, giving a port address and protocol number is sufficient,
-but check the source files in linux/drivers/block/paride for more
-information. (Hopefully someone will write some man pages one day !).
-
-As another example, here's what happens when PARPORT is installed, and
-a SyQuest EZ-135 is attached to port 0x378:
-
- # insmod paride
- paride: version 1.0 installed
- # insmod epat
- paride: epat registered as protocol 0
- # insmod pd
- pd: pd version 1.0, major 45, cluster 64, nice 0
- pda: Sharing parport1 at 0x378
- pda: epat 1.0, Shuttle EPAT chip c3 at 0x378, mode 5 (EPP-32), delay 1
- pda: SyQuest EZ135A, 262144 blocks [128M], (512/16/32), removable media
- pda: pda1
-
-Note that the last line is the output from the generic partition table
-scanner - in this case it reports that it has found a disk with one partition.
-
-2.3 Using a PARIDE device
-
-Once the drivers have been loaded, you can access PARIDE devices in the
-same way as their traditional counterparts. You will probably need to
-create the device "special files". Here is a simple script that you can
-cut to a file and execute:
-
-#!/bin/bash
-#
-# mkd -- a script to create the device special files for the PARIDE subsystem
-#
-function mkdev {
- mknod $1 $2 $3 $4 ; chmod 0660 $1 ; chown root:disk $1
-}
-#
-function pd {
- D=$( printf \\$( printf "x%03x" $[ $1 + 97 ] ) )
- mkdev pd$D b 45 $[ $1 * 16 ]
- for P in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- do mkdev pd$D$P b 45 $[ $1 * 16 + $P ]
- done
-}
-#
-cd /dev
-#
-for u in 0 1 2 3 ; do pd $u ; done
-for u in 0 1 2 3 ; do mkdev pcd$u b 46 $u ; done
-for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done
-for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done
-for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done
-for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done
-#
-# end of mkd
-
-With the device files and drivers in place, you can access PARIDE devices
-like any other Linux device. For example, to mount a CD-ROM in pcd0, use:
-
- mount /dev/pcd0 /cdrom
-
-If you have a fresh Avatar Shark cartridge, and the drive is pda, you
-might do something like:
-
- fdisk /dev/pda -- make a new partition table with
- partition 1 of type 83
-
- mke2fs /dev/pda1 -- to build the file system
-
- mkdir /shark -- make a place to mount the disk
-
- mount /dev/pda1 /shark
-
-Devices like the Imation superdisk work in the same way, except that
-they do not have a partition table. For example to make a 120MB
-floppy that you could share with a DOS system:
-
- mkdosfs /dev/pf0
- mount /dev/pf0 /mnt
-
-
-2.4 The pf driver
-
-The pf driver is intended for use with parallel port ATAPI disk
-devices. The most common devices in this category are PD drives
-and LS-120 drives. Traditionally, media for these devices are not
-partitioned. Consequently, the pf driver does not support partitioned
-media. This may be changed in a future version of the driver.
-
-2.5 Using the pt driver
-
-The pt driver for parallel port ATAPI tape drives is a minimal driver.
-It does not yet support many of the standard tape ioctl operations.
-For best performance, a block size of 32KB should be used. You will
-probably want to set the parallel port delay to 0, if you can.
-
-2.6 Using the pg driver
-
-The pg driver can be used in conjunction with the cdrecord program
-to create CD-ROMs. Please get cdrecord version 1.6.1 or later
-from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . To record CD-R media
-your parallel port should ideally be set to EPP mode, and the "port delay"
-should be set to 0. With those settings it is possible to record at 2x
-speed without any buffer underruns. If you cannot get the driver to work
-in EPP mode, try to use "bidirectional" or "PS/2" mode and 1x speeds only.
-
-
-3. Troubleshooting
-
-3.1 Use EPP mode if you can
-
-The most common problems that people report with the PARIDE drivers
-concern the parallel port CMOS settings. At this time, none of the
-PARIDE protocol modules support ECP mode, or any ECP combination modes.
-If you are able to do so, please set your parallel port into EPP mode
-using your CMOS setup procedure.
-
-3.2 Check the port delay
-
-Some parallel ports cannot reliably transfer data at full speed. To
-offset the errors, the PARIDE protocol modules introduce a "port
-delay" between each access to the i/o ports. Each protocol sets
-a default value for this delay. In most cases, the user can override
-the default and set it to 0 - resulting in somewhat higher transfer
-rates. In some rare cases (especially with older 486 systems) the
-default delays are not long enough. if you experience corrupt data
-transfers, or unexpected failures, you may wish to increase the
-port delay. The delay can be programmed using the "driveN" parameters
-to each of the high-level drivers. Please see the notes above, or
-read the comments at the beginning of the driver source files in
-linux/drivers/block/paride.
-
-3.3 Some drives need a printer reset
-
-There appear to be a number of "noname" external drives on the market
-that do not always power up correctly. We have noticed this with some
-drives based on OnSpec and older Freecom adapters. In these rare cases,
-the adapter can often be reinitialised by issuing a "printer reset" on
-the parallel port. As the reset operation is potentially disruptive in
-multiple device environments, the PARIDE drivers will not do it
-automatically. You can however, force a printer reset by doing:
-
- insmod lp reset=1
- rmmod lp
-
-If you have one of these marginal cases, you should probably build
-your paride drivers as modules, and arrange to do the printer reset
-before loading the PARIDE drivers.
-
-3.4 Use the verbose option and dmesg if you need help
-
-While a lot of testing has gone into these drivers to make them work
-as smoothly as possible, problems will arise. If you do have problems,
-please check all the obvious things first: does the drive work in
-DOS with the manufacturer's drivers ? If that doesn't yield any useful
-clues, then please make sure that only one drive is hooked to your system,
-and that either (a) PARPORT is enabled or (b) no other device driver
-is using your parallel port (check in /proc/ioports). Then, load the
-appropriate drivers (you can load several protocol modules if you want)
-as in:
-
- # insmod paride
- # insmod epat
- # insmod bpck
- # insmod kbic
- ...
- # insmod pd verbose=1
-
-(using the correct driver for the type of device you have, of course).
-The verbose=1 parameter will cause the drivers to log a trace of their
-activity as they attempt to locate your drive.
-
-Use 'dmesg' to capture a log of all the PARIDE messages (any messages
-beginning with paride:, a protocol module's name or a driver's name) and
-include that with your bug report. You can submit a bug report in one
-of two ways. Either send it directly to the author of the PARIDE suite,
-by e-mail to grant@torque.net, or join the linux-parport mailing list
-and post your report there.
-
-3.5 For more information or help
-
-You can join the linux-parport mailing list by sending a mail message
-to
- linux-parport-request@torque.net
-
-with the single word
-
- subscribe
-
-in the body of the mail message (not in the subject line). Please be
-sure that your mail program is correctly set up when you do this, as
-the list manager is a robot that will subscribe you using the reply
-address in your mail headers. REMOVE any anti-spam gimmicks you may
-have in your mail headers, when sending mail to the list server.
-
-You might also find some useful information on the linux-parport
-web pages (although they are not always up to date) at
-
- http://www.torque.net/parport/
-
-
+++ /dev/null
-Using the RAM disk block device with Linux
-------------------------------------------
-
-Contents:
-
- 1) Overview
- 2) Kernel Command Line Parameters
- 3) Using "rdev -r"
- 4) An Example of Creating a Compressed RAM Disk
-
-
-1) Overview
------------
-
-The RAM disk driver is a way to use main system memory as a block device. It
-is required for initrd, an initial filesystem used if you need to load modules
-in order to access the root filesystem (see Documentation/initrd.txt). It can
-also be used for a temporary filesystem for crypto work, since the contents
-are erased on reboot.
-
-The RAM disk dynamically grows as more space is required. It does this by using
-RAM from the buffer cache. The driver marks the buffers it is using as dirty
-so that the VM subsystem does not try to reclaim them later.
-
-The RAM disk supports up to 16 RAM disks by default, and can be reconfigured
-to support an unlimited number of RAM disks (at your own risk). Just change
-the configuration symbol BLK_DEV_RAM_COUNT in the Block drivers config menu
-and (re)build the kernel.
-
-To use RAM disk support with your system, run './MAKEDEV ram' from the /dev
-directory. RAM disks are all major number 1, and start with minor number 0
-for /dev/ram0, etc. If used, modern kernels use /dev/ram0 for an initrd.
-
-The new RAM disk also has the ability to load compressed RAM disk images,
-allowing one to squeeze more programs onto an average installation or
-rescue floppy disk.
-
-
-2) Kernel Command Line Parameters
----------------------------------
-
- ramdisk_size=N
- ==============
-
-This parameter tells the RAM disk driver to set up RAM disks of N k size. The
-default is 4096 (4 MB) (8192 (8 MB) on S390).
-
- ramdisk_blocksize=N
- ===================
-
-This parameter tells the RAM disk driver how many bytes to use per block. The
-default is 1024 (BLOCK_SIZE).
-
-
-3) Using "rdev -r"
-------------------
-
-The usage of the word (two bytes) that "rdev -r" sets in the kernel image is
-as follows. The low 11 bits (0 -> 10) specify an offset (in 1 k blocks) of up
-to 2 MB (2^11) of where to find the RAM disk (this used to be the size). Bit
-14 indicates that a RAM disk is to be loaded, and bit 15 indicates whether a
-prompt/wait sequence is to be given before trying to read the RAM disk. Since
-the RAM disk dynamically grows as data is being written into it, a size field
-is not required. Bits 11 to 13 are not currently used and may as well be zero.
-These numbers are no magical secrets, as seen below:
-
-./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK 0x07FF
-./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000
-./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000
-
-Consider a typical two floppy disk setup, where you will have the
-kernel on disk one, and have already put a RAM disk image onto disk #2.
-
-Hence you want to set bits 0 to 13 as 0, meaning that your RAM disk
-starts at an offset of 0 kB from the beginning of the floppy.
-The command line equivalent is: "ramdisk_start=0"
-
-You want bit 14 as one, indicating that a RAM disk is to be loaded.
-The command line equivalent is: "load_ramdisk=1"
-
-You want bit 15 as one, indicating that you want a prompt/keypress
-sequence so that you have a chance to switch floppy disks.
-The command line equivalent is: "prompt_ramdisk=1"
-
-Putting that together gives 2^15 + 2^14 + 0 = 49152 for an rdev word.
-So to create disk one of the set, you would do:
-
- /usr/src/linux# cat arch/i386/boot/zImage > /dev/fd0
- /usr/src/linux# rdev /dev/fd0 /dev/fd0
- /usr/src/linux# rdev -r /dev/fd0 49152
-
-If you make a boot disk that has LILO, then for the above, you would use:
- append = "ramdisk_start=0 load_ramdisk=1 prompt_ramdisk=1"
-Since the default start = 0 and the default prompt = 1, you could use:
- append = "load_ramdisk=1"
-
-
-4) An Example of Creating a Compressed RAM Disk
-----------------------------------------------
-
-To create a RAM disk image, you will need a spare block device to
-construct it on. This can be the RAM disk device itself, or an
-unused disk partition (such as an unmounted swap partition). For this
-example, we will use the RAM disk device, "/dev/ram0".
-
-Note: This technique should not be done on a machine with less than 8 MB
-of RAM. If using a spare disk partition instead of /dev/ram0, then this
-restriction does not apply.
-
-a) Decide on the RAM disk size that you want. Say 2 MB for this example.
- Create it by writing to the RAM disk device. (This step is not currently
- required, but may be in the future.) It is wise to zero out the
- area (esp. for disks) so that maximal compression is achieved for
- the unused blocks of the image that you are about to create.
-
- dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
-
-b) Make a filesystem on it. Say ext2fs for this example.
-
- mke2fs -vm0 /dev/ram0 2048
-
-c) Mount it, copy the files you want to it (eg: /etc/* /dev/* ...)
- and unmount it again.
-
-d) Compress the contents of the RAM disk. The level of compression
- will be approximately 50% of the space used by the files. Unused
- space on the RAM disk will compress to almost nothing.
-
- dd if=/dev/ram0 bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz
-
-e) Put the kernel onto the floppy
-
- dd if=zImage of=/dev/fd0 bs=1k
-
-f) Put the RAM disk image onto the floppy, after the kernel. Use an offset
- that is slightly larger than the kernel, so that you can put another
- (possibly larger) kernel onto the same floppy later without overlapping
- the RAM disk image. An offset of 400 kB for kernels about 350 kB in
- size would be reasonable. Make sure offset+size of ram_image.gz is
- not larger than the total space on your floppy (usually 1440 kB).
-
- dd if=/tmp/ram_image.gz of=/dev/fd0 bs=1k seek=400
-
-g) Use "rdev" to set the boot device, RAM disk offset, prompt flag, etc.
- For prompt_ramdisk=1, load_ramdisk=1, ramdisk_start=400, one would
- have 2^15 + 2^14 + 400 = 49552.
-
- rdev /dev/fd0 /dev/fd0
- rdev -r /dev/fd0 49552
-
-That is it. You now have your boot/root compressed RAM disk floppy. Some
-users may wish to combine steps (d) and (f) by using a pipe.
-
---------------------------------------------------------------------------
- Paul Gortmaker 12/95
-
-Changelog:
-----------
-
-10-22-04 : Updated to reflect changes in command line options, remove
- obsolete references, general cleanup.
- James Nelson (james4765@gmail.com)
-
-
-12-95 : Original Document
+++ /dev/null
-* NOTE - this is an unmaintained driver. The original author cannot be located.
-
-SDL Communications is now SBS Technologies, and does not have any
-information on these ancient ISA cards on their website.
-
-James Nelson <james4765@gmail.com> - 12-12-2004
-
- This is the README for RISCom/8 multi-port serial driver
- (C) 1994-1996 D.Gorodchanin
- See file LICENSE for terms and conditions.
-
-NOTE: English is not my native language.
- I'm sorry for any mistakes in this text.
-
-Misc. notes for RISCom/8 serial driver, in no particular order :)
-
-1) This driver can support up to 4 boards at time.
- Use string "riscom8=0xXXX,0xXXX,0xXXX,0xXXX" at LILO prompt, for
- setting I/O base addresses for boards. If you compile driver
- as module use modprobe options "iobase=0xXXX iobase1=0xXXX iobase2=..."
-
-2) The driver partially supports famous 'setserial' program, you can use almost
- any of its options, excluding port & irq settings.
-
-3) There are some misc. defines at the beginning of riscom8.c, please read the
- comments and try to change some of them in case of problems.
-
-4) I consider the current state of the driver as BETA.
-
-5) SDL Communications WWW page is http://www.sdlcomm.com.
-
-6) You can use the MAKEDEV program to create RISCom/8 /dev/ttyL* entries.
-
-7) Minor numbers for first board are 0-7, for second 8-15, etc.
-
-22 Apr 1996.
+++ /dev/null
-Comtrol(tm) RocketPort(R)/RocketModem(TM) Series
-Device Driver for the Linux Operating System
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-PRODUCT OVERVIEW
-----------------
-
-This driver provides a loadable kernel driver for the Comtrol RocketPort
-and RocketModem PCI boards. These boards provide, 2, 4, 8, 16, or 32
-high-speed serial ports or modems. This driver supports up to a combination
-of four RocketPort or RocketModems boards in one machine simultaneously.
-This file assumes that you are using the RocketPort driver which is
-integrated into the kernel sources.
-
-The driver can also be installed as an external module using the usual
-"make;make install" routine. This external module driver, obtainable
-from the Comtrol website listed below, is useful for updating the driver
-or installing it into kernels which do not have the driver configured
-into them. Installations instructions for the external module
-are in the included README and HW_INSTALL files.
-
-RocketPort ISA and RocketModem II PCI boards currently are only supported by
-this driver in module form.
-
-The RocketPort ISA board requires I/O ports to be configured by the DIP
-switches on the board. See the section "ISA Rocketport Boards" below for
-information on how to set the DIP switches.
-
-You pass the I/O port to the driver using the following module parameters:
-
-board1 : I/O port for the first ISA board
-board2 : I/O port for the second ISA board
-board3 : I/O port for the third ISA board
-board4 : I/O port for the fourth ISA board
-
-There is a set of utilities and scripts provided with the external driver
-( downloadable from http://www.comtrol.com ) that ease the configuration and
-setup of the ISA cards.
-
-The RocketModem II PCI boards require firmware to be loaded into the card
-before it will function. The driver has only been tested as a module for this
-board.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-INSTALLATION PROCEDURES
------------------------
-
-RocketPort/RocketModem PCI cards require no driver configuration, they are
-automatically detected and configured.
-
-The RocketPort driver can be installed as a module (recommended) or built
-into the kernel. This is selected, as for other drivers, through the `make config`
-command from the root of the Linux source tree during the kernel build process.
-
-The RocketPort/RocketModem serial ports installed by this driver are assigned
-device major number 46, and will be named /dev/ttyRx, where x is the port number
-starting at zero (ex. /dev/ttyR0, /devttyR1, ...). If you have multiple cards
-installed in the system, the mapping of port names to serial ports is displayed
-in the system log at /var/log/messages.
-
-If installed as a module, the module must be loaded. This can be done
-manually by entering "modprobe rocket". To have the module loaded automatically
-upon system boot, edit the /etc/modprobe.conf file and add the line
-"alias char-major-46 rocket".
-
-In order to use the ports, their device names (nodes) must be created with mknod.
-This is only required once, the system will retain the names once created. To
-create the RocketPort/RocketModem device names, use the command
-"mknod /dev/ttyRx c 46 x" where x is the port number starting at zero. For example:
-
->mknod /dev/ttyR0 c 46 0
->mknod /dev/ttyR1 c 46 1
->mknod /dev/ttyR2 c 46 2
-
-The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes)
-for you:
-
->/dev/MAKEDEV ttyR
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-ISA Rocketport Boards
----------------------
-
-You must assign and configure the I/O addresses used by the ISA Rocketport
-card before installing and using it. This is done by setting a set of DIP
-switches on the Rocketport board.
-
-
-SETTING THE I/O ADDRESS
------------------------
-
-Before installing RocketPort(R) or RocketPort RA boards, you must find
-a range of I/O addresses for it to use. The first RocketPort card
-requires a 68-byte contiguous block of I/O addresses, starting at one
-of the following: 0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h,
-0x300h, 0x340h, 0x380h. This I/O address must be reflected in the DIP
-switches of *all* of the Rocketport cards.
-
-The second, third, and fourth RocketPort cards require a 64-byte
-contiguous block of I/O addresses, starting at one of the following
-I/O addresses: 0x100h, 0x140h, 0x180h, 0x1C0h, 0x200h, 0x240h, 0x280h,
-0x2C0h, 0x300h, 0x340h, 0x380h, 0x3C0h. The I/O address used by the
-second, third, and fourth Rocketport cards (if present) are set via
-software control. The DIP switch settings for the I/O address must be
-set to the value of the first Rocketport cards.
-
-In order to distinguish each of the card from the others, each card
-must have a unique board ID set on the dip switches. The first
-Rocketport board must be set with the DIP switches corresponding to
-the first board, the second board must be set with the DIP switches
-corresponding to the second board, etc. IMPORTANT: The board ID is
-the only place where the DIP switch settings should differ between the
-various Rocketport boards in a system.
-
-The I/O address range used by any of the RocketPort cards must not
-conflict with any other cards in the system, including other
-RocketPort cards. Below, you will find a list of commonly used I/O
-address ranges which may be in use by other devices in your system.
-On a Linux system, "cat /proc/ioports" will also be helpful in
-identifying what I/O addresses are being used by devices on your
-system.
-
-Remember, the FIRST RocketPort uses 68 I/O addresses. So, if you set it
-for 0x100, it will occupy 0x100 to 0x143. This would mean that you
-CAN NOT set the second, third or fourth board for address 0x140 since
-the first 4 bytes of that range are used by the first board. You would
-need to set the second, third, or fourth board to one of the next available
-blocks such as 0x180.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-RocketPort and RocketPort RA SW1 Settings:
-
- +-------------------------------+
- | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
- +-------+-------+---------------+
- | Unused| Card | I/O Port Block|
- +-------------------------------+
-
-DIP Switches DIP Switches
-7 8 6 5
-=================== ===================
-On On UNUSED, MUST BE ON. On On First Card <==== Default
- On Off Second Card
- Off On Third Card
- Off Off Fourth Card
-
-DIP Switches I/O Address Range
-4 3 2 1 Used by the First Card
-=====================================
-On Off On Off 100-143
-On Off Off On 140-183
-On Off Off Off 180-1C3 <==== Default
-Off On On Off 200-243
-Off On Off On 240-283
-Off On Off Off 280-2C3
-Off Off On Off 300-343
-Off Off Off On 340-383
-Off Off Off Off 380-3C3
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-REPORTING BUGS
---------------
-
-For technical support, please provide the following
-information: Driver version, kernel release, distribution of
-kernel, and type of board you are using. Error messages and log
-printouts port configuration details are especially helpful.
-
-USA
- Phone: (612) 494-4100
- FAX: (612) 494-4199
- email: support@comtrol.com
-
-Comtrol Europe
- Phone: +44 (0) 1 869 323-220
- FAX: +44 (0) 1 869 323-211
- email: support@comtrol.co.uk
-
-Web: http://www.comtrol.com
-FTP: ftp.comtrol.com
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-
--- /dev/null
+00-INDEX
+ - this file.
+README.cycladesZ
+ - info on Cyclades-Z firmware loading.
+computone.txt
+ - info on Computone Intelliport II/Plus Multiport Serial Driver.
+digiepca.txt
+ - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
+hayes-esp.txt
+ - info on using the Hayes ESP serial driver.
+moxa-smartio
+ - file with info on installing/using Moxa multiport serial driver.
+riscom8.txt
+ - notes on using the RISCom/8 multi-port serial driver.
+rocket.txt
+ - info on the Comtrol RocketPort multiport serial driver.
+specialix.txt
+ - info on hardware/driver for specialix IO8+ multiport serial card.
+stallion.txt
+ - info on using the Stallion multiport serial driver.
+sx.txt
+ - info on the Specialix SX/SI multiport serial driver.
+tty.txt
+ - guide to the locking policies of the tty layer.
--- /dev/null
+
+The Cyclades-Z must have firmware loaded onto the card before it will
+operate. This operation should be performed during system startup,
+
+The firmware, loader program and the latest device driver code are
+available from Cyclades at
+ ftp://ftp.cyclades.com/pub/cyclades/cyclades-z/linux/
+
--- /dev/null
+NOTE: This is an unmaintained driver. It is not guaranteed to work due to
+changes made in the tty layer in 2.6. If you wish to take over maintenance of
+this driver, contact Michael Warfield <mhw@wittsend.com>.
+
+Changelog:
+----------
+11-01-2001: Original Document
+
+10-29-2004: Minor misspelling & format fix, update status of driver.
+ James Nelson <james4765@gmail.com>
+
+Computone Intelliport II/Plus Multiport Serial Driver
+-----------------------------------------------------
+
+Release Notes For Linux Kernel 2.2 and higher.
+These notes are for the drivers which have already been integrated into the
+kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
+
+Version: 1.2.14
+Date: 11/01/2001
+Historical Author: Andrew Manison <amanison@america.net>
+Primary Author: Doug McNash
+Support: support@computone.com
+Fixes and Updates: Mike Warfield <mhw@wittsend.com>
+
+This file assumes that you are using the Computone drivers which are
+integrated into the kernel sources. For updating the drivers or installing
+drivers into kernels which do not already have Computone drivers, please
+refer to the instructions in the README.computone file in the driver patch.
+
+
+1. INTRODUCTION
+
+This driver supports the entire family of Intelliport II/Plus controllers
+with the exception of the MicroChannel controllers. It does not support
+products previous to the Intelliport II.
+
+This driver was developed on the v2.0.x Linux tree and has been tested up
+to v2.4.14; it will probably not work with earlier v1.X kernels,.
+
+
+2. QUICK INSTALLATION
+
+Hardware - If you have an ISA card, find a free interrupt and io port.
+ List those in use with `cat /proc/interrupts` and
+ `cat /proc/ioports`. Set the card dip switches to a free
+ address. You may need to configure your BIOS to reserve an
+ irq for an ISA card. PCI and EISA parameters are set
+ automagically. Insert card into computer with the power off
+ before or after drivers installation.
+
+ Note the hardware address from the Computone ISA cards installed into
+ the system. These are required for editing ip2.c or editing
+ /etc/modprobe.conf, or for specification on the modprobe
+ command line.
+
+ Note that the /etc/modules.conf should be used for older (pre-2.6)
+ kernels.
+
+Software -
+
+Module installation:
+
+a) Determine free irq/address to use if any (configure BIOS if need be)
+b) Run "make config" or "make menuconfig" or "make xconfig"
+ Select (m) module for CONFIG_COMPUTONE under character
+ devices. CONFIG_PCI and CONFIG_MODULES also may need to be set.
+c) Set address on ISA cards then:
+ edit /usr/src/linux/drivers/char/ip2.c if needed
+ or
+ edit /etc/modprobe.conf if needed (module).
+ or both to match this setting.
+d) Run "make modules"
+e) Run "make modules_install"
+f) Run "/sbin/depmod -a"
+g) install driver using `modprobe ip2 <options>` (options listed below)
+h) run ip2mkdev (either the script below or the binary version)
+
+
+Kernel installation:
+
+a) Determine free irq/address to use if any (configure BIOS if need be)
+b) Run "make config" or "make menuconfig" or "make xconfig"
+ Select (y) kernel for CONFIG_COMPUTONE under character
+ devices. CONFIG_PCI may need to be set if you have PCI bus.
+c) Set address on ISA cards then:
+ edit /usr/src/linux/drivers/char/ip2.c
+ (Optional - may be specified on kernel command line now)
+d) Run "make zImage" or whatever target you prefer.
+e) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
+f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
+ or copy to a floppy disk and boot from that floppy disk.
+g) Reboot using this kernel
+h) run ip2mkdev (either the script below or the binary version)
+
+Kernel command line options:
+
+When compiling the driver into the kernel, io and irq may be
+compiled into the driver by editing ip2.c and setting the values for
+io and irq in the appropriate array. An alternative is to specify
+a command line parameter to the kernel at boot up.
+
+ ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
+
+Note that this order is very different from the specifications for the
+modload parameters which have separate IRQ and IO specifiers.
+
+The io port also selects PCI (1) and EISA (2) boards.
+
+ io=0 No board
+ io=1 PCI board
+ io=2 EISA board
+ else ISA board io address
+
+You only need to specify the boards which are present.
+
+ Examples:
+
+ 2 PCI boards:
+
+ ip2=1,0,1,0
+
+ 1 ISA board at 0x310 irq 5:
+
+ ip2=0x310,5
+
+This can be added to and "append" option in lilo.conf similar to this:
+
+ append="ip2=1,0,1,0"
+
+
+3. INSTALLATION
+
+Previously, the driver sources were packaged with a set of patch files
+to update the character drivers' makefile and configuration file, and other
+kernel source files. A build script (ip2build) was included which applies
+the patches if needed, and build any utilities needed.
+What you receive may be a single patch file in conventional kernel
+patch format build script. That form can also be applied by
+running patch -p1 < ThePatchFile. Otherwise run ip2build.
+
+The driver can be installed as a module (recommended) or built into the
+kernel. This is selected as for other drivers through the `make config`
+command from the root of the Linux source tree. If the driver is built
+into the kernel you will need to edit the file ip2.c to match the boards
+you are installing. See that file for instructions. If the driver is
+installed as a module the configuration can also be specified on the
+modprobe command line as follows:
+
+ modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4
+
+where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11,
+12,15) and addr1-4 are the base addresses for up to four controllers. If
+the irqs are not specified the driver uses the default in ip2.c (which
+selects polled mode). If no base addresses are specified the defaults in
+ip2.c are used. If you are autoloading the driver module with kerneld or
+kmod the base addresses and interrupt number must also be set in ip2.c
+and recompile or just insert and options line in /etc/modprobe.conf or both.
+The options line is equivalent to the command line and takes precedence over
+what is in ip2.c.
+
+/etc/modprobe.conf sample:
+ options ip2 io=1,0x328 irq=1,10
+ alias char-major-71 ip2
+ alias char-major-72 ip2
+ alias char-major-73 ip2
+
+The equivalent in ip2.c:
+
+static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 };
+static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 };
+
+The equivalent for the kernel command line (in lilo.conf):
+
+ append="ip2=1,1,0x328,10"
+
+
+Note: Both io and irq should be updated to reflect YOUR system. An "io"
+ address of 1 or 2 indicates a PCI or EISA card in the board table.
+ The PCI or EISA irq will be assigned automatically.
+
+Specifying an invalid or in-use irq will default the driver into
+running in polled mode for that card. If all irq entries are 0 then
+all cards will operate in polled mode.
+
+If you select the driver as part of the kernel run :
+
+ make zlilo (or whatever you do to create a bootable kernel)
+
+If you selected a module run :
+
+ make modules && make modules_install
+
+The utility ip2mkdev (see 5 and 7 below) creates all the device nodes
+required by the driver. For a device to be created it must be configured
+in the driver and the board must be installed. Only devices corresponding
+to real IntelliPort II ports are created. With multiple boards and expansion
+boxes this will leave gaps in the sequence of device names. ip2mkdev uses
+Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
+cuf0 - cuf255 for callout devices.
+
+
+4. USING THE DRIVERS
+
+As noted above, the driver implements the ports in accordance with Linux
+conventions, and the devices should be interchangeable with the standard
+serial devices. (This is a key point for problem reporting: please make
+sure that what you are trying do works on the ttySx/cuax ports first; then
+tell us what went wrong with the ip2 ports!)
+
+Higher speeds can be obtained using the setserial utility which remaps
+38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed.
+Intelliport II installations using the PowerPort expansion module can
+use the custom speed setting to select the highest speeds: 153,600 bps,
+230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for
+custom baud rate configuration is fixed at 921,600 for cards/expansion
+modules with ST654's and 115200 for those with Cirrus CD1400's. This
+corresponds to the maximum bit rates those chips are capable.
+For example if the baud base is 921600 and the baud divisor is 18 then
+the custom rate is 921600/18 = 51200 bps. See the setserial man page for
+complete details. Of course if stty accepts the higher rates now you can
+use that as well as the standard ioctls().
+
+
+5. ip2mkdev and assorted utilities...
+
+Several utilities, including the source for a binary ip2mkdev utility are
+available under .../drivers/char/ip2. These can be build by changing to
+that directory and typing "make" after the kernel has be built. If you do
+not wish to compile the binary utilities, the shell script below can be
+cut out and run as "ip2mkdev" to create the necessary device files. To
+use the ip2mkdev script, you must have procfs enabled and the proc file
+system mounted on /proc.
+
+
+6. NOTES
+
+This is a release version of the driver, but it is impossible to test it
+in all configurations of Linux. If there is any anomalous behaviour that
+does not match the standard serial port's behaviour please let us know.
+
+
+7. ip2mkdev shell script
+
+Previously, this script was simply attached here. It is now attached as a
+shar archive to make it easier to extract the script from the documentation.
+To create the ip2mkdev shell script change to a convenient directory (/tmp
+works just fine) and run the following command:
+
+ unshar Documentation/serial/computone.txt
+ (This file)
+
+You should now have a file ip2mkdev in your current working directory with
+permissions set to execute. Running that script with then create the
+necessary devices for the Computone boards, interfaces, and ports which
+are present on you system at the time it is run.
+
+
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2.1).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 2001-10-29 10:32 EST by <mhw@alcove.wittsend.com>.
+# Source directory was `/home2/src/tmp'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 4251 -rwxr-xr-x ip2mkdev
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+ if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+ && ($dir/gettext --version >/dev/null 2>&1)
+ then
+ set `$dir/gettext --version 2>&1`
+ if test "$3" = GNU
+ then
+ gettext_dir=$dir
+ fi
+ fi
+ if test "$locale_dir" = FAILED && test -f $dir/shar \
+ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+ then
+ locale_dir=`$dir/shar --print-text-domain-dir`
+ fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+ echo=echo
+else
+ TEXTDOMAINDIR=$locale_dir
+ export TEXTDOMAINDIR
+ TEXTDOMAIN=sharutils
+ export TEXTDOMAIN
+ echo="$gettext_dir/gettext -s"
+fi
+if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
+ shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
+elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
+ shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
+elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
+ shar_touch='touch -am $3$4$5$6$2 "$8"'
+else
+ shar_touch=:
+ echo
+ $echo 'WARNING: not restoring timestamps. Consider getting and'
+ $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+ echo
+fi
+rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
+#
+if mkdir _sh17581; then
+ $echo 'x -' 'creating lock directory'
+else
+ $echo 'failed to create lock directory'
+ exit 1
+fi
+# ============= ip2mkdev ==============
+if test -f 'ip2mkdev' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
+else
+ $echo 'x -' extracting 'ip2mkdev' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
+#!/bin/sh -
+#
+# ip2mkdev
+#
+# Make or remove devices as needed for Computone Intelliport drivers
+#
+# First rule! If the dev file exists and you need it, don't mess
+# with it. That prevents us from screwing up open ttys, ownership
+# and permissions on a running system!
+#
+# This script will NOT remove devices that no longer exist if their
+# board or interface box has been removed. If you want to get rid
+# of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
+# before running this script. Running this script will then recreate
+# all the valid devices.
+#
+# Michael H. Warfield
+# /\/\|=mhw=|\/\/
+# mhw@wittsend.com
+#
+# Updated 10/29/2000 for version 1.2.13 naming convention
+# under devfs. /\/\|=mhw=|\/\/
+#
+# Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/
+#
+X
+if test -d /dev/ip2 ; then
+# This is devfs mode... We don't do anything except create symlinks
+# from the real devices to the old names!
+X cd /dev
+X echo "Creating symbolic links to devfs devices"
+X for i in `ls ip2` ; do
+X if test ! -L ip2$i ; then
+X # Remove it incase it wasn't a symlink (old device)
+X rm -f ip2$i
+X ln -s ip2/$i ip2$i
+X fi
+X done
+X for i in `( cd tts ; ls F* )` ; do
+X if test ! -L tty$i ; then
+X # Remove it incase it wasn't a symlink (old device)
+X rm -f tty$i
+X ln -s tts/$i tty$i
+X fi
+X done
+X for i in `( cd cua ; ls F* )` ; do
+X DEVNUMBER=`expr $i : 'F\(.*\)'`
+X if test ! -L cuf$DEVNUMBER ; then
+X # Remove it incase it wasn't a symlink (old device)
+X rm -f cuf$DEVNUMBER
+X ln -s cua/$i cuf$DEVNUMBER
+X fi
+X done
+X exit 0
+fi
+X
+if test ! -f /proc/tty/drivers
+then
+X echo "\
+Unable to check driver status.
+Make sure proc file system is mounted."
+X
+X exit 255
+fi
+X
+if test ! -f /proc/tty/driver/ip2
+then
+X echo "\
+Unable to locate ip2 proc file.
+Attempting to load driver"
+X
+X if /sbin/insmod ip2
+X then
+X if test ! -f /proc/tty/driver/ip2
+X then
+X echo "\
+Unable to locate ip2 proc file after loading driver.
+Driver initialization failure or driver version error.
+"
+X exit 255
+X fi
+X else
+X echo "Unable to load ip2 driver."
+X exit 255
+X fi
+fi
+X
+# Ok... So we got the driver loaded and we can locate the procfs files.
+# Next we need our major numbers.
+X
+TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
+CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ ]*[ ]*\([0-9]*\)[ ]*.*/\1/' < /proc/tty/drivers`
+BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ ]*.*/\1/' < /proc/tty/driver/ip2`
+X
+echo "\
+TTYMAJOR = $TTYMAJOR
+CUAMAJOR = $CUAMAJOR
+BRDMAJOR = $BRDMAJOR
+"
+X
+# Ok... Now we should know our major numbers, if appropriate...
+# Now we need our boards and start the device loops.
+X
+grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
+do
+X # The test for blank "type" will catch the stats lead-in lines
+X # if they exist in the file
+X if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
+X then
+X continue
+X fi
+X
+X BOARDNO=`expr "$number" : '\([0-9]\):'`
+X PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
+X MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
+X
+X if test "$BOARDNO" = "" -o "$PORTS" = ""
+X then
+# This may be a bug. We should at least get this much information
+X echo "Unable to process board line"
+X continue
+X fi
+X
+X if test "$MINORS" = ""
+X then
+# Silently skip this one. This board seems to have no boxes
+X continue
+X fi
+X
+X echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
+X
+X if test "$BRDMAJOR" != ""
+X then
+X BRDMINOR=`expr $BOARDNO \* 4`
+X STSMINOR=`expr $BRDMINOR + 1`
+X if test ! -c /dev/ip2ipl$BOARDNO ; then
+X mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
+X fi
+X if test ! -c /dev/ip2stat$BOARDNO ; then
+X mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
+X fi
+X fi
+X
+X if test "$TTYMAJOR" != ""
+X then
+X PORTNO=$BOARDBASE
+X
+X for PORTNO in $MINORS
+X do
+X if test ! -c /dev/ttyF$PORTNO ; then
+X # We got the hardware but no device - make it
+X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
+X fi
+X done
+X fi
+X
+X if test "$CUAMAJOR" != ""
+X then
+X PORTNO=$BOARDBASE
+X
+X for PORTNO in $MINORS
+X do
+X if test ! -c /dev/cuf$PORTNO ; then
+X # We got the hardware but no device - make it
+X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
+X fi
+X done
+X fi
+done
+X
+Xexit 0
+SHAR_EOF
+ (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") &&
+ chmod 0755 'ip2mkdev' ||
+ $echo 'restore of' 'ip2mkdev' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'ip2mkdev:' 'MD5 check failed'
+cb5717134509f38bad9fde6b1f79b4a4 ip2mkdev
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
+ test 4251 -eq "$shar_count" ||
+ $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!"
+ fi
+fi
+rm -fr _sh17581
+exit 0
--- /dev/null
+NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at
+http://www.digi.com for PCI cards. They no longer maintain this driver,
+and have no 2.6 driver for ISA cards.
+
+This driver requires a number of user-space tools. They can be acquired from
+http://www.digi.com, but only works with 2.4 kernels.
+
+
+The Digi Intl. epca driver.
+----------------------------
+The Digi Intl. epca driver for Linux supports the following boards:
+
+Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve
+Digi EISA/Xem, PCI/Xem, PCI/Xr
+
+Limitations:
+------------
+Currently the driver only autoprobes for supported PCI boards.
+
+The Linux MAKEDEV command does not support generating the Digiboard
+Devices. Users executing digiConfig to setup EISA and PC series cards
+will have their device nodes automatically constructed (cud?? for ~CLOCAL,
+and ttyD?? for CLOCAL). Users wishing to boot their board from the LILO
+prompt, or those users booting PCI cards may use buildDIGI to construct
+the necessary nodes.
+
+Notes:
+------
+This driver may be configured via LILO. For users who have already configured
+their driver using digiConfig, configuring from LILO will override previous
+settings. Multiple boards may be configured by issuing multiple LILO command
+lines. For examples see the bottom of this document.
+
+Device names start at 0 and continue up. Beware of this as previous Digi
+drivers started device names with 1.
+
+PCI boards are auto-detected and configured by the driver. PCI boards will
+be allocated device numbers (internally) beginning with the lowest PCI slot
+first. In other words a PCI card in slot 3 will always have higher device
+nodes than a PCI card in slot 1.
+
+LILO config examples:
+---------------------
+Using LILO's APPEND command, a string of comma separated identifiers or
+integers can be used to configure supported boards. The six values in order
+are:
+
+ Enable/Disable this card or Override,
+ Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2),
+ EISA/Xem (3), PC/64Xe (4), PC/Xi (5),
+ Enable/Disable alternate pin arrangement,
+ Number of ports on this card,
+ I/O Port where card is configured (in HEX if using string identifiers),
+ Base of memory window (in HEX if using string identifiers),
+
+NOTE : PCI boards are auto-detected and configured. Do not attempt to
+configure PCI boards with the LILO append command. If you wish to override
+previous configuration data (As set by digiConfig), but you do not wish to
+configure any specific card (Example if there are PCI cards in the system)
+the following override command will accomplish this:
+-> append="digi=2"
+
+Samples:
+ append="digiepca=E,PC/Xe,D,16,200,D0000"
+ or
+ append="digi=1,0,0,16,512,851968"
+
+Supporting Tools:
+-----------------
+Supporting tools include digiDload, digiConfig, buildPCI, and ditty. See
+drivers/char/README.epca for more details. Note,
+this driver REQUIRES that digiDload be executed prior to it being used.
+Failure to do this will result in an ENODEV error.
+
+Documentation:
+--------------
+Complete documentation for this product may be found in the tool package.
+
+Sources of information and support:
+-----------------------------------
+Digi Intl. support site for this product:
+
+-> http://www.digi.com
+
+Acknowledgments:
+----------------
+Much of this work (And even text) was derived from a similar document
+supporting the original public domain DigiBoard driver Copyright (C)
+1994,1995 Troy De Jongh. Many thanks to Christoph Lameter
+(christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored
+and contributed to the original document.
+
+Changelog:
+----------
+10-29-04: Update status of driver, remove dead links in document
+ James Nelson <james4765@gmail.com>
+
+2000 (?) Original Document
--- /dev/null
+HAYES ESP DRIVER VERSION 2.1
+
+A big thanks to the people at Hayes, especially Alan Adamson. Their support
+has enabled me to provide enhancements to the driver.
+
+Please report your experiences with this driver to me (arobinso@nyx.net). I
+am looking for both positive and negative feedback.
+
+*** IMPORTANT CHANGES FOR 2.1 ***
+Support for PIO mode. Five situations will cause PIO mode to be used:
+1) A multiport card is detected. PIO mode will always be used. (8 port cards
+do not support DMA).
+2) The DMA channel is set to an invalid value (anything other than 1 or 3).
+3) The DMA buffer/channel could not be allocated. The port will revert to PIO
+mode until it is reopened.
+4) Less than a specified number of bytes need to be transferred to/from the
+FIFOs. PIO mode will be used for that transfer only.
+5) A port needs to do a DMA transfer and another port is already using the
+DMA channel. PIO mode will be used for that transfer only.
+
+Since the Hayes ESP seems to conflict with other cards (notably sound cards)
+when using DMA, DMA is turned off by default. To use DMA, it must be turned
+on explicitly, either with the "dma=" option described below or with
+setserial. A multiport card can be forced into DMA mode by using setserial;
+however, most multiport cards don't support DMA.
+
+The latest version of setserial allows the enhanced configuration of the ESP
+card to be viewed and modified.
+***
+
+This package contains the files needed to compile a module to support the Hayes
+ESP card. The drivers are basically a modified version of the serial drivers.
+
+Features:
+
+- Uses the enhanced mode of the ESP card, allowing a wider range of
+ interrupts and features than compatibility mode
+- Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs,
+ reducing CPU load
+- Supports primary and secondary ports
+
+
+If the driver is compiled as a module, the IRQs to use can be specified by
+using the irq= option. The format is:
+
+irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380]
+
+The address in brackets is the base address of the card. The IRQ of
+nonexistent cards can be set to 0. If an IRQ of a card that does exist is set
+to 0, the driver will attempt to guess at the correct IRQ. For example, to set
+the IRQ of the card at address 0x300 to 12, the insmod command would be:
+
+insmod esp irq=0,0,0,0,0,0,12,0
+
+The custom divisor can be set by using the divisor= option. The format is the
+same as for the irq= option. Each divisor value is a series of hex digits,
+with each digit representing the divisor to use for a corresponding port. The
+divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value
+will automatically set the spd_cust flag. To calculate the divisor to use for
+a certain baud rate, divide the port's base baud (generally 921600) by the
+desired rate. For example, to set the divisor of the primary port at 0x300 to
+4 and the divisor of the secondary port at 0x308 to 8, the insmod command would
+be:
+
+insmod esp divisor=0,0,0,0,0,0,0x84,0
+
+The dma= option can be used to set the DMA channel. The channel can be either
+1 or 3. Specifying any other value will force the driver to use PIO mode.
+For example, to set the DMA channel to 3, the insmod command would be:
+
+insmod esp dma=3
+
+The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger
+levels. They specify when the ESP card should send an interrupt. Larger
+values will decrease the number of interrupts; however, a value too high may
+result in data loss. Valid values are 1 through 1023, with 768 being the
+default. For example, to set the receive trigger level to 512 bytes and the
+transmit trigger level to 700 bytes, the insmod command would be:
+
+insmod esp rx_trigger=512 tx_trigger=700
+
+The flow_off= and flow_on= options can be used to set the hardware flow off/
+flow on levels. The flow on level must be lower than the flow off level, and
+the flow off level should be higher than rx_trigger. Valid values are 1
+through 1023, with 1016 being the default flow off level and 944 being the
+default flow on level. For example, to set the flow off level to 1000 bytes
+and the flow on level to 935 bytes, the insmod command would be:
+
+insmod esp flow_off=1000 flow_on=935
+
+The rx_timeout= option can be used to set the receive timeout value. This
+value indicates how long after receiving the last character that the ESP card
+should wait before signalling an interrupt. Valid values are 0 though 255,
+with 128 being the default. A value too high will increase latency, and a
+value too low will cause unnecessary interrupts. For example, to set the
+receive timeout to 255, the insmod command would be:
+
+insmod esp rx_timeout=255
+
+The pio_threshold= option sets the threshold (in number of characters) for
+using PIO mode instead of DMA mode. For example, if this value is 32,
+transfers of 32 bytes or less will always use PIO mode.
+
+insmod esp pio_threshold=32
+
+Multiple options can be listed on the insmod command line by separating each
+option with a space. For example:
+
+insmod esp dma=3 trigger=512
+
+The esp module can be automatically loaded when needed. To cause this to
+happen, add the following lines to /etc/modprobe.conf (replacing the last line
+with options for your configuration):
+
+alias char-major-57 esp
+alias char-major-58 esp
+options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0
+
+You may also need to run 'depmod -a'.
+
+Devices must be created manually. To create the devices, note the output from
+the module after it is inserted. The output will appear in the location where
+kernel messages usually appear (usually /var/adm/messages). Create two devices
+for each 'tty' mentioned, one with major of 57 and the other with major of 58.
+The minor number should be the same as the tty number reported. The commands
+would be (replace ? with the tty number):
+
+mknod /dev/ttyP? c 57 ?
+mknod /dev/cup? c 58 ?
+
+For example, if the following line appears:
+
+Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port
+
+...two devices should be created:
+
+mknod /dev/ttyP8 c 57 8
+mknod /dev/cup8 c 58 8
+
+You may need to set the permissions on the devices:
+
+chmod 666 /dev/ttyP*
+chmod 666 /dev/cup*
+
+The ESP module and the serial module should not conflict (they can be used at
+the same time). After the ESP module has been loaded the ports on the ESP card
+will no longer be accessible by the serial driver.
+
+If I/O errors are experienced when accessing the port, check for IRQ and DMA
+conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and
+DMAs currently in use).
+
+Enjoy!
+Andrew J. Robinson <arobinso@nyx.net>
--- /dev/null
+=============================================================================
+ MOXA Smartio/Industio Family Device Driver Installation Guide
+ for Linux Kernel 2.4.x, 2.6.x
+ Copyright (C) 2008, Moxa Inc.
+=============================================================================
+Date: 01/21/2008
+
+Content
+
+1. Introduction
+2. System Requirement
+3. Installation
+ 3.1 Hardware installation
+ 3.2 Driver files
+ 3.3 Device naming convention
+ 3.4 Module driver configuration
+ 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x.
+ 3.6 Custom configuration
+ 3.7 Verify driver installation
+4. Utilities
+5. Setserial
+6. Troubleshooting
+
+-----------------------------------------------------------------------------
+1. Introduction
+
+ The Smartio/Industio/UPCI family Linux driver supports following multiport
+ boards.
+
+ - 2 ports multiport board
+ CP-102U, CP-102UL, CP-102UF
+ CP-132U-I, CP-132UL,
+ CP-132, CP-132I, CP132S, CP-132IS,
+ CI-132, CI-132I, CI-132IS,
+ (C102H, C102HI, C102HIS, C102P, CP-102, CP-102S)
+
+ - 4 ports multiport board
+ CP-104EL,
+ CP-104UL, CP-104JU,
+ CP-134U, CP-134U-I,
+ C104H/PCI, C104HS/PCI,
+ CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL,
+ C104H, C104HS,
+ CI-104J, CI-104JS,
+ CI-134, CI-134I, CI-134IS,
+ (C114HI, CT-114I, C104P)
+ POS-104UL,
+ CB-114,
+ CB-134I
+
+ - 8 ports multiport board
+ CP-118EL, CP-168EL,
+ CP-118U, CP-168U,
+ C168H/PCI,
+ C168H, C168HS,
+ (C168P),
+ CB-108
+
+ This driver and installation procedure have been developed upon Linux Kernel
+ 2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order
+ to maintain compatibility, this version has also been properly tested with
+ RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem
+ occurs, please contact Moxa at support@moxa.com.tw.
+
+ In addition to device driver, useful utilities are also provided in this
+ version. They are
+ - msdiag Diagnostic program for displaying installed Moxa
+ Smartio/Industio boards.
+ - msmon Monitor program to observe data count and line status signals.
+ - msterm A simple terminal program which is useful in testing serial
+ ports.
+ - io-irq.exe Configuration program to setup ISA boards. Please note that
+ this program can only be executed under DOS.
+
+ All the drivers and utilities are published in form of source code under
+ GNU General Public License in this version. Please refer to GNU General
+ Public License announcement in each source code file for more detail.
+
+ In Moxa's Web sites, you may always find latest driver at http://web.moxa.com.
+
+ This version of driver can be installed as Loadable Module (Module driver)
+ or built-in into kernel (Static driver). You may refer to following
+ installation procedure for suitable one. Before you install the driver,
+ please refer to hardware installation procedure in the User's Manual.
+
+ We assume the user should be familiar with following documents.
+ - Serial-HOWTO
+ - Kernel-HOWTO
+
+-----------------------------------------------------------------------------
+2. System Requirement
+ - Hardware platform: Intel x86 machine
+ - Kernel version: 2.4.x or 2.6.x
+ - gcc version 2.72 or later
+ - Maximum 4 boards can be installed in combination
+
+-----------------------------------------------------------------------------
+3. Installation
+
+ 3.1 Hardware installation
+ 3.2 Driver files
+ 3.3 Device naming convention
+ 3.4 Module driver configuration
+ 3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x.
+ 3.6 Custom configuration
+ 3.7 Verify driver installation
+
+
+ 3.1 Hardware installation
+
+ There are two types of buses, ISA and PCI, for Smartio/Industio
+ family multiport board.
+
+ ISA board
+ ---------
+ You'll have to configure CAP address, I/O address, Interrupt Vector
+ as well as IRQ before installing this driver. Please refer to hardware
+ installation procedure in User's Manual before proceed any further.
+ Please make sure the JP1 is open after the ISA board is set properly.
+
+ PCI/UPCI board
+ --------------
+ You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
+ with other ISA devices. Please refer to hardware installation
+ procedure in User's Manual in advance.
+
+ PCI IRQ Sharing
+ -----------
+ Each port within the same multiport board shares the same IRQ. Up to
+ 4 Moxa Smartio/Industio PCI Family multiport boards can be installed
+ together on one system and they can share the same IRQ.
+
+
+ 3.2 Driver files
+
+ The driver file may be obtained from ftp, CD-ROM or floppy disk. The
+ first step, anyway, is to copy driver file "mxser.tgz" into specified
+ directory. e.g. /moxa. The execute commands as below.
+
+ # cd /
+ # mkdir moxa
+ # cd /moxa
+ # tar xvf /dev/fd0
+
+ or
+
+ # cd /
+ # mkdir moxa
+ # cd /moxa
+ # cp /mnt/cdrom/<driver directory>/mxser.tgz .
+ # tar xvfz mxser.tgz
+
+
+ 3.3 Device naming convention
+
+ You may find all the driver and utilities files in /moxa/mxser.
+ Following installation procedure depends on the model you'd like to
+ run the driver. If you prefer module driver, please refer to 3.4.
+ If static driver is required, please refer to 3.5.
+
+ Dialin and callout port
+ -----------------------
+ This driver remains traditional serial device properties. There are
+ two special file name for each serial port. One is dial-in port
+ which is named "ttyMxx". For callout port, the naming convention
+ is "cumxx".
+
+ Device naming when more than 2 boards installed
+ -----------------------------------------------
+ Naming convention for each Smartio/Industio multiport board is
+ pre-defined as below.
+
+ Board Num. Dial-in Port Callout port
+ 1st board ttyM0 - ttyM7 cum0 - cum7
+ 2nd board ttyM8 - ttyM15 cum8 - cum15
+ 3rd board ttyM16 - ttyM23 cum16 - cum23
+ 4th board ttyM24 - ttym31 cum24 - cum31
+
+
+ !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ Under Kernel 2.6 the cum Device is Obsolete. So use ttyM*
+ device instead.
+ !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ Board sequence
+ --------------
+ This driver will activate ISA boards according to the parameter set
+ in the driver. After all specified ISA board activated, PCI board
+ will be installed in the system automatically driven.
+ Therefore the board number is sorted by the CAP address of ISA boards.
+ For PCI boards, their sequence will be after ISA boards and C168H/PCI
+ has higher priority than C104H/PCI boards.
+
+ 3.4 Module driver configuration
+ Module driver is easiest way to install. If you prefer static driver
+ installation, please skip this paragraph.
+
+
+ ------------- Prepare to use the MOXA driver--------------------
+ 3.4.1 Create tty device with correct major number
+ Before using MOXA driver, your system must have the tty devices
+ which are created with driver's major number. We offer one shell
+ script "msmknod" to simplify the procedure.
+ This step is only needed to be executed once. But you still
+ need to do this procedure when:
+ a. You change the driver's major number. Please refer the "3.7"
+ section.
+ b. Your total installed MOXA boards number is changed. Maybe you
+ add/delete one MOXA board.
+ c. You want to change the tty name. This needs to modify the
+ shell script "msmknod"
+
+ The procedure is:
+ # cd /moxa/mxser/driver
+ # ./msmknod
+
+ This shell script will require the major number for dial-in
+ device and callout device to create tty device. You also need
+ to specify the total installed MOXA board number. Default major
+ numbers for dial-in device and callout device are 30, 35. If
+ you need to change to other number, please refer section "3.7"
+ for more detailed procedure.
+ Msmknod will delete any special files occupying the same device
+ naming.
+
+ 3.4.2 Build the MOXA driver and utilities
+ Before using the MOXA driver and utilities, you need compile the
+ all the source code. This step is only need to be executed once.
+ But you still re-compile the source code if you modify the source
+ code. For example, if you change the driver's major number (see
+ "3.7" section), then you need to do this step again.
+
+ Find "Makefile" in /moxa/mxser, then run
+
+ # make clean; make install
+
+ !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
+ For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1:
+ # make clean; make installsp1
+
+ For Red Hat Enterprise Linux AS4/ES4/WS4:
+ # make clean; make installsp2
+ !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
+
+ The driver files "mxser.o" and utilities will be properly compiled
+ and copied to system directories respectively.
+
+ ------------- Load MOXA driver--------------------
+ 3.4.3 Load the MOXA driver
+
+ # modprobe mxser <argument>
+
+ will activate the module driver. You may run "lsmod" to check
+ if "mxser" is activated. If the MOXA board is ISA board, the
+ <argument> is needed. Please refer to section "3.4.5" for more
+ information.
+
+
+ ------------- Load MOXA driver on boot --------------------
+ 3.4.4 For the above description, you may manually execute
+ "modprobe mxser" to activate this driver and run
+ "rmmod mxser" to remove it.
+ However, it's better to have a boot time configuration to
+ eliminate manual operation. Boot time configuration can be
+ achieved by rc file. We offer one "rc.mxser" file to simplify
+ the procedure under "moxa/mxser/driver".
+
+ But if you use ISA board, please modify the "modprobe ..." command
+ to add the argument (see "3.4.5" section). After modifying the
+ rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser"
+ manually to make sure the modification is ok. If any error
+ encountered, please try to modify again. If the modification is
+ completed, follow the below step.
+
+ Run following command for setting rc files.
+
+ # cd /moxa/mxser/driver
+ # cp ./rc.mxser /etc/rc.d
+ # cd /etc/rc.d
+
+ Check "rc.serial" is existed or not. If "rc.serial" doesn't exist,
+ create it by vi, run "chmod 755 rc.serial" to change the permission.
+ Add "/etc/rc.d/rc.mxser" in last line,
+
+ Reboot and check if moxa.o activated by "lsmod" command.
+
+ 3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system,
+ you'll have to add parameter to specify CAP address of given
+ board while activating "mxser.o". The format for parameters are
+ as follows.
+
+ modprobe mxser ioaddr=0x???,0x???,0x???,0x???
+ | | | |
+ | | | +- 4th ISA board
+ | | +------ 3rd ISA board
+ | +------------ 2nd ISA board
+ +------------------- 1st ISA board
+
+ 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x
+
+ Note: To use static driver, you must install the linux kernel
+ source package.
+
+ 3.5.1 Backup the built-in driver in the kernel.
+ # cd /usr/src/linux/drivers/char
+ # mv mxser.c mxser.c.old
+
+ For Red Hat 7.x user, you need to create link:
+ # cd /usr/src
+ # ln -s linux-2.4 linux
+
+ 3.5.2 Create link
+ # cd /usr/src/linux/drivers/char
+ # ln -s /moxa/mxser/driver/mxser.c mxser.c
+
+ 3.5.3 Add CAP address list for ISA boards. For PCI boards user,
+ please skip this step.
+
+ In module mode, the CAP address for ISA board is given by
+ parameter. In static driver configuration, you'll have to
+ assign it within driver's source code. If you will not
+ install any ISA boards, you may skip to next portion.
+ The instructions to modify driver source code are as
+ below.
+ a. # cd /moxa/mxser/driver
+ # vi mxser.c
+ b. Find the array mxserBoardCAP[] as below.
+
+ static int mxserBoardCAP[]
+ = {0x00, 0x00, 0x00, 0x00};
+
+ c. Change the address within this array using vi. For
+ example, to driver 2 ISA boards with CAP address
+ 0x280 and 0x180 as 1st and 2nd board. Just to change
+ the source code as follows.
+
+ static int mxserBoardCAP[]
+ = {0x280, 0x180, 0x00, 0x00};
+
+ 3.5.4 Setup kernel configuration
+
+ Configure the kernel:
+
+ # cd /usr/src/linux
+ # make menuconfig
+
+ You will go into a menu-driven system. Please select [Character
+ devices][Non-standard serial port support], enable the [Moxa
+ SmartIO support] driver with "[*]" for built-in (not "[M]"), then
+ select [Exit] to exit this program.
+
+ 3.5.5 Rebuild kernel
+ The following are for Linux kernel rebuilding, for your
+ reference only.
+ For appropriate details, please refer to the Linux document.
+
+ a. cd /usr/src/linux
+ b. make clean /* take a few minutes */
+ c. make dep /* take a few minutes */
+ d. make bzImage /* take probably 10-20 minutes */
+ e. make install /* copy boot image to correct position */
+ f. Please make sure the boot kernel (vmlinuz) is in the
+ correct position.
+ g. If you use 'lilo' utility, you should check /etc/lilo.conf
+ 'image' item specified the path which is the 'vmlinuz' path,
+ or you will load wrong (or old) boot kernel image (vmlinuz).
+ After checking /etc/lilo.conf, please run "lilo".
+
+ Note that if the result of "make bzImage" is ERROR, then you have to
+ go back to Linux configuration Setup. Type "make menuconfig" in
+ directory /usr/src/linux.
+
+
+ 3.5.6 Make tty device and special file
+ # cd /moxa/mxser/driver
+ # ./msmknod
+
+ 3.5.7 Make utility
+ # cd /moxa/mxser/utility
+ # make clean; make install
+
+ 3.5.8 Reboot
+
+
+
+ 3.6 Custom configuration
+ Although this driver already provides you default configuration, you
+ still can change the device name and major number. The instruction to
+ change these parameters are shown as below.
+
+ Change Device name
+ ------------------
+ If you'd like to use other device names instead of default naming
+ convention, all you have to do is to modify the internal code
+ within the shell script "msmknod". First, you have to open "msmknod"
+ by vi. Locate each line contains "ttyM" and "cum" and change them
+ to the device name you desired. "msmknod" creates the device names
+ you need next time executed.
+
+ Change Major number
+ -------------------
+ If major number 30 and 35 had been occupied, you may have to select
+ 2 free major numbers for this driver. There are 3 steps to change
+ major numbers.
+
+ 3.6.1 Find free major numbers
+ In /proc/devices, you may find all the major numbers occupied
+ in the system. Please select 2 major numbers that are available.
+ e.g. 40, 45.
+ 3.6.2 Create special files
+ Run /moxa/mxser/driver/msmknod to create special files with
+ specified major numbers.
+ 3.6.3 Modify driver with new major number
+ Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
+ contains "MXSERMAJOR". Change the content as below.
+ #define MXSERMAJOR 40
+ #define MXSERCUMAJOR 45
+ 3.6.4 Run "make clean; make install" in /moxa/mxser/driver.
+
+ 3.7 Verify driver installation
+ You may refer to /var/log/messages to check the latest status
+ log reported by this driver whenever it's activated.
+
+-----------------------------------------------------------------------------
+4. Utilities
+ There are 3 utilities contained in this driver. They are msdiag, msmon and
+ msterm. These 3 utilities are released in form of source code. They should
+ be compiled into executable file and copied into /usr/bin.
+
+ Before using these utilities, please load driver (refer 3.4 & 3.5) and
+ make sure you had run the "msmknod" utility.
+
+ msdiag - Diagnostic
+ --------------------
+ This utility provides the function to display what Moxa Smartio/Industio
+ board found by driver in the system.
+
+ msmon - Port Monitoring
+ -----------------------
+ This utility gives the user a quick view about all the MOXA ports'
+ activities. One can easily learn each port's total received/transmitted
+ (Rx/Tx) character count since the time when the monitoring is started.
+ Rx/Tx throughputs per second are also reported in interval basis (e.g.
+ the last 5 seconds) and in average basis (since the time the monitoring
+ is started). You can reset all ports' count by <HOME> key. <+> <->
+ (plus/minus) keys to change the displaying time interval. Press <ENTER>
+ on the port, that cursor stay, to view the port's communication
+ parameters, signal status, and input/output queue.
+
+ msterm - Terminal Emulation
+ ---------------------------
+ This utility provides data sending and receiving ability of all tty ports,
+ especially for MOXA ports. It is quite useful for testing simple
+ application, for example, sending AT command to a modem connected to the
+ port or used as a terminal for login purpose. Note that this is only a
+ dumb terminal emulation without handling full screen operation.
+
+-----------------------------------------------------------------------------
+5. Setserial
+
+ Supported Setserial parameters are listed as below.
+
+ uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
+ close_delay set the amount of time(in 1/100 of a second) that DTR
+ should be kept low while being closed.
+ closing_wait set the amount of time(in 1/100 of a second) that the
+ serial port should wait for data to be drained while
+ being closed, before the receiver is disable.
+ spd_hi Use 57.6kb when the application requests 38.4kb.
+ spd_vhi Use 115.2kb when the application requests 38.4kb.
+ spd_shi Use 230.4kb when the application requests 38.4kb.
+ spd_warp Use 460.8kb when the application requests 38.4kb.
+ spd_normal Use 38.4kb when the application requests 38.4kb.
+ spd_cust Use the custom divisor to set the speed when the
+ application requests 38.4kb.
+ divisor This option set the custom divison.
+ baud_base This option set the base baud rate.
+
+-----------------------------------------------------------------------------
+6. Troubleshooting
+
+ The boot time error messages and solutions are stated as clearly as
+ possible. If all the possible solutions fail, please contact our technical
+ support team to get more help.
+
+
+ Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board
+ and after are ignored.
+ Solution:
+ To avoid this problem, please unplug fifth and after board, because Moxa
+ driver supports up to 4 boards.
+
+ Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
+ Solution:
+ Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
+ which device causes the situation, please check /proc/interrupts to find
+ free IRQ and simply change another free IRQ for Moxa board.
+
+ Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
+ Solution:
+ Each port within the same multiport board shares the same IRQ. Please set
+ one IRQ (IRQ doesn't equal to zero) for one Moxa board.
+
+ Error msg: No interrupt vector be set for Moxa ISA board(CAP=xxx).
+ Solution:
+ Moxa ISA board needs an interrupt vector.Please refer to user's manual
+ "Hardware Installation" chapter to set interrupt vector.
+
+ Error msg: Couldn't install MOXA Smartio/Industio family driver!
+ Solution:
+ Load Moxa driver fail, the major number may conflict with other devices.
+ Please refer to previous section 3.7 to change a free major number for
+ Moxa driver.
+
+ Error msg: Couldn't install MOXA Smartio/Industio family callout driver!
+ Solution:
+ Load Moxa callout driver fail, the callout device major number may
+ conflict with other devices. Please refer to previous section 3.7 to
+ change a free callout device major number for Moxa driver.
+
+
+-----------------------------------------------------------------------------
+
--- /dev/null
+* NOTE - this is an unmaintained driver. The original author cannot be located.
+
+SDL Communications is now SBS Technologies, and does not have any
+information on these ancient ISA cards on their website.
+
+James Nelson <james4765@gmail.com> - 12-12-2004
+
+ This is the README for RISCom/8 multi-port serial driver
+ (C) 1994-1996 D.Gorodchanin
+ See file LICENSE for terms and conditions.
+
+NOTE: English is not my native language.
+ I'm sorry for any mistakes in this text.
+
+Misc. notes for RISCom/8 serial driver, in no particular order :)
+
+1) This driver can support up to 4 boards at time.
+ Use string "riscom8=0xXXX,0xXXX,0xXXX,0xXXX" at LILO prompt, for
+ setting I/O base addresses for boards. If you compile driver
+ as module use modprobe options "iobase=0xXXX iobase1=0xXXX iobase2=..."
+
+2) The driver partially supports famous 'setserial' program, you can use almost
+ any of its options, excluding port & irq settings.
+
+3) There are some misc. defines at the beginning of riscom8.c, please read the
+ comments and try to change some of them in case of problems.
+
+4) I consider the current state of the driver as BETA.
+
+5) SDL Communications WWW page is http://www.sdlcomm.com.
+
+6) You can use the MAKEDEV program to create RISCom/8 /dev/ttyL* entries.
+
+7) Minor numbers for first board are 0-7, for second 8-15, etc.
+
+22 Apr 1996.
--- /dev/null
+Comtrol(tm) RocketPort(R)/RocketModem(TM) Series
+Device Driver for the Linux Operating System
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+PRODUCT OVERVIEW
+----------------
+
+This driver provides a loadable kernel driver for the Comtrol RocketPort
+and RocketModem PCI boards. These boards provide, 2, 4, 8, 16, or 32
+high-speed serial ports or modems. This driver supports up to a combination
+of four RocketPort or RocketModems boards in one machine simultaneously.
+This file assumes that you are using the RocketPort driver which is
+integrated into the kernel sources.
+
+The driver can also be installed as an external module using the usual
+"make;make install" routine. This external module driver, obtainable
+from the Comtrol website listed below, is useful for updating the driver
+or installing it into kernels which do not have the driver configured
+into them. Installations instructions for the external module
+are in the included README and HW_INSTALL files.
+
+RocketPort ISA and RocketModem II PCI boards currently are only supported by
+this driver in module form.
+
+The RocketPort ISA board requires I/O ports to be configured by the DIP
+switches on the board. See the section "ISA Rocketport Boards" below for
+information on how to set the DIP switches.
+
+You pass the I/O port to the driver using the following module parameters:
+
+board1 : I/O port for the first ISA board
+board2 : I/O port for the second ISA board
+board3 : I/O port for the third ISA board
+board4 : I/O port for the fourth ISA board
+
+There is a set of utilities and scripts provided with the external driver
+( downloadable from http://www.comtrol.com ) that ease the configuration and
+setup of the ISA cards.
+
+The RocketModem II PCI boards require firmware to be loaded into the card
+before it will function. The driver has only been tested as a module for this
+board.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+INSTALLATION PROCEDURES
+-----------------------
+
+RocketPort/RocketModem PCI cards require no driver configuration, they are
+automatically detected and configured.
+
+The RocketPort driver can be installed as a module (recommended) or built
+into the kernel. This is selected, as for other drivers, through the `make config`
+command from the root of the Linux source tree during the kernel build process.
+
+The RocketPort/RocketModem serial ports installed by this driver are assigned
+device major number 46, and will be named /dev/ttyRx, where x is the port number
+starting at zero (ex. /dev/ttyR0, /devttyR1, ...). If you have multiple cards
+installed in the system, the mapping of port names to serial ports is displayed
+in the system log at /var/log/messages.
+
+If installed as a module, the module must be loaded. This can be done
+manually by entering "modprobe rocket". To have the module loaded automatically
+upon system boot, edit the /etc/modprobe.conf file and add the line
+"alias char-major-46 rocket".
+
+In order to use the ports, their device names (nodes) must be created with mknod.
+This is only required once, the system will retain the names once created. To
+create the RocketPort/RocketModem device names, use the command
+"mknod /dev/ttyRx c 46 x" where x is the port number starting at zero. For example:
+
+>mknod /dev/ttyR0 c 46 0
+>mknod /dev/ttyR1 c 46 1
+>mknod /dev/ttyR2 c 46 2
+
+The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes)
+for you:
+
+>/dev/MAKEDEV ttyR
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ISA Rocketport Boards
+---------------------
+
+You must assign and configure the I/O addresses used by the ISA Rocketport
+card before installing and using it. This is done by setting a set of DIP
+switches on the Rocketport board.
+
+
+SETTING THE I/O ADDRESS
+-----------------------
+
+Before installing RocketPort(R) or RocketPort RA boards, you must find
+a range of I/O addresses for it to use. The first RocketPort card
+requires a 68-byte contiguous block of I/O addresses, starting at one
+of the following: 0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h,
+0x300h, 0x340h, 0x380h. This I/O address must be reflected in the DIP
+switches of *all* of the Rocketport cards.
+
+The second, third, and fourth RocketPort cards require a 64-byte
+contiguous block of I/O addresses, starting at one of the following
+I/O addresses: 0x100h, 0x140h, 0x180h, 0x1C0h, 0x200h, 0x240h, 0x280h,
+0x2C0h, 0x300h, 0x340h, 0x380h, 0x3C0h. The I/O address used by the
+second, third, and fourth Rocketport cards (if present) are set via
+software control. The DIP switch settings for the I/O address must be
+set to the value of the first Rocketport cards.
+
+In order to distinguish each of the card from the others, each card
+must have a unique board ID set on the dip switches. The first
+Rocketport board must be set with the DIP switches corresponding to
+the first board, the second board must be set with the DIP switches
+corresponding to the second board, etc. IMPORTANT: The board ID is
+the only place where the DIP switch settings should differ between the
+various Rocketport boards in a system.
+
+The I/O address range used by any of the RocketPort cards must not
+conflict with any other cards in the system, including other
+RocketPort cards. Below, you will find a list of commonly used I/O
+address ranges which may be in use by other devices in your system.
+On a Linux system, "cat /proc/ioports" will also be helpful in
+identifying what I/O addresses are being used by devices on your
+system.
+
+Remember, the FIRST RocketPort uses 68 I/O addresses. So, if you set it
+for 0x100, it will occupy 0x100 to 0x143. This would mean that you
+CAN NOT set the second, third or fourth board for address 0x140 since
+the first 4 bytes of that range are used by the first board. You would
+need to set the second, third, or fourth board to one of the next available
+blocks such as 0x180.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+RocketPort and RocketPort RA SW1 Settings:
+
+ +-------------------------------+
+ | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ +-------+-------+---------------+
+ | Unused| Card | I/O Port Block|
+ +-------------------------------+
+
+DIP Switches DIP Switches
+7 8 6 5
+=================== ===================
+On On UNUSED, MUST BE ON. On On First Card <==== Default
+ On Off Second Card
+ Off On Third Card
+ Off Off Fourth Card
+
+DIP Switches I/O Address Range
+4 3 2 1 Used by the First Card
+=====================================
+On Off On Off 100-143
+On Off Off On 140-183
+On Off Off Off 180-1C3 <==== Default
+Off On On Off 200-243
+Off On Off On 240-283
+Off On Off Off 280-2C3
+Off Off On Off 300-343
+Off Off Off On 340-383
+Off Off Off Off 380-3C3
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+REPORTING BUGS
+--------------
+
+For technical support, please provide the following
+information: Driver version, kernel release, distribution of
+kernel, and type of board you are using. Error messages and log
+printouts port configuration details are especially helpful.
+
+USA
+ Phone: (612) 494-4100
+ FAX: (612) 494-4199
+ email: support@comtrol.com
+
+Comtrol Europe
+ Phone: +44 (0) 1 869 323-220
+ FAX: +44 (0) 1 869 323-211
+ email: support@comtrol.co.uk
+
+Web: http://www.comtrol.com
+FTP: ftp.comtrol.com
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+
--- /dev/null
+
+ specialix.txt -- specialix IO8+ multiport serial driver readme.
+
+
+
+ Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
+
+ Specialix pays for the development and support of this driver.
+ Please DO contact io8-linux@specialix.co.uk if you require
+ support.
+
+ This driver was developed in the BitWizard linux device
+ driver service. If you require a linux device driver for your
+ product, please contact devices@BitWizard.nl for a quote.
+
+ This code is firmly based on the riscom/8 serial driver,
+ written by Dmitry Gorodchanin. The specialix IO8+ card
+ programming information was obtained from the CL-CD1865 Data
+ Book, and Specialix document number 6200059: IO8+ Hardware
+ Functional Specification, augmented by document number 6200088:
+ Merak Hardware Functional Specification. (IO8+/PCI is also
+ called Merak)
+
+
+ This program 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.
+
+ 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.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139,
+ USA.
+
+
+Intro
+=====
+
+
+This file contains some random information, that I like to have online
+instead of in a manual that can get lost. Ever misplace your Linux
+kernel sources? And the manual of one of the boards in your computer?
+
+
+Addresses and interrupts
+========================
+
+Address dip switch settings:
+The dip switch sets bits 2-9 of the IO address.
+
+ 9 8 7 6 5 4 3 2
+ +-----------------+
+ 0 | X X X X X X X |
+ | | = IoBase = 0x100
+ 1 | X |
+ +-----------------+ ------ RS232 connectors ---->
+
+ | | |
+ edge connector
+ | | |
+ V V V
+
+Base address 0x100 caused a conflict in one of my computers once. I
+haven't the foggiest why. My Specialix card is now at 0x180. My
+other computer runs just fine with the Specialix card at 0x100....
+The card occupies 4 addresses, but actually only two are really used.
+
+The PCI version doesn't have any dip switches. The BIOS assigns
+an IO address.
+
+The driver now still autoprobes at 0x100, 0x180, 0x250 and 0x260. If
+that causes trouble for you, please report that. I'll remove
+autoprobing then.
+
+The driver will tell the card what IRQ to use, so you don't have to
+change any jumpers to change the IRQ. Just use a command line
+argument (irq=xx) to the insmod program to set the interrupt.
+
+The BIOS assigns the IRQ on the PCI version. You have no say in what
+IRQ to use in that case.
+
+If your specialix cards are not at the default locations, you can use
+the kernel command line argument "specialix=io0,irq0,io1,irq1...".
+Here "io0" is the io address for the first card, and "irq0" is the
+irq line that the first card should use. And so on.
+
+Examples.
+
+You use the driver as a module and have three cards at 0x100, 0x250
+and 0x180. And some way or another you want them detected in that
+order. Moreover irq 12 is taken (e.g. by your PS/2 mouse).
+
+ insmod specialix.o iobase=0x100,0x250,0x180 irq=9,11,15
+
+The same three cards, but now in the kernel would require you to
+add
+
+ specialix=0x100,9,0x250,11,0x180,15
+
+to the command line. This would become
+
+ append="specialix=0x100,9,0x250,11,0x180,15"
+
+in your /etc/lilo.conf file if you use lilo.
+
+The Specialix driver is slightly odd: It allows you to have the second
+or third card detected without having a first card. This has
+advantages and disadvantages. A slot that isn't filled by an ISA card,
+might be filled if a PCI card is detected. Thus if you have an ISA
+card at 0x250 and a PCI card, you would get:
+
+sx0: specialix IO8+ Board at 0x100 not found.
+sx1: specialix IO8+ Board at 0x180 not found.
+sx2: specialix IO8+ board detected at 0x250, IRQ 12, CD1865 Rev. B.
+sx3: specialix IO8+ Board at 0x260 not found.
+sx0: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
+
+This would happen if you don't give any probe hints to the driver.
+If you would specify:
+
+ specialix=0x250,11
+
+you'd get the following messages:
+
+sx0: specialix IO8+ board detected at 0x250, IRQ 11, CD1865 Rev. B.
+sx1: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
+
+ISA probing is aborted after the IO address you gave is exhausted, and
+the PCI card is now detected as the second card. The ISA card is now
+also forced to IRQ11....
+
+
+Baud rates
+==========
+
+The rev 1.2 and below boards use a CL-CD1864. These chips can only
+do 64kbit. The rev 1.3 and newer boards use a CL-CD1865. These chips
+are officially capable of 115k2.
+
+The Specialix card uses a 25MHz crystal (in times two mode, which in
+fact is a divided by two mode). This is not enough to reach the rated
+115k2 on all ports at the same time. With this clock rate you can only
+do 37% of this rate. This means that at 115k2 on all ports you are
+going to lose characters (The chip cannot handle that many incoming
+bits at this clock rate.) (Yes, you read that correctly: there is a
+limit to the number of -=bits=- per second that the chip can handle.)
+
+If you near the "limit" you will first start to see a graceful
+degradation in that the chip cannot keep the transmitter busy at all
+times. However with a central clock this slow, you can also get it to
+miss incoming characters. The driver will print a warning message when
+you are outside the official specs. The messages usually show up in
+the file /var/log/messages .
+
+The specialix card cannot reliably do 115k2. If you use it, you have
+to do "extensive testing" (*) to verify if it actually works.
+
+When "mgetty" communicates with my modem at 115k2 it reports:
+got: +++[0d]ATQ0V1H0[0d][0d][8a]O[cb][0d][8a]
+ ^^^^ ^^^^ ^^^^
+
+The three characters that have the "^^^" under them have suffered a
+bit error in the highest bit. In conclusion: I've tested it, and found
+that it simply DOESN'T work for me. I also suspect that this is also
+caused by the baud rate being just a little bit out of tune.
+
+I upgraded the crystal to 66Mhz on one of my Specialix cards. Works
+great! Contact me for details. (Voids warranty, requires a steady hand
+and more such restrictions....)
+
+
+(*) Cirrus logic CD1864 databook, page 40.
+
+
+Cables for the Specialix IO8+
+=============================
+
+The pinout of the connectors on the IO8+ is:
+
+ pin short direction long name
+ name
+ Pin 1 DCD input Data Carrier Detect
+ Pin 2 RXD input Receive
+ Pin 3 DTR/RTS output Data Terminal Ready/Ready To Send
+ Pin 4 GND - Ground
+ Pin 5 TXD output Transmit
+ Pin 6 CTS input Clear To Send
+
+
+ -- 6 5 4 3 2 1 --
+ | |
+ | |
+ | |
+ | |
+ +----- -----+
+ |__________|
+ clip
+
+ Front view of an RJ12 connector. Cable moves "into" the paper.
+ (the plug is ready to plug into your mouth this way...)
+
+
+ NULL cable. I don't know who is going to use these except for
+ testing purposes, but I tested the cards with this cable. (It
+ took quite a while to figure out, so I'm not going to delete
+ it. So there! :-)
+
+
+ This end goes This end needs
+ straight into the some twists in
+ RJ12 plug. the wiring.
+ IO8+ RJ12 IO8+ RJ12
+ 1 DCD white -
+ - - 1 DCD
+ 2 RXD black 5 TXD
+ 3 DTR/RTS red 6 CTS
+ 4 GND green 4 GND
+ 5 TXD yellow 2 RXD
+ 6 CTS blue 3 DTR/RTS
+
+
+ Same NULL cable, but now sorted on the second column.
+
+ 1 DCD white -
+ - - 1 DCD
+ 5 TXD yellow 2 RXD
+ 6 CTS blue 3 DTR/RTS
+ 4 GND green 4 GND
+ 2 RXD black 5 TXD
+ 3 DTR/RTS red 6 CTS
+
+
+
+ This is a modem cable usable for hardware handshaking:
+ RJ12 DB25 DB9
+ 1 DCD white 8 DCD 1 DCD
+ 2 RXD black 3 RXD 2 RXD
+ 3 DTR/RTS red 4 RTS 7 RTS
+ 4 GND green 7 GND 5 GND
+ 5 TXD yellow 2 TXD 3 TXD
+ 6 CTS blue 5 CTS 8 CTS
+ +---- 6 DSR 6 DSR
+ +---- 20 DTR 4 DTR
+
+ This is a modem cable usable for software handshaking:
+ It allows you to reset the modem using the DTR ioctls.
+ I (REW) have never tested this, "but xxxxxxxxxxxxx
+ says that it works." If you test this, please
+ tell me and I'll fill in your name on the xxx's.
+
+ RJ12 DB25 DB9
+ 1 DCD white 8 DCD 1 DCD
+ 2 RXD black 3 RXD 2 RXD
+ 3 DTR/RTS red 20 DTR 4 DTR
+ 4 GND green 7 GND 5 GND
+ 5 TXD yellow 2 TXD 3 TXD
+ 6 CTS blue 5 CTS 8 CTS
+ +---- 6 DSR 6 DSR
+ +---- 4 RTS 7 RTS
+
+ I bought a 6 wire flat cable. It was colored as indicated.
+ Check that yours is the same before you trust me on this.
+
+
+Hardware handshaking issues.
+============================
+
+The driver can be told to operate in two different ways. The default
+behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
+hardware handshaking is off. It behaves as the RTS hardware
+handshaking signal when hardware handshaking is selected.
+
+When you use this, you have to use the appropriate cable. The
+cable will either be compatible with hardware handshaking or with
+software handshaking. So switching on the fly is not really an
+option.
+
+I actually prefer to use the "specialix.sx_rtscts=1" option.
+This makes the DTR/RTS pin always an RTS pin, and ioctls to
+change DTR are always ignored. I have a cable that is configured
+for this.
+
+
+Ports and devices
+=================
+
+Port 0 is the one furthest from the card-edge connector.
+
+Devices:
+
+You should make the devices as follows:
+
+bash
+cd /dev
+for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+do
+ echo -n "$i "
+ mknod /dev/ttyW$i c 75 $i
+ mknod /dev/cuw$i c 76 $i
+done
+echo ""
+
+If your system doesn't come with these devices preinstalled, bug your
+linux-vendor about this. They have had ample time to get this
+implemented by now.
+
+You cannot have more than 4 boards in one computer. The card only
+supports 4 different interrupts. If you really want this, contact me
+about this and I'll give you a few tips (requires soldering iron)....
+
+If you have enough PCI slots, you can probably use more than 4 PCI
+versions of the card though....
+
+The PCI version of the card cannot adhere to the mechanical part of
+the PCI spec because the 8 serial connectors are simply too large. If
+it doesn't fit in your computer, bring back the card.
+
+
+------------------------------------------------------------------------
+
+
+ Fixed bugs and restrictions:
+ - During initialization, interrupts are blindly turned on.
+ Having a shadow variable would cause an extra memory
+ access on every IO instruction.
+ - The interrupt (on the card) should be disabled when we
+ don't allocate the Linux end of the interrupt. This allows
+ a different driver/card to use it while all ports are not in
+ use..... (a la standard serial port)
+ == An extra _off variant of the sx_in and sx_out macros are
+ now available. They don't set the interrupt enable bit.
+ These are used during initialization. Normal operation uses
+ the old variant which enables the interrupt line.
+ - RTS/DTR issue needs to be implemented according to
+ specialix' spec.
+ I kind of like the "determinism" of the current
+ implementation. Compile time flag?
+ == Ok. Compile time flag! Default is how Specialix likes it.
+ == Now a config time flag! Gets saved in your config file. Neat!
+ - Can you set the IO address from the lilo command line?
+ If you need this, bug me about it, I'll make it.
+ == Hah! No bugging needed. Fixed! :-)
+ - Cirrus logic hasn't gotten back to me yet why the CD1865 can
+ and the CD1864 can't do 115k2. I suspect that this is
+ because the CD1864 is not rated for 33MHz operation.
+ Therefore the CD1864 versions of the card can't do 115k2 on
+ all ports just like the CD1865 versions. The driver does
+ not block 115k2 on CD1864 cards.
+ == I called the Cirrus Logic representative here in Holland.
+ The CD1864 databook is identical to the CD1865 databook,
+ except for an extra warning at the end. Similar Bit errors
+ have been observed in testing at 115k2 on both an 1865 and
+ a 1864 chip. I see no reason why I would prohibit 115k2 on
+ 1864 chips and not do it on 1865 chips. Actually there is
+ reason to prohibit it on BOTH chips. I print a warning.
+ If you use 115k2, you're on your own.
+ - A spiky CD may send spurious HUPs. Also in CLOCAL???
+ -- A fix for this turned out to be counter productive.
+ Different fix? Current behaviour is acceptable?
+ -- Maybe the current implementation is correct. If anybody
+ gets bitten by this, please report, and it will get fixed.
+
+ -- Testing revealed that when in CLOCAL, the problem doesn't
+ occur. As warned for in the CD1865 manual, the chip may
+ send modem intr's on a spike. We could filter those out,
+ but that would be a cludge anyway (You'd still risk getting
+ a spurious HUP when two spikes occur.).....
+
+
+
+ Bugs & restrictions:
+ - This is a difficult card to autoprobe.
+ You have to WRITE to the address register to even
+ read-probe a CD186x register. Disable autodetection?
+ -- Specialix: any suggestions?
+
+
--- /dev/null
+* NOTE - This is an unmaintained driver. Lantronix, which bought Stallion
+technologies, is not active in driver maintenance, and they have no information
+on when or if they will have a 2.6 driver.
+
+James Nelson <james4765@gmail.com> - 12-12-2004
+
+Stallion Multiport Serial Driver Readme
+---------------------------------------
+
+Copyright (C) 1994-1999, Stallion Technologies.
+
+Version: 5.5.1
+Date: 28MAR99
+
+
+
+1. INTRODUCTION
+
+There are two drivers that work with the different families of Stallion
+multiport serial boards. One is for the Stallion smart boards - that is
+EasyIO, EasyConnection 8/32 and EasyConnection 8/64-PCI, the other for
+the true Stallion intelligent multiport boards - EasyConnection 8/64
+(ISA, EISA, MCA), EasyConnection/RA-PCI, ONboard and Brumby.
+
+If you are using any of the Stallion intelligent multiport boards (Brumby,
+ONboard, EasyConnection 8/64 (ISA, EISA, MCA), EasyConnection/RA-PCI) with
+Linux you will need to get the driver utility package. This contains a
+firmware loader and the firmware images necessary to make the devices operate.
+
+The Stallion Technologies ftp site, ftp.stallion.com, will always have
+the latest version of the driver utility package.
+
+ftp://ftp.stallion.com/drivers/ata5/Linux/ata-linux-550.tar.gz
+
+As of the printing of this document the latest version of the driver
+utility package is 5.5.0. If a later version is now available then you
+should use the latest version.
+
+If you are using the EasyIO, EasyConnection 8/32 or EasyConnection 8/64-PCI
+boards then you don't need this package, although it does have a serial stats
+display program.
+
+If you require DIP switch settings, EISA or MCA configuration files, or any
+other information related to Stallion boards then have a look at Stallion's
+web pages at http://www.stallion.com.
+
+
+
+2. INSTALLATION
+
+The drivers can be used as loadable modules or compiled into the kernel.
+You can choose which when doing a "config" on the kernel.
+
+All ISA, EISA and MCA boards that you want to use need to be configured into
+the driver(s). All PCI boards will be automatically detected when you load
+the driver - so they do not need to be entered into the driver(s)
+configuration structure. Note that kernel PCI support is required to use PCI
+boards.
+
+There are two methods of configuring ISA, EISA and MCA boards into the drivers.
+If using the driver as a loadable module then the simplest method is to pass
+the driver configuration as module arguments. The other method is to modify
+the driver source to add configuration lines for each board in use.
+
+If you have pre-built Stallion driver modules then the module argument
+configuration method should be used. A lot of Linux distributions come with
+pre-built driver modules in /lib/modules/X.Y.Z/misc for the kernel in use.
+That makes things pretty simple to get going.
+
+
+2.1 MODULE DRIVER CONFIGURATION:
+
+The simplest configuration for modules is to use the module load arguments
+to configure any ISA, EISA or MCA boards. PCI boards are automatically
+detected, so do not need any additional configuration at all.
+
+If using EasyIO, EasyConnection 8/32 ISA or MCA, or EasyConnection 8/63-PCI
+boards then use the "stallion" driver module, Otherwise if you are using
+an EasyConnection 8/64 ISA, EISA or MCA, EasyConnection/RA-PCI, ONboard,
+Brumby or original Stallion board then use the "istallion" driver module.
+
+Typically to load up the smart board driver use:
+
+ modprobe stallion
+
+This will load the EasyIO and EasyConnection 8/32 driver. It will output a
+message to say that it loaded and print the driver version number. It will
+also print out whether it found the configured boards or not. These messages
+may not appear on the console, but typically are always logged to
+/var/adm/messages or /var/log/syslog files - depending on how the klogd and
+syslogd daemons are setup on your system.
+
+To load the intelligent board driver use:
+
+ modprobe istallion
+
+It will output similar messages to the smart board driver.
+
+If not using an auto-detectable board type (that is a PCI board) then you
+will also need to supply command line arguments to the modprobe command
+when loading the driver. The general form of the configuration argument is
+
+ board?=<name>[,<ioaddr>[,<addr>][,<irq>]]
+
+where:
+
+ board? -- specifies the arbitrary board number of this board,
+ can be in the range 0 to 3.
+
+ name -- textual name of this board. The board name is the common
+ board name, or any "shortened" version of that. The board
+ type number may also be used here.
+
+ ioaddr -- specifies the I/O address of this board. This argument is
+ optional, but should generally be specified.
+
+ addr -- optional second address argument. Some board types require
+ a second I/O address, some require a memory address. The
+ exact meaning of this argument depends on the board type.
+
+ irq -- optional IRQ line used by this board.
+
+Up to 4 board configuration arguments can be specified on the load line.
+Here is some examples:
+
+ modprobe stallion board0=easyio,0x2a0,5
+
+This configures an EasyIO board as board 0 at I/O address 0x2a0 and IRQ 5.
+
+ modprobe istallion board3=ec8/64,0x2c0,0xcc000
+
+This configures an EasyConnection 8/64 ISA as board 3 at I/O address 0x2c0 at
+memory address 0xcc000.
+
+ modprobe stallion board1=ec8/32-at,0x2a0,0x280,10
+
+This configures an EasyConnection 8/32 ISA board at primary I/O address 0x2a0,
+secondary address 0x280 and IRQ 10.
+
+You will probably want to enter this module load and configuration information
+into your system startup scripts so that the drivers are loaded and configured
+on each system boot. Typically the start up script would be something like
+/etc/modprobe.conf.
+
+
+2.2 STATIC DRIVER CONFIGURATION:
+
+For static driver configuration you need to modify the driver source code.
+Entering ISA, EISA and MCA boards into the driver(s) configuration structure
+involves editing the driver(s) source file. It's pretty easy if you follow
+the instructions below. Both drivers can support up to 4 boards. The smart
+card driver (the stallion.c driver) supports any combination of EasyIO and
+EasyConnection 8/32 boards (up to a total of 4). The intelligent driver
+supports any combination of ONboards, Brumbys, Stallions and EasyConnection
+8/64 (ISA and EISA) boards (up to a total of 4).
+
+To set up the driver(s) for the boards that you want to use you need to
+edit the appropriate driver file and add configuration entries.
+
+If using EasyIO or EasyConnection 8/32 ISA or MCA boards,
+ In drivers/char/stallion.c:
+ - find the definition of the stl_brdconf array (of structures)
+ near the top of the file
+ - modify this to match the boards you are going to install
+ (the comments before this structure should help)
+ - save and exit
+
+If using ONboard, Brumby, Stallion or EasyConnection 8/64 (ISA or EISA)
+boards,
+ In drivers/char/istallion.c:
+ - find the definition of the stli_brdconf array (of structures)
+ near the top of the file
+ - modify this to match the boards you are going to install
+ (the comments before this structure should help)
+ - save and exit
+
+Once you have set up the board configurations then you are ready to build
+the kernel or modules.
+
+When the new kernel is booted, or the loadable module loaded then the
+driver will emit some kernel trace messages about whether the configured
+boards were detected or not. Depending on how your system logger is set
+up these may come out on the console, or just be logged to
+/var/adm/messages or /var/log/syslog. You should check the messages to
+confirm that all is well.
+
+
+2.3 SHARING INTERRUPTS
+
+It is possible to share interrupts between multiple EasyIO and
+EasyConnection 8/32 boards in an EISA system. To do this you must be using
+static driver configuration, modifying the driver source code to add driver
+configuration. Then a couple of extra things are required:
+
+1. When entering the board resources into the stallion.c file you need to
+ mark the boards as using level triggered interrupts. Do this by replacing
+ the "0" entry at field position 6 (the last field) in the board
+ configuration structure with a "1". (This is the structure that defines
+ the board type, I/O locations, etc. for each board). All boards that are
+ sharing an interrupt must be set this way, and each board should have the
+ same interrupt number specified here as well. Now build the module or
+ kernel as you would normally.
+
+2. When physically installing the boards into the system you must enter
+ the system EISA configuration utility. You will need to install the EISA
+ configuration files for *all* the EasyIO and EasyConnection 8/32 boards
+ that are sharing interrupts. The Stallion EasyIO and EasyConnection 8/32
+ EISA configuration files required are supplied by Stallion Technologies
+ on the EASY Utilities floppy diskette (usually supplied in the box with
+ the board when purchased. If not, you can pick it up from Stallion's FTP
+ site, ftp.stallion.com). You will need to edit the board resources to
+ choose level triggered interrupts, and make sure to set each board's
+ interrupt to the same IRQ number.
+
+You must complete both the above steps for this to work. When you reboot
+or load the driver your EasyIO and EasyConnection 8/32 boards will be
+sharing interrupts.
+
+
+2.4 USING HIGH SHARED MEMORY
+
+The EasyConnection 8/64-EI, ONboard and Stallion boards are capable of
+using shared memory addresses above the usual 640K - 1Mb range. The ONboard
+ISA and the Stallion boards can be programmed to use memory addresses up to
+16Mb (the ISA bus addressing limit), and the EasyConnection 8/64-EI and
+ONboard/E can be programmed for memory addresses up to 4Gb (the EISA bus
+addressing limit).
+
+The higher than 1Mb memory addresses are fully supported by this driver.
+Just enter the address as you normally would for a lower than 1Mb address
+(in the driver's board configuration structure).
+
+
+
+2.5 TROUBLE SHOOTING
+
+If a board is not found by the driver but is actually in the system then the
+most likely problem is that the I/O address is wrong. Change the module load
+argument for the loadable module form. Or change it in the driver stallion.c
+or istallion.c configuration structure and rebuild the kernel or modules, or
+change it on the board.
+
+On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable, so
+if there is a conflict you may need to change the IRQ used for a board. There
+are no interrupts to worry about for ONboard, Brumby or EasyConnection 8/64
+(ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
+ONboard boards is software programmable, but not on the Brumby boards.
+
+
+
+3. USING THE DRIVERS
+
+3.1 INTELLIGENT DRIVER OPERATION
+
+The intelligent boards also need to have their "firmware" code downloaded
+to them. This is done via a user level application supplied in the driver
+utility package called "stlload". Compile this program wherever you dropped
+the package files, by typing "make". In its simplest form you can then type
+
+ ./stlload -i cdk.sys
+
+in this directory and that will download board 0 (assuming board 0 is an
+EasyConnection 8/64 or EasyConnection/RA board). To download to an
+ONboard, Brumby or Stallion do:
+
+ ./stlload -i 2681.sys
+
+Normally you would want all boards to be downloaded as part of the standard
+system startup. To achieve this, add one of the lines above into the
+/etc/rc.d/rc.S or /etc/rc.d/rc.serial file. To download each board just add
+the "-b <brd-number>" option to the line. You will need to download code for
+every board. You should probably move the stlload program into a system
+directory, such as /usr/sbin. Also, the default location of the cdk.sys image
+file in the stlload down-loader is /usr/lib/stallion. Create that directory
+and put the cdk.sys and 2681.sys files in it. (It's a convenient place to put
+them anyway). As an example your /etc/rc.d/rc.S file might have the
+following lines added to it (if you had 3 boards):
+
+ /usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys
+ /usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys
+ /usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys
+
+The image files cdk.sys and 2681.sys are specific to the board types. The
+cdk.sys will only function correctly on an EasyConnection 8/64 board. Similarly
+the 2681.sys image fill only operate on ONboard, Brumby and Stallion boards.
+If you load the wrong image file into a board it will fail to start up, and
+of course the ports will not be operational!
+
+If you are using the modularized version of the driver you might want to put
+the modprobe calls in the startup script as well (before the download lines
+obviously).
+
+
+3.2 USING THE SERIAL PORTS
+
+Once the driver is installed you will need to setup some device nodes to
+access the serial ports. The simplest method is to use the /dev/MAKEDEV program.
+It will automatically create device entries for Stallion boards. This will
+create the normal serial port devices as /dev/ttyE# where# is the port number
+starting from 0. A bank of 64 minor device numbers is allocated to each board,
+so the first port on the second board is port 64,etc. A set of callout type
+devices may also be created. They are created as the devices /dev/cue# where #
+is the same as for the ttyE devices.
+
+For the most part the Stallion driver tries to emulate the standard PC system
+COM ports and the standard Linux serial driver. The idea is that you should
+be able to use Stallion board ports and COM ports interchangeably without
+modifying anything but the device name. Anything that doesn't work like that
+should be considered a bug in this driver!
+
+If you look at the driver code you will notice that it is fairly closely
+based on the Linux serial driver (linux/drivers/char/serial.c). This is
+intentional, obviously this is the easiest way to emulate its behavior!
+
+Since this driver tries to emulate the standard serial ports as much as
+possible, most system utilities should work as they do for the standard
+COM ports. Most importantly "stty" works as expected and "setserial" can
+also be used (excepting the ability to auto-configure the I/O and IRQ
+addresses of boards). Higher baud rates are supported in the usual fashion
+through setserial or using the CBAUDEX extensions. Note that the EasyIO and
+EasyConnection (all types) support at least 57600 and 115200 baud. The newer
+EasyConnection XP modules and new EasyIO boards support 230400 and 460800
+baud as well. The older boards including ONboard and Brumby support a
+maximum baud rate of 38400.
+
+If you are unfamiliar with how to use serial ports, then get the Serial-HOWTO
+by Greg Hankins. It will explain everything you need to know!
+
+
+
+4. NOTES
+
+You can use both drivers at once if you have a mix of board types installed
+in a system. However to do this you will need to change the major numbers
+used by one of the drivers. Currently both drivers use major numbers 24, 25
+and 28 for their devices. Change one driver to use some other major numbers,
+and then modify the mkdevnods script to make device nodes based on those new
+major numbers. For example, you could change the istallion.c driver to use
+major numbers 60, 61 and 62. You will also need to create device nodes with
+different names for the ports, for example ttyF# and cuf#.
+
+The original Stallion board is no longer supported by Stallion Technologies.
+Although it is known to work with the istallion driver.
+
+Finding a free physical memory address range can be a problem. The older
+boards like the Stallion and ONboard need large areas (64K or even 128K), so
+they can be very difficult to get into a system. If you have 16 Mb of RAM
+then you have no choice but to put them somewhere in the 640K -> 1Mb range.
+ONboards require 64K, so typically 0xd0000 is good, or 0xe0000 on some
+systems. If you have an original Stallion board, "V4.0" or Rev.O, then you
+need a 64K memory address space, so again 0xd0000 and 0xe0000 are good.
+Older Stallion boards are a much bigger problem. They need 128K of address
+space and must be on a 128K boundary. If you don't have a VGA card then
+0xc0000 might be usable - there is really no other place you can put them
+below 1Mb.
+
+Both the ONboard and old Stallion boards can use higher memory addresses as
+well, but you must have less than 16Mb of RAM to be able to use them. Usual
+high memory addresses used include 0xec0000 and 0xf00000.
+
+The Brumby boards only require 16Kb of address space, so you can usually
+squeeze them in somewhere. Common addresses are 0xc8000, 0xcc000, or in
+the 0xd0000 range. EasyConnection 8/64 boards are even better, they only
+require 4Kb of address space, again usually 0xc8000, 0xcc000 or 0xd0000
+are good.
+
+If you are using an EasyConnection 8/64-EI or ONboard/E then usually the
+0xd0000 or 0xe0000 ranges are the best options below 1Mb. If neither of
+them can be used then the high memory support to use the really high address
+ranges is the best option. Typically the 2Gb range is convenient for them,
+and gets them well out of the way.
+
+The ports of the EasyIO-8M board do not have DCD or DTR signals. So these
+ports cannot be used as real modem devices. Generally, when using these
+ports you should only use the cueX devices.
+
+The driver utility package contains a couple of very useful programs. One
+is a serial port statistics collection and display program - very handy
+for solving serial port problems. The other is an extended option setting
+program that works with the intelligent boards.
+
+
+
+5. DISCLAIMER
+
+The information contained in this document is believed to be accurate and
+reliable. However, no responsibility is assumed by Stallion Technologies
+Pty. Ltd. for its use, nor any infringements of patents or other rights
+of third parties resulting from its use. Stallion Technologies reserves
+the right to modify the design of its products and will endeavour to change
+the information in manuals and accompanying documentation accordingly.
+
--- /dev/null
+
+ sx.txt -- specialix SX/SI multiport serial driver readme.
+
+
+
+ Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
+
+ Specialix pays for the development and support of this driver.
+ Please DO contact support@specialix.co.uk if you require
+ support.
+
+ This driver was developed in the BitWizard linux device
+ driver service. If you require a linux device driver for your
+ product, please contact devices@BitWizard.nl for a quote.
+
+ (History)
+ There used to be an SI driver by Simon Allan. This is a complete
+ rewrite from scratch. Just a few lines-of-code have been snatched.
+
+ (Sources)
+ Specialix document number 6210028: SX Host Card and Download Code
+ Software Functional Specification.
+
+ (Copying)
+ This program 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.
+
+ 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.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139,
+ USA.
+
+ (Addendum)
+ I'd appreciate it that if you have fixes, that you send them
+ to me first.
+
+
+Introduction
+============
+
+This file contains some random information, that I like to have online
+instead of in a manual that can get lost. Ever misplace your Linux
+kernel sources? And the manual of one of the boards in your computer?
+
+
+Theory of operation
+===================
+
+An important thing to know is that the driver itself doesn't have the
+firmware for the card. This means that you need the separate package
+"sx_firmware". For now you can get the source at
+
+ ftp://ftp.bitwizard.nl/specialix/sx_firmware_<version>.tgz
+
+The firmware load needs a "misc" device, so you'll need to enable the
+"Support for user misc device modules" in your kernel configuration.
+The misc device needs to be called "/dev/specialix_sxctl". It needs
+misc major 10, and minor number 167 (assigned by HPA). The section
+on creating device files below also creates this device.
+
+After loading the sx.o module into your kernel, the driver will report
+the number of cards detected, but because it doesn't have any
+firmware, it will not be able to determine the number of ports. Only
+when you then run "sx_firmware" will the firmware be downloaded and
+the rest of the driver initialized. At that time the sx_firmware
+program will report the number of ports installed.
+
+In contrast with many other multi port serial cards, some of the data
+structures are only allocated when the card knows the number of ports
+that are connected. This means we won't waste memory for 120 port
+descriptor structures when you only have 8 ports. If you experience
+problems due to this, please report them: I haven't seen any.
+
+
+Interrupts
+==========
+
+A multi port serial card, would generate a horrendous amount of
+interrupts if it would interrupt the CPU for every received
+character. Even more than 10 years ago, the trick not to use
+interrupts but to poll the serial cards was invented.
+
+The SX card allow us to do this two ways. First the card limits its
+own interrupt rate to a rate that won't overwhelm the CPU. Secondly,
+we could forget about the cards interrupt completely and use the
+internal timer for this purpose.
+
+Polling the card can take up to a few percent of your CPU. Using the
+interrupts would be better if you have most of the ports idle. Using
+timer-based polling is better if your card almost always has work to
+do. You save the separate interrupt in that case.
+
+In any case, it doesn't really matter all that much.
+
+The most common problem with interrupts is that for ISA cards in a PCI
+system the BIOS has to be told to configure that interrupt as "legacy
+ISA". Otherwise the card can pull on the interrupt line all it wants
+but the CPU won't see this.
+
+If you can't get the interrupt to work, remember that polling mode is
+more efficient (provided you actually use the card intensively).
+
+
+Allowed Configurations
+======================
+
+Some configurations are disallowed. Even though at a glance they might
+seem to work, they are known to lockup the bus between the host card
+and the device concentrators. You should respect the drivers decision
+not to support certain configurations. It's there for a reason.
+
+Warning: Seriously technical stuff ahead. Executive summary: Don't use
+SX cards except configured at a 64k boundary. Skip the next paragraph.
+
+The SX cards can theoretically be placed at a 32k boundary. So for
+instance you can put an SX card at 0xc8000-0xd7fff. This is not a
+"recommended configuration". ISA cards have to tell the bus controller
+how they like their timing. Due to timing issues they have to do this
+based on which 64k window the address falls into. This means that the
+32k window below and above the SX card have to use exactly the same
+timing as the SX card. That reportedly works for other SX cards. But
+you're still left with two useless 32k windows that should not be used
+by anybody else.
+
+
+Configuring the driver
+======================
+
+PCI cards are always detected. The driver auto-probes for ISA cards at
+some sensible addresses. Please report if the auto-probe causes trouble
+in your system, or when a card isn't detected.
+
+I'm afraid I haven't implemented "kernel command line parameters" yet.
+This means that if the default doesn't work for you, you shouldn't use
+the compiled-into-the-kernel version of the driver. Use a module
+instead. If you convince me that you need this, I'll make it for
+you. Deal?
+
+I'm afraid that the module parameters are a bit clumsy. If you have a
+better idea, please tell me.
+
+You can specify several parameters:
+
+ sx_poll: number of jiffies between timer-based polls.
+
+ Set this to "0" to disable timer based polls.
+ Initialization of cards without a working interrupt
+ will fail.
+
+ Set this to "1" if you want a polling driver.
+ (on Intel: 100 polls per second). If you don't use
+ fast baud rates, you might consider a value like "5".
+ (If you don't know how to do the math, use 1).
+
+ sx_slowpoll: Number of jiffies between timer-based polls.
+ Set this to "100" to poll once a second.
+ This should get the card out of a stall if the driver
+ ever misses an interrupt. I've never seen this happen,
+ and if it does, that's a bug. Tell me.
+
+ sx_maxints: Number of interrupts to request from the card.
+ The card normally limits interrupts to about 100 per
+ second to offload the host CPU. You can increase this
+ number to reduce latency on the card a little.
+ Note that if you give a very high number you can overload
+ your CPU as well as the CPU on the host card. This setting
+ is inaccurate and not recommended for SI cards (But it
+ works).
+
+ sx_irqmask: The mask of allowable IRQs to use. I suggest you set
+ this to 0 (disable IRQs all together) and use polling if
+ the assignment of IRQs becomes problematic. This is defined
+ as the sum of (1 << irq) 's that you want to allow. So
+ sx_irqmask of 8 (1 << 3) specifies that only irq 3 may
+ be used by the SX driver. If you want to specify to the
+ driver: "Either irq 11 or 12 is ok for you to use", then
+ specify (1 << 11) | (1 << 12) = 0x1800 .
+
+ sx_debug: You can enable different sorts of debug traces with this.
+ At "-1" all debugging traces are active. You'll get several
+ times more debugging output than you'll get characters
+ transmitted.
+
+
+Baud rates
+==========
+
+Theoretically new SXDCs should be capable of more than 460k
+baud. However the line drivers usually give up before that. Also the
+CPU on the card may not be able to handle 8 channels going at full
+blast at that speed. Moreover, the buffers are not large enough to
+allow operation with 100 interrupts per second. You'll have to realize
+that the card has a 256 byte buffer, so you'll have to increase the
+number of interrupts per second if you have more than 256*100 bytes
+per second to transmit. If you do any performance testing in this
+area, I'd be glad to hear from you...
+
+(Psst Linux users..... I think the Linux driver is more efficient than
+the driver for other OSes. If you can and want to benchmark them
+against each other, be my guest, and report your findings...... :-)
+
+
+Ports and devices
+=================
+
+Port 0 is the top connector on the module closest to the host
+card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8
+instead of from 0 to 7, as they are numbered by linux. I'm stubborn in
+this: I know for sure that I wouldn't be able to calculate which port
+is which anymore if I would change that....
+
+
+Devices:
+
+You should make the device files as follows:
+
+#!/bin/sh
+# (I recommend that you cut-and-paste this into a file and run that)
+cd /dev
+t=0
+mknod specialix_sxctl c 10 167
+while [ $t -lt 64 ]
+ do
+ echo -n "$t "
+ mknod ttyX$t c 32 $t
+ mknod cux$t c 33 $t
+ t=`expr $t + 1`
+done
+echo ""
+rm /etc/psdevtab
+ps > /dev/null
+
+
+This creates 64 devices. If you have more, increase the constant on
+the line with "while". The devices start at 0, as is customary on
+Linux. Specialix seems to like starting the numbering at 1.
+
+If your system doesn't come with these devices pre-installed, bug your
+linux-vendor about this. They should have these devices
+"pre-installed" before the new millennium. The "ps" stuff at the end
+is to "tell" ps that the new devices exist.
+
+Officially the maximum number of cards per computer is 4. This driver
+however supports as many cards in one machine as you want. You'll run
+out of interrupts after a few, but you can switch to polled operation
+then. At about 256 ports (More than 8 cards), we run out of minor
+device numbers. Sorry. I suggest you buy a second computer.... (Or
+switch to RIO).
+
+------------------------------------------------------------------------
+
+
+ Fixed bugs and restrictions:
+ - Hangup processing.
+ -- Done.
+
+ - the write path in generic_serial (lockup / oops).
+ -- Done (Ugly: not the way I want it. Copied from serial.c).
+
+ - write buffer isn't flushed at close.
+ -- Done. I still seem to lose a few chars at close.
+ Sorry. I think that this is a firmware issue. (-> Specialix)
+
+ - drain hardware before changing termios
+ - Change debug on the fly.
+ - ISA free irq -1. (no firmware loaded).
+ - adding c8000 as a probe address. Added warning.
+ - Add a RAMtest for the RAM on the card.c
+ - Crash when opening a port "way" of the number of allowed ports.
+ (for example opening port 60 when there are only 24 ports attached)
+ - Sometimes the use-count strays a bit. After a few hours of
+ testing the use count is sometimes "3". If you are not like
+ me and can remember what you did to get it that way, I'd
+ appreciate an Email. Possibly fixed. Tell me if anyone still
+ sees this.
+ - TAs don't work right if you don't connect all the modem control
+ signals. SXDCs do. T225 firmware problem -> Specialix.
+ (Mostly fixed now, I think. Tell me if you encounter this!)
+
+ Bugs & restrictions:
+
+ - Arbitrary baud rates. Requires firmware update. (-> Specialix)
+
+ - Low latency (mostly firmware, -> Specialix)
+
+
+
--- /dev/null
+
+ The Lockronomicon
+
+Your guide to the ancient and twisted locking policies of the tty layer and
+the warped logic behind them. Beware all ye who read on.
+
+FIXME: still need to work out the full set of BKL assumptions and document
+them so they can eventually be killed off.
+
+
+Line Discipline
+---------------
+
+Line disciplines are registered with tty_register_ldisc() passing the
+discipline number and the ldisc structure. At the point of registration the
+discipline must be ready to use and it is possible it will get used before
+the call returns success. If the call returns an error then it won't get
+called. Do not re-use ldisc numbers as they are part of the userspace ABI
+and writing over an existing ldisc will cause demons to eat your computer.
+After the return the ldisc data has been copied so you may free your own
+copy of the structure. You must not re-register over the top of the line
+discipline even with the same data or your computer again will be eaten by
+demons.
+
+In order to remove a line discipline call tty_unregister_ldisc().
+In ancient times this always worked. In modern times the function will
+return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
+code manages the module counts this should not usually be a concern.
+
+Heed this warning: the reference count field of the registered copies of the
+tty_ldisc structure in the ldisc table counts the number of lines using this
+discipline. The reference count of the tty_ldisc structure within a tty
+counts the number of active users of the ldisc at this instant. In effect it
+counts the number of threads of execution within an ldisc method (plus those
+about to enter and exit although this detail matters not).
+
+Line Discipline Methods
+-----------------------
+
+TTY side interfaces:
+
+open() - Called when the line discipline is attached to
+ the terminal. No other call into the line
+ discipline for this tty will occur until it
+ completes successfully. Can sleep.
+
+close() - This is called on a terminal when the line
+ discipline is being unplugged. At the point of
+ execution no further users will enter the
+ ldisc code for this tty. Can sleep.
+
+hangup() - Called when the tty line is hung up.
+ The line discipline should cease I/O to the tty.
+ No further calls into the ldisc code will occur.
+ Can sleep.
+
+write() - A process is writing data through the line
+ discipline. Multiple write calls are serialized
+ by the tty layer for the ldisc. May sleep.
+
+flush_buffer() - (optional) May be called at any point between
+ open and close, and instructs the line discipline
+ to empty its input buffer.
+
+chars_in_buffer() - (optional) Report the number of bytes in the input
+ buffer.
+
+set_termios() - (optional) Called on termios structure changes.
+ The caller passes the old termios data and the
+ current data is in the tty. Called under the
+ termios semaphore so allowed to sleep. Serialized
+ against itself only.
+
+read() - Move data from the line discipline to the user.
+ Multiple read calls may occur in parallel and the
+ ldisc must deal with serialization issues. May
+ sleep.
+
+poll() - Check the status for the poll/select calls. Multiple
+ poll calls may occur in parallel. May sleep.
+
+ioctl() - Called when an ioctl is handed to the tty layer
+ that might be for the ldisc. Multiple ioctl calls
+ may occur in parallel. May sleep.
+
+Driver Side Interfaces:
+
+receive_buf() - Hand buffers of bytes from the driver to the ldisc
+ for processing. Semantics currently rather
+ mysterious 8(
+
+write_wakeup() - May be called at any point between open and close.
+ The TTY_DO_WRITE_WAKEUP flag indicates if a call
+ is needed but always races versus calls. Thus the
+ ldisc must be careful about setting order and to
+ handle unexpected calls. Must not sleep.
+
+ The driver is forbidden from calling this directly
+ from the ->write call from the ldisc as the ldisc
+ is permitted to call the driver write method from
+ this function. In such a situation defer it.
+
+
+Driver Access
+
+Line discipline methods can call the following methods of the underlying
+hardware driver through the function pointers within the tty->driver
+structure:
+
+write() Write a block of characters to the tty device.
+ Returns the number of characters accepted. The
+ character buffer passed to this method is already
+ in kernel space.
+
+put_char() Queues a character for writing to the tty device.
+ If there is no room in the queue, the character is
+ ignored.
+
+flush_chars() (Optional) If defined, must be called after
+ queueing characters with put_char() in order to
+ start transmission.
+
+write_room() Returns the numbers of characters the tty driver
+ will accept for queueing to be written.
+
+ioctl() Invoke device specific ioctl.
+ Expects data pointers to refer to userspace.
+ Returns ENOIOCTLCMD for unrecognized ioctl numbers.
+
+set_termios() Notify the tty driver that the device's termios
+ settings have changed. New settings are in
+ tty->termios. Previous settings should be passed in
+ the "old" argument.
+
+ The API is defined such that the driver should return
+ the actual modes selected. This means that the
+ driver function is responsible for modifying any
+ bits in the request it cannot fulfill to indicate
+ the actual modes being used. A device with no
+ hardware capability for change (eg a USB dongle or
+ virtual port) can provide NULL for this method.
+
+throttle() Notify the tty driver that input buffers for the
+ line discipline are close to full, and it should
+ somehow signal that no more characters should be
+ sent to the tty.
+
+unthrottle() Notify the tty driver that characters can now be
+ sent to the tty without fear of overrunning the
+ input buffers of the line disciplines.
+
+stop() Ask the tty driver to stop outputting characters
+ to the tty device.
+
+start() Ask the tty driver to resume sending characters
+ to the tty device.
+
+hangup() Ask the tty driver to hang up the tty device.
+
+break_ctl() (Optional) Ask the tty driver to turn on or off
+ BREAK status on the RS-232 port. If state is -1,
+ then the BREAK status should be turned on; if
+ state is 0, then BREAK should be turned off.
+ If this routine is not implemented, use ioctls
+ TIOCSBRK / TIOCCBRK instead.
+
+wait_until_sent() Waits until the device has written out all of the
+ characters in its transmitter FIFO.
+
+send_xchar() Send a high-priority XON/XOFF character to the device.
+
+
+Flags
+
+Line discipline methods have access to tty->flags field containing the
+following interesting flags:
+
+TTY_THROTTLED Driver input is throttled. The ldisc should call
+ tty->driver->unthrottle() in order to resume
+ reception when it is ready to process more data.
+
+TTY_DO_WRITE_WAKEUP If set, causes the driver to call the ldisc's
+ write_wakeup() method in order to resume
+ transmission when it can accept more data
+ to transmit.
+
+TTY_IO_ERROR If set, causes all subsequent userspace read/write
+ calls on the tty to fail, returning -EIO.
+
+TTY_OTHER_CLOSED Device is a pty and the other side has closed.
+
+TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
+ smaller chunks.
+
+
+Locking
+
+Callers to the line discipline functions from the tty layer are required to
+take line discipline locks. The same is true of calls from the driver side
+but not yet enforced.
+
+Three calls are now provided
+
+ ldisc = tty_ldisc_ref(tty);
+
+takes a handle to the line discipline in the tty and returns it. If no ldisc
+is currently attached or the ldisc is being closed and re-opened at this
+point then NULL is returned. While this handle is held the ldisc will not
+change or go away.
+
+ tty_ldisc_deref(ldisc)
+
+Returns the ldisc reference and allows the ldisc to be closed. Returning the
+reference takes away your right to call the ldisc functions until you take
+a new reference.
+
+ ldisc = tty_ldisc_ref_wait(tty);
+
+Performs the same function as tty_ldisc_ref except that it will wait for an
+ldisc change to complete and then return a reference to the new ldisc.
+
+While these functions are slightly slower than the old code they should have
+minimal impact as most receive logic uses the flip buffers and they only
+need to take a reference when they push bits up through the driver.
+
+A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc
+functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
+fail in this situation if used within these functions. Ldisc and driver
+code calling its own functions must be careful in this case.
+
+
+Driver Interface
+----------------
+
+open() - Called when a device is opened. May sleep
+
+close() - Called when a device is closed. At the point of
+ return from this call the driver must make no
+ further ldisc calls of any kind. May sleep
+
+write() - Called to write bytes to the device. May not
+ sleep. May occur in parallel in special cases.
+ Because this includes panic paths drivers generally
+ shouldn't try and do clever locking here.
+
+put_char() - Stuff a single character onto the queue. The
+ driver is guaranteed following up calls to
+ flush_chars.
+
+flush_chars() - Ask the kernel to write put_char queue
+
+write_room() - Return the number of characters tht can be stuffed
+ into the port buffers without overflow (or less).
+ The ldisc is responsible for being intelligent
+ about multi-threading of write_room/write calls
+
+ioctl() - Called when an ioctl may be for the driver
+
+set_termios() - Called on termios change, serialized against
+ itself by a semaphore. May sleep.
+
+set_ldisc() - Notifier for discipline change. At the point this
+ is done the discipline is not yet usable. Can now
+ sleep (I think)
+
+throttle() - Called by the ldisc to ask the driver to do flow
+ control. Serialization including with unthrottle
+ is the job of the ldisc layer.
+
+unthrottle() - Called by the ldisc to ask the driver to stop flow
+ control.
+
+stop() - Ldisc notifier to the driver to stop output. As with
+ throttle the serializations with start() are down
+ to the ldisc layer.
+
+start() - Ldisc notifier to the driver to start output.
+
+hangup() - Ask the tty driver to cause a hangup initiated
+ from the host side. [Can sleep ??]
+
+break_ctl() - Send RS232 break. Can sleep. Can get called in
+ parallel, driver must serialize (for now), and
+ with write calls.
+
+wait_until_sent() - Wait for characters to exit the hardware queue
+ of the driver. Can sleep
+
+send_xchar() - Send XON/XOFF and if possible jump the queue with
+ it in order to get fast flow control responses.
+ Cannot sleep ??
+
+++ /dev/null
-
- specialix.txt -- specialix IO8+ multiport serial driver readme.
-
-
-
- Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
-
- Specialix pays for the development and support of this driver.
- Please DO contact io8-linux@specialix.co.uk if you require
- support.
-
- This driver was developed in the BitWizard linux device
- driver service. If you require a linux device driver for your
- product, please contact devices@BitWizard.nl for a quote.
-
- This code is firmly based on the riscom/8 serial driver,
- written by Dmitry Gorodchanin. The specialix IO8+ card
- programming information was obtained from the CL-CD1865 Data
- Book, and Specialix document number 6200059: IO8+ Hardware
- Functional Specification, augmented by document number 6200088:
- Merak Hardware Functional Specification. (IO8+/PCI is also
- called Merak)
-
-
- This program 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.
-
- 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.
-
- 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., 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
-
-Intro
-=====
-
-
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources? And the manual of one of the boards in your computer?
-
-
-Addresses and interrupts
-========================
-
-Address dip switch settings:
-The dip switch sets bits 2-9 of the IO address.
-
- 9 8 7 6 5 4 3 2
- +-----------------+
- 0 | X X X X X X X |
- | | = IoBase = 0x100
- 1 | X |
- +-----------------+ ------ RS232 connectors ---->
-
- | | |
- edge connector
- | | |
- V V V
-
-Base address 0x100 caused a conflict in one of my computers once. I
-haven't the foggiest why. My Specialix card is now at 0x180. My
-other computer runs just fine with the Specialix card at 0x100....
-The card occupies 4 addresses, but actually only two are really used.
-
-The PCI version doesn't have any dip switches. The BIOS assigns
-an IO address.
-
-The driver now still autoprobes at 0x100, 0x180, 0x250 and 0x260. If
-that causes trouble for you, please report that. I'll remove
-autoprobing then.
-
-The driver will tell the card what IRQ to use, so you don't have to
-change any jumpers to change the IRQ. Just use a command line
-argument (irq=xx) to the insmod program to set the interrupt.
-
-The BIOS assigns the IRQ on the PCI version. You have no say in what
-IRQ to use in that case.
-
-If your specialix cards are not at the default locations, you can use
-the kernel command line argument "specialix=io0,irq0,io1,irq1...".
-Here "io0" is the io address for the first card, and "irq0" is the
-irq line that the first card should use. And so on.
-
-Examples.
-
-You use the driver as a module and have three cards at 0x100, 0x250
-and 0x180. And some way or another you want them detected in that
-order. Moreover irq 12 is taken (e.g. by your PS/2 mouse).
-
- insmod specialix.o iobase=0x100,0x250,0x180 irq=9,11,15
-
-The same three cards, but now in the kernel would require you to
-add
-
- specialix=0x100,9,0x250,11,0x180,15
-
-to the command line. This would become
-
- append="specialix=0x100,9,0x250,11,0x180,15"
-
-in your /etc/lilo.conf file if you use lilo.
-
-The Specialix driver is slightly odd: It allows you to have the second
-or third card detected without having a first card. This has
-advantages and disadvantages. A slot that isn't filled by an ISA card,
-might be filled if a PCI card is detected. Thus if you have an ISA
-card at 0x250 and a PCI card, you would get:
-
-sx0: specialix IO8+ Board at 0x100 not found.
-sx1: specialix IO8+ Board at 0x180 not found.
-sx2: specialix IO8+ board detected at 0x250, IRQ 12, CD1865 Rev. B.
-sx3: specialix IO8+ Board at 0x260 not found.
-sx0: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-This would happen if you don't give any probe hints to the driver.
-If you would specify:
-
- specialix=0x250,11
-
-you'd get the following messages:
-
-sx0: specialix IO8+ board detected at 0x250, IRQ 11, CD1865 Rev. B.
-sx1: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-ISA probing is aborted after the IO address you gave is exhausted, and
-the PCI card is now detected as the second card. The ISA card is now
-also forced to IRQ11....
-
-
-Baud rates
-==========
-
-The rev 1.2 and below boards use a CL-CD1864. These chips can only
-do 64kbit. The rev 1.3 and newer boards use a CL-CD1865. These chips
-are officially capable of 115k2.
-
-The Specialix card uses a 25MHz crystal (in times two mode, which in
-fact is a divided by two mode). This is not enough to reach the rated
-115k2 on all ports at the same time. With this clock rate you can only
-do 37% of this rate. This means that at 115k2 on all ports you are
-going to lose characters (The chip cannot handle that many incoming
-bits at this clock rate.) (Yes, you read that correctly: there is a
-limit to the number of -=bits=- per second that the chip can handle.)
-
-If you near the "limit" you will first start to see a graceful
-degradation in that the chip cannot keep the transmitter busy at all
-times. However with a central clock this slow, you can also get it to
-miss incoming characters. The driver will print a warning message when
-you are outside the official specs. The messages usually show up in
-the file /var/log/messages .
-
-The specialix card cannot reliably do 115k2. If you use it, you have
-to do "extensive testing" (*) to verify if it actually works.
-
-When "mgetty" communicates with my modem at 115k2 it reports:
-got: +++[0d]ATQ0V1H0[0d][0d][8a]O[cb][0d][8a]
- ^^^^ ^^^^ ^^^^
-
-The three characters that have the "^^^" under them have suffered a
-bit error in the highest bit. In conclusion: I've tested it, and found
-that it simply DOESN'T work for me. I also suspect that this is also
-caused by the baud rate being just a little bit out of tune.
-
-I upgraded the crystal to 66Mhz on one of my Specialix cards. Works
-great! Contact me for details. (Voids warranty, requires a steady hand
-and more such restrictions....)
-
-
-(*) Cirrus logic CD1864 databook, page 40.
-
-
-Cables for the Specialix IO8+
-=============================
-
-The pinout of the connectors on the IO8+ is:
-
- pin short direction long name
- name
- Pin 1 DCD input Data Carrier Detect
- Pin 2 RXD input Receive
- Pin 3 DTR/RTS output Data Terminal Ready/Ready To Send
- Pin 4 GND - Ground
- Pin 5 TXD output Transmit
- Pin 6 CTS input Clear To Send
-
-
- -- 6 5 4 3 2 1 --
- | |
- | |
- | |
- | |
- +----- -----+
- |__________|
- clip
-
- Front view of an RJ12 connector. Cable moves "into" the paper.
- (the plug is ready to plug into your mouth this way...)
-
-
- NULL cable. I don't know who is going to use these except for
- testing purposes, but I tested the cards with this cable. (It
- took quite a while to figure out, so I'm not going to delete
- it. So there! :-)
-
-
- This end goes This end needs
- straight into the some twists in
- RJ12 plug. the wiring.
- IO8+ RJ12 IO8+ RJ12
- 1 DCD white -
- - - 1 DCD
- 2 RXD black 5 TXD
- 3 DTR/RTS red 6 CTS
- 4 GND green 4 GND
- 5 TXD yellow 2 RXD
- 6 CTS blue 3 DTR/RTS
-
-
- Same NULL cable, but now sorted on the second column.
-
- 1 DCD white -
- - - 1 DCD
- 5 TXD yellow 2 RXD
- 6 CTS blue 3 DTR/RTS
- 4 GND green 4 GND
- 2 RXD black 5 TXD
- 3 DTR/RTS red 6 CTS
-
-
-
- This is a modem cable usable for hardware handshaking:
- RJ12 DB25 DB9
- 1 DCD white 8 DCD 1 DCD
- 2 RXD black 3 RXD 2 RXD
- 3 DTR/RTS red 4 RTS 7 RTS
- 4 GND green 7 GND 5 GND
- 5 TXD yellow 2 TXD 3 TXD
- 6 CTS blue 5 CTS 8 CTS
- +---- 6 DSR 6 DSR
- +---- 20 DTR 4 DTR
-
- This is a modem cable usable for software handshaking:
- It allows you to reset the modem using the DTR ioctls.
- I (REW) have never tested this, "but xxxxxxxxxxxxx
- says that it works." If you test this, please
- tell me and I'll fill in your name on the xxx's.
-
- RJ12 DB25 DB9
- 1 DCD white 8 DCD 1 DCD
- 2 RXD black 3 RXD 2 RXD
- 3 DTR/RTS red 20 DTR 4 DTR
- 4 GND green 7 GND 5 GND
- 5 TXD yellow 2 TXD 3 TXD
- 6 CTS blue 5 CTS 8 CTS
- +---- 6 DSR 6 DSR
- +---- 4 RTS 7 RTS
-
- I bought a 6 wire flat cable. It was colored as indicated.
- Check that yours is the same before you trust me on this.
-
-
-Hardware handshaking issues.
-============================
-
-The driver can be told to operate in two different ways. The default
-behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
-hardware handshaking is off. It behaves as the RTS hardware
-handshaking signal when hardware handshaking is selected.
-
-When you use this, you have to use the appropriate cable. The
-cable will either be compatible with hardware handshaking or with
-software handshaking. So switching on the fly is not really an
-option.
-
-I actually prefer to use the "specialix.sx_rtscts=1" option.
-This makes the DTR/RTS pin always an RTS pin, and ioctls to
-change DTR are always ignored. I have a cable that is configured
-for this.
-
-
-Ports and devices
-=================
-
-Port 0 is the one furthest from the card-edge connector.
-
-Devices:
-
-You should make the devices as follows:
-
-bash
-cd /dev
-for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
- 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-do
- echo -n "$i "
- mknod /dev/ttyW$i c 75 $i
- mknod /dev/cuw$i c 76 $i
-done
-echo ""
-
-If your system doesn't come with these devices preinstalled, bug your
-linux-vendor about this. They have had ample time to get this
-implemented by now.
-
-You cannot have more than 4 boards in one computer. The card only
-supports 4 different interrupts. If you really want this, contact me
-about this and I'll give you a few tips (requires soldering iron)....
-
-If you have enough PCI slots, you can probably use more than 4 PCI
-versions of the card though....
-
-The PCI version of the card cannot adhere to the mechanical part of
-the PCI spec because the 8 serial connectors are simply too large. If
-it doesn't fit in your computer, bring back the card.
-
-
-------------------------------------------------------------------------
-
-
- Fixed bugs and restrictions:
- - During initialization, interrupts are blindly turned on.
- Having a shadow variable would cause an extra memory
- access on every IO instruction.
- - The interrupt (on the card) should be disabled when we
- don't allocate the Linux end of the interrupt. This allows
- a different driver/card to use it while all ports are not in
- use..... (a la standard serial port)
- == An extra _off variant of the sx_in and sx_out macros are
- now available. They don't set the interrupt enable bit.
- These are used during initialization. Normal operation uses
- the old variant which enables the interrupt line.
- - RTS/DTR issue needs to be implemented according to
- specialix' spec.
- I kind of like the "determinism" of the current
- implementation. Compile time flag?
- == Ok. Compile time flag! Default is how Specialix likes it.
- == Now a config time flag! Gets saved in your config file. Neat!
- - Can you set the IO address from the lilo command line?
- If you need this, bug me about it, I'll make it.
- == Hah! No bugging needed. Fixed! :-)
- - Cirrus logic hasn't gotten back to me yet why the CD1865 can
- and the CD1864 can't do 115k2. I suspect that this is
- because the CD1864 is not rated for 33MHz operation.
- Therefore the CD1864 versions of the card can't do 115k2 on
- all ports just like the CD1865 versions. The driver does
- not block 115k2 on CD1864 cards.
- == I called the Cirrus Logic representative here in Holland.
- The CD1864 databook is identical to the CD1865 databook,
- except for an extra warning at the end. Similar Bit errors
- have been observed in testing at 115k2 on both an 1865 and
- a 1864 chip. I see no reason why I would prohibit 115k2 on
- 1864 chips and not do it on 1865 chips. Actually there is
- reason to prohibit it on BOTH chips. I print a warning.
- If you use 115k2, you're on your own.
- - A spiky CD may send spurious HUPs. Also in CLOCAL???
- -- A fix for this turned out to be counter productive.
- Different fix? Current behaviour is acceptable?
- -- Maybe the current implementation is correct. If anybody
- gets bitten by this, please report, and it will get fixed.
-
- -- Testing revealed that when in CLOCAL, the problem doesn't
- occur. As warned for in the CD1865 manual, the chip may
- send modem intr's on a spike. We could filter those out,
- but that would be a cludge anyway (You'd still risk getting
- a spurious HUP when two spikes occur.).....
-
-
-
- Bugs & restrictions:
- - This is a difficult card to autoprobe.
- You have to WRITE to the address register to even
- read-probe a CD186x register. Disable autodetection?
- -- Specialix: any suggestions?
-
-
+++ /dev/null
-* NOTE - This is an unmaintained driver. Lantronix, which bought Stallion
-technologies, is not active in driver maintenance, and they have no information
-on when or if they will have a 2.6 driver.
-
-James Nelson <james4765@gmail.com> - 12-12-2004
-
-Stallion Multiport Serial Driver Readme
----------------------------------------
-
-Copyright (C) 1994-1999, Stallion Technologies.
-
-Version: 5.5.1
-Date: 28MAR99
-
-
-
-1. INTRODUCTION
-
-There are two drivers that work with the different families of Stallion
-multiport serial boards. One is for the Stallion smart boards - that is
-EasyIO, EasyConnection 8/32 and EasyConnection 8/64-PCI, the other for
-the true Stallion intelligent multiport boards - EasyConnection 8/64
-(ISA, EISA, MCA), EasyConnection/RA-PCI, ONboard and Brumby.
-
-If you are using any of the Stallion intelligent multiport boards (Brumby,
-ONboard, EasyConnection 8/64 (ISA, EISA, MCA), EasyConnection/RA-PCI) with
-Linux you will need to get the driver utility package. This contains a
-firmware loader and the firmware images necessary to make the devices operate.
-
-The Stallion Technologies ftp site, ftp.stallion.com, will always have
-the latest version of the driver utility package.
-
-ftp://ftp.stallion.com/drivers/ata5/Linux/ata-linux-550.tar.gz
-
-As of the printing of this document the latest version of the driver
-utility package is 5.5.0. If a later version is now available then you
-should use the latest version.
-
-If you are using the EasyIO, EasyConnection 8/32 or EasyConnection 8/64-PCI
-boards then you don't need this package, although it does have a serial stats
-display program.
-
-If you require DIP switch settings, EISA or MCA configuration files, or any
-other information related to Stallion boards then have a look at Stallion's
-web pages at http://www.stallion.com.
-
-
-
-2. INSTALLATION
-
-The drivers can be used as loadable modules or compiled into the kernel.
-You can choose which when doing a "config" on the kernel.
-
-All ISA, EISA and MCA boards that you want to use need to be configured into
-the driver(s). All PCI boards will be automatically detected when you load
-the driver - so they do not need to be entered into the driver(s)
-configuration structure. Note that kernel PCI support is required to use PCI
-boards.
-
-There are two methods of configuring ISA, EISA and MCA boards into the drivers.
-If using the driver as a loadable module then the simplest method is to pass
-the driver configuration as module arguments. The other method is to modify
-the driver source to add configuration lines for each board in use.
-
-If you have pre-built Stallion driver modules then the module argument
-configuration method should be used. A lot of Linux distributions come with
-pre-built driver modules in /lib/modules/X.Y.Z/misc for the kernel in use.
-That makes things pretty simple to get going.
-
-
-2.1 MODULE DRIVER CONFIGURATION:
-
-The simplest configuration for modules is to use the module load arguments
-to configure any ISA, EISA or MCA boards. PCI boards are automatically
-detected, so do not need any additional configuration at all.
-
-If using EasyIO, EasyConnection 8/32 ISA or MCA, or EasyConnection 8/63-PCI
-boards then use the "stallion" driver module, Otherwise if you are using
-an EasyConnection 8/64 ISA, EISA or MCA, EasyConnection/RA-PCI, ONboard,
-Brumby or original Stallion board then use the "istallion" driver module.
-
-Typically to load up the smart board driver use:
-
- modprobe stallion
-
-This will load the EasyIO and EasyConnection 8/32 driver. It will output a
-message to say that it loaded and print the driver version number. It will
-also print out whether it found the configured boards or not. These messages
-may not appear on the console, but typically are always logged to
-/var/adm/messages or /var/log/syslog files - depending on how the klogd and
-syslogd daemons are setup on your system.
-
-To load the intelligent board driver use:
-
- modprobe istallion
-
-It will output similar messages to the smart board driver.
-
-If not using an auto-detectable board type (that is a PCI board) then you
-will also need to supply command line arguments to the modprobe command
-when loading the driver. The general form of the configuration argument is
-
- board?=<name>[,<ioaddr>[,<addr>][,<irq>]]
-
-where:
-
- board? -- specifies the arbitrary board number of this board,
- can be in the range 0 to 3.
-
- name -- textual name of this board. The board name is the common
- board name, or any "shortened" version of that. The board
- type number may also be used here.
-
- ioaddr -- specifies the I/O address of this board. This argument is
- optional, but should generally be specified.
-
- addr -- optional second address argument. Some board types require
- a second I/O address, some require a memory address. The
- exact meaning of this argument depends on the board type.
-
- irq -- optional IRQ line used by this board.
-
-Up to 4 board configuration arguments can be specified on the load line.
-Here is some examples:
-
- modprobe stallion board0=easyio,0x2a0,5
-
-This configures an EasyIO board as board 0 at I/O address 0x2a0 and IRQ 5.
-
- modprobe istallion board3=ec8/64,0x2c0,0xcc000
-
-This configures an EasyConnection 8/64 ISA as board 3 at I/O address 0x2c0 at
-memory address 0xcc000.
-
- modprobe stallion board1=ec8/32-at,0x2a0,0x280,10
-
-This configures an EasyConnection 8/32 ISA board at primary I/O address 0x2a0,
-secondary address 0x280 and IRQ 10.
-
-You will probably want to enter this module load and configuration information
-into your system startup scripts so that the drivers are loaded and configured
-on each system boot. Typically the start up script would be something like
-/etc/modprobe.conf.
-
-
-2.2 STATIC DRIVER CONFIGURATION:
-
-For static driver configuration you need to modify the driver source code.
-Entering ISA, EISA and MCA boards into the driver(s) configuration structure
-involves editing the driver(s) source file. It's pretty easy if you follow
-the instructions below. Both drivers can support up to 4 boards. The smart
-card driver (the stallion.c driver) supports any combination of EasyIO and
-EasyConnection 8/32 boards (up to a total of 4). The intelligent driver
-supports any combination of ONboards, Brumbys, Stallions and EasyConnection
-8/64 (ISA and EISA) boards (up to a total of 4).
-
-To set up the driver(s) for the boards that you want to use you need to
-edit the appropriate driver file and add configuration entries.
-
-If using EasyIO or EasyConnection 8/32 ISA or MCA boards,
- In drivers/char/stallion.c:
- - find the definition of the stl_brdconf array (of structures)
- near the top of the file
- - modify this to match the boards you are going to install
- (the comments before this structure should help)
- - save and exit
-
-If using ONboard, Brumby, Stallion or EasyConnection 8/64 (ISA or EISA)
-boards,
- In drivers/char/istallion.c:
- - find the definition of the stli_brdconf array (of structures)
- near the top of the file
- - modify this to match the boards you are going to install
- (the comments before this structure should help)
- - save and exit
-
-Once you have set up the board configurations then you are ready to build
-the kernel or modules.
-
-When the new kernel is booted, or the loadable module loaded then the
-driver will emit some kernel trace messages about whether the configured
-boards were detected or not. Depending on how your system logger is set
-up these may come out on the console, or just be logged to
-/var/adm/messages or /var/log/syslog. You should check the messages to
-confirm that all is well.
-
-
-2.3 SHARING INTERRUPTS
-
-It is possible to share interrupts between multiple EasyIO and
-EasyConnection 8/32 boards in an EISA system. To do this you must be using
-static driver configuration, modifying the driver source code to add driver
-configuration. Then a couple of extra things are required:
-
-1. When entering the board resources into the stallion.c file you need to
- mark the boards as using level triggered interrupts. Do this by replacing
- the "0" entry at field position 6 (the last field) in the board
- configuration structure with a "1". (This is the structure that defines
- the board type, I/O locations, etc. for each board). All boards that are
- sharing an interrupt must be set this way, and each board should have the
- same interrupt number specified here as well. Now build the module or
- kernel as you would normally.
-
-2. When physically installing the boards into the system you must enter
- the system EISA configuration utility. You will need to install the EISA
- configuration files for *all* the EasyIO and EasyConnection 8/32 boards
- that are sharing interrupts. The Stallion EasyIO and EasyConnection 8/32
- EISA configuration files required are supplied by Stallion Technologies
- on the EASY Utilities floppy diskette (usually supplied in the box with
- the board when purchased. If not, you can pick it up from Stallion's FTP
- site, ftp.stallion.com). You will need to edit the board resources to
- choose level triggered interrupts, and make sure to set each board's
- interrupt to the same IRQ number.
-
-You must complete both the above steps for this to work. When you reboot
-or load the driver your EasyIO and EasyConnection 8/32 boards will be
-sharing interrupts.
-
-
-2.4 USING HIGH SHARED MEMORY
-
-The EasyConnection 8/64-EI, ONboard and Stallion boards are capable of
-using shared memory addresses above the usual 640K - 1Mb range. The ONboard
-ISA and the Stallion boards can be programmed to use memory addresses up to
-16Mb (the ISA bus addressing limit), and the EasyConnection 8/64-EI and
-ONboard/E can be programmed for memory addresses up to 4Gb (the EISA bus
-addressing limit).
-
-The higher than 1Mb memory addresses are fully supported by this driver.
-Just enter the address as you normally would for a lower than 1Mb address
-(in the driver's board configuration structure).
-
-
-
-2.5 TROUBLE SHOOTING
-
-If a board is not found by the driver but is actually in the system then the
-most likely problem is that the I/O address is wrong. Change the module load
-argument for the loadable module form. Or change it in the driver stallion.c
-or istallion.c configuration structure and rebuild the kernel or modules, or
-change it on the board.
-
-On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable, so
-if there is a conflict you may need to change the IRQ used for a board. There
-are no interrupts to worry about for ONboard, Brumby or EasyConnection 8/64
-(ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
-ONboard boards is software programmable, but not on the Brumby boards.
-
-
-
-3. USING THE DRIVERS
-
-3.1 INTELLIGENT DRIVER OPERATION
-
-The intelligent boards also need to have their "firmware" code downloaded
-to them. This is done via a user level application supplied in the driver
-utility package called "stlload". Compile this program wherever you dropped
-the package files, by typing "make". In its simplest form you can then type
-
- ./stlload -i cdk.sys
-
-in this directory and that will download board 0 (assuming board 0 is an
-EasyConnection 8/64 or EasyConnection/RA board). To download to an
-ONboard, Brumby or Stallion do:
-
- ./stlload -i 2681.sys
-
-Normally you would want all boards to be downloaded as part of the standard
-system startup. To achieve this, add one of the lines above into the
-/etc/rc.d/rc.S or /etc/rc.d/rc.serial file. To download each board just add
-the "-b <brd-number>" option to the line. You will need to download code for
-every board. You should probably move the stlload program into a system
-directory, such as /usr/sbin. Also, the default location of the cdk.sys image
-file in the stlload down-loader is /usr/lib/stallion. Create that directory
-and put the cdk.sys and 2681.sys files in it. (It's a convenient place to put
-them anyway). As an example your /etc/rc.d/rc.S file might have the
-following lines added to it (if you had 3 boards):
-
- /usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys
- /usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys
- /usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys
-
-The image files cdk.sys and 2681.sys are specific to the board types. The
-cdk.sys will only function correctly on an EasyConnection 8/64 board. Similarly
-the 2681.sys image fill only operate on ONboard, Brumby and Stallion boards.
-If you load the wrong image file into a board it will fail to start up, and
-of course the ports will not be operational!
-
-If you are using the modularized version of the driver you might want to put
-the modprobe calls in the startup script as well (before the download lines
-obviously).
-
-
-3.2 USING THE SERIAL PORTS
-
-Once the driver is installed you will need to setup some device nodes to
-access the serial ports. The simplest method is to use the /dev/MAKEDEV program.
-It will automatically create device entries for Stallion boards. This will
-create the normal serial port devices as /dev/ttyE# where# is the port number
-starting from 0. A bank of 64 minor device numbers is allocated to each board,
-so the first port on the second board is port 64,etc. A set of callout type
-devices may also be created. They are created as the devices /dev/cue# where #
-is the same as for the ttyE devices.
-
-For the most part the Stallion driver tries to emulate the standard PC system
-COM ports and the standard Linux serial driver. The idea is that you should
-be able to use Stallion board ports and COM ports interchangeably without
-modifying anything but the device name. Anything that doesn't work like that
-should be considered a bug in this driver!
-
-If you look at the driver code you will notice that it is fairly closely
-based on the Linux serial driver (linux/drivers/char/serial.c). This is
-intentional, obviously this is the easiest way to emulate its behavior!
-
-Since this driver tries to emulate the standard serial ports as much as
-possible, most system utilities should work as they do for the standard
-COM ports. Most importantly "stty" works as expected and "setserial" can
-also be used (excepting the ability to auto-configure the I/O and IRQ
-addresses of boards). Higher baud rates are supported in the usual fashion
-through setserial or using the CBAUDEX extensions. Note that the EasyIO and
-EasyConnection (all types) support at least 57600 and 115200 baud. The newer
-EasyConnection XP modules and new EasyIO boards support 230400 and 460800
-baud as well. The older boards including ONboard and Brumby support a
-maximum baud rate of 38400.
-
-If you are unfamiliar with how to use serial ports, then get the Serial-HOWTO
-by Greg Hankins. It will explain everything you need to know!
-
-
-
-4. NOTES
-
-You can use both drivers at once if you have a mix of board types installed
-in a system. However to do this you will need to change the major numbers
-used by one of the drivers. Currently both drivers use major numbers 24, 25
-and 28 for their devices. Change one driver to use some other major numbers,
-and then modify the mkdevnods script to make device nodes based on those new
-major numbers. For example, you could change the istallion.c driver to use
-major numbers 60, 61 and 62. You will also need to create device nodes with
-different names for the ports, for example ttyF# and cuf#.
-
-The original Stallion board is no longer supported by Stallion Technologies.
-Although it is known to work with the istallion driver.
-
-Finding a free physical memory address range can be a problem. The older
-boards like the Stallion and ONboard need large areas (64K or even 128K), so
-they can be very difficult to get into a system. If you have 16 Mb of RAM
-then you have no choice but to put them somewhere in the 640K -> 1Mb range.
-ONboards require 64K, so typically 0xd0000 is good, or 0xe0000 on some
-systems. If you have an original Stallion board, "V4.0" or Rev.O, then you
-need a 64K memory address space, so again 0xd0000 and 0xe0000 are good.
-Older Stallion boards are a much bigger problem. They need 128K of address
-space and must be on a 128K boundary. If you don't have a VGA card then
-0xc0000 might be usable - there is really no other place you can put them
-below 1Mb.
-
-Both the ONboard and old Stallion boards can use higher memory addresses as
-well, but you must have less than 16Mb of RAM to be able to use them. Usual
-high memory addresses used include 0xec0000 and 0xf00000.
-
-The Brumby boards only require 16Kb of address space, so you can usually
-squeeze them in somewhere. Common addresses are 0xc8000, 0xcc000, or in
-the 0xd0000 range. EasyConnection 8/64 boards are even better, they only
-require 4Kb of address space, again usually 0xc8000, 0xcc000 or 0xd0000
-are good.
-
-If you are using an EasyConnection 8/64-EI or ONboard/E then usually the
-0xd0000 or 0xe0000 ranges are the best options below 1Mb. If neither of
-them can be used then the high memory support to use the really high address
-ranges is the best option. Typically the 2Gb range is convenient for them,
-and gets them well out of the way.
-
-The ports of the EasyIO-8M board do not have DCD or DTR signals. So these
-ports cannot be used as real modem devices. Generally, when using these
-ports you should only use the cueX devices.
-
-The driver utility package contains a couple of very useful programs. One
-is a serial port statistics collection and display program - very handy
-for solving serial port problems. The other is an extended option setting
-program that works with the intelligent boards.
-
-
-
-5. DISCLAIMER
-
-The information contained in this document is believed to be accurate and
-reliable. However, no responsibility is assumed by Stallion Technologies
-Pty. Ltd. for its use, nor any infringements of patents or other rights
-of third parties resulting from its use. Stallion Technologies reserves
-the right to modify the design of its products and will endeavour to change
-the information in manuals and accompanying documentation accordingly.
-
+++ /dev/null
-
- sx.txt -- specialix SX/SI multiport serial driver readme.
-
-
-
- Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
-
- Specialix pays for the development and support of this driver.
- Please DO contact support@specialix.co.uk if you require
- support.
-
- This driver was developed in the BitWizard linux device
- driver service. If you require a linux device driver for your
- product, please contact devices@BitWizard.nl for a quote.
-
- (History)
- There used to be an SI driver by Simon Allan. This is a complete
- rewrite from scratch. Just a few lines-of-code have been snatched.
-
- (Sources)
- Specialix document number 6210028: SX Host Card and Download Code
- Software Functional Specification.
-
- (Copying)
- This program 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.
-
- 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.
-
- 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., 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- (Addendum)
- I'd appreciate it that if you have fixes, that you send them
- to me first.
-
-
-Introduction
-============
-
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources? And the manual of one of the boards in your computer?
-
-
-Theory of operation
-===================
-
-An important thing to know is that the driver itself doesn't have the
-firmware for the card. This means that you need the separate package
-"sx_firmware". For now you can get the source at
-
- ftp://ftp.bitwizard.nl/specialix/sx_firmware_<version>.tgz
-
-The firmware load needs a "misc" device, so you'll need to enable the
-"Support for user misc device modules" in your kernel configuration.
-The misc device needs to be called "/dev/specialix_sxctl". It needs
-misc major 10, and minor number 167 (assigned by HPA). The section
-on creating device files below also creates this device.
-
-After loading the sx.o module into your kernel, the driver will report
-the number of cards detected, but because it doesn't have any
-firmware, it will not be able to determine the number of ports. Only
-when you then run "sx_firmware" will the firmware be downloaded and
-the rest of the driver initialized. At that time the sx_firmware
-program will report the number of ports installed.
-
-In contrast with many other multi port serial cards, some of the data
-structures are only allocated when the card knows the number of ports
-that are connected. This means we won't waste memory for 120 port
-descriptor structures when you only have 8 ports. If you experience
-problems due to this, please report them: I haven't seen any.
-
-
-Interrupts
-==========
-
-A multi port serial card, would generate a horrendous amount of
-interrupts if it would interrupt the CPU for every received
-character. Even more than 10 years ago, the trick not to use
-interrupts but to poll the serial cards was invented.
-
-The SX card allow us to do this two ways. First the card limits its
-own interrupt rate to a rate that won't overwhelm the CPU. Secondly,
-we could forget about the cards interrupt completely and use the
-internal timer for this purpose.
-
-Polling the card can take up to a few percent of your CPU. Using the
-interrupts would be better if you have most of the ports idle. Using
-timer-based polling is better if your card almost always has work to
-do. You save the separate interrupt in that case.
-
-In any case, it doesn't really matter all that much.
-
-The most common problem with interrupts is that for ISA cards in a PCI
-system the BIOS has to be told to configure that interrupt as "legacy
-ISA". Otherwise the card can pull on the interrupt line all it wants
-but the CPU won't see this.
-
-If you can't get the interrupt to work, remember that polling mode is
-more efficient (provided you actually use the card intensively).
-
-
-Allowed Configurations
-======================
-
-Some configurations are disallowed. Even though at a glance they might
-seem to work, they are known to lockup the bus between the host card
-and the device concentrators. You should respect the drivers decision
-not to support certain configurations. It's there for a reason.
-
-Warning: Seriously technical stuff ahead. Executive summary: Don't use
-SX cards except configured at a 64k boundary. Skip the next paragraph.
-
-The SX cards can theoretically be placed at a 32k boundary. So for
-instance you can put an SX card at 0xc8000-0xd7fff. This is not a
-"recommended configuration". ISA cards have to tell the bus controller
-how they like their timing. Due to timing issues they have to do this
-based on which 64k window the address falls into. This means that the
-32k window below and above the SX card have to use exactly the same
-timing as the SX card. That reportedly works for other SX cards. But
-you're still left with two useless 32k windows that should not be used
-by anybody else.
-
-
-Configuring the driver
-======================
-
-PCI cards are always detected. The driver auto-probes for ISA cards at
-some sensible addresses. Please report if the auto-probe causes trouble
-in your system, or when a card isn't detected.
-
-I'm afraid I haven't implemented "kernel command line parameters" yet.
-This means that if the default doesn't work for you, you shouldn't use
-the compiled-into-the-kernel version of the driver. Use a module
-instead. If you convince me that you need this, I'll make it for
-you. Deal?
-
-I'm afraid that the module parameters are a bit clumsy. If you have a
-better idea, please tell me.
-
-You can specify several parameters:
-
- sx_poll: number of jiffies between timer-based polls.
-
- Set this to "0" to disable timer based polls.
- Initialization of cards without a working interrupt
- will fail.
-
- Set this to "1" if you want a polling driver.
- (on Intel: 100 polls per second). If you don't use
- fast baud rates, you might consider a value like "5".
- (If you don't know how to do the math, use 1).
-
- sx_slowpoll: Number of jiffies between timer-based polls.
- Set this to "100" to poll once a second.
- This should get the card out of a stall if the driver
- ever misses an interrupt. I've never seen this happen,
- and if it does, that's a bug. Tell me.
-
- sx_maxints: Number of interrupts to request from the card.
- The card normally limits interrupts to about 100 per
- second to offload the host CPU. You can increase this
- number to reduce latency on the card a little.
- Note that if you give a very high number you can overload
- your CPU as well as the CPU on the host card. This setting
- is inaccurate and not recommended for SI cards (But it
- works).
-
- sx_irqmask: The mask of allowable IRQs to use. I suggest you set
- this to 0 (disable IRQs all together) and use polling if
- the assignment of IRQs becomes problematic. This is defined
- as the sum of (1 << irq) 's that you want to allow. So
- sx_irqmask of 8 (1 << 3) specifies that only irq 3 may
- be used by the SX driver. If you want to specify to the
- driver: "Either irq 11 or 12 is ok for you to use", then
- specify (1 << 11) | (1 << 12) = 0x1800 .
-
- sx_debug: You can enable different sorts of debug traces with this.
- At "-1" all debugging traces are active. You'll get several
- times more debugging output than you'll get characters
- transmitted.
-
-
-Baud rates
-==========
-
-Theoretically new SXDCs should be capable of more than 460k
-baud. However the line drivers usually give up before that. Also the
-CPU on the card may not be able to handle 8 channels going at full
-blast at that speed. Moreover, the buffers are not large enough to
-allow operation with 100 interrupts per second. You'll have to realize
-that the card has a 256 byte buffer, so you'll have to increase the
-number of interrupts per second if you have more than 256*100 bytes
-per second to transmit. If you do any performance testing in this
-area, I'd be glad to hear from you...
-
-(Psst Linux users..... I think the Linux driver is more efficient than
-the driver for other OSes. If you can and want to benchmark them
-against each other, be my guest, and report your findings...... :-)
-
-
-Ports and devices
-=================
-
-Port 0 is the top connector on the module closest to the host
-card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8
-instead of from 0 to 7, as they are numbered by linux. I'm stubborn in
-this: I know for sure that I wouldn't be able to calculate which port
-is which anymore if I would change that....
-
-
-Devices:
-
-You should make the device files as follows:
-
-#!/bin/sh
-# (I recommend that you cut-and-paste this into a file and run that)
-cd /dev
-t=0
-mknod specialix_sxctl c 10 167
-while [ $t -lt 64 ]
- do
- echo -n "$t "
- mknod ttyX$t c 32 $t
- mknod cux$t c 33 $t
- t=`expr $t + 1`
-done
-echo ""
-rm /etc/psdevtab
-ps > /dev/null
-
-
-This creates 64 devices. If you have more, increase the constant on
-the line with "while". The devices start at 0, as is customary on
-Linux. Specialix seems to like starting the numbering at 1.
-
-If your system doesn't come with these devices pre-installed, bug your
-linux-vendor about this. They should have these devices
-"pre-installed" before the new millennium. The "ps" stuff at the end
-is to "tell" ps that the new devices exist.
-
-Officially the maximum number of cards per computer is 4. This driver
-however supports as many cards in one machine as you want. You'll run
-out of interrupts after a few, but you can switch to polled operation
-then. At about 256 ports (More than 8 cards), we run out of minor
-device numbers. Sorry. I suggest you buy a second computer.... (Or
-switch to RIO).
-
-------------------------------------------------------------------------
-
-
- Fixed bugs and restrictions:
- - Hangup processing.
- -- Done.
-
- - the write path in generic_serial (lockup / oops).
- -- Done (Ugly: not the way I want it. Copied from serial.c).
-
- - write buffer isn't flushed at close.
- -- Done. I still seem to lose a few chars at close.
- Sorry. I think that this is a firmware issue. (-> Specialix)
-
- - drain hardware before changing termios
- - Change debug on the fly.
- - ISA free irq -1. (no firmware loaded).
- - adding c8000 as a probe address. Added warning.
- - Add a RAMtest for the RAM on the card.c
- - Crash when opening a port "way" of the number of allowed ports.
- (for example opening port 60 when there are only 24 ports attached)
- - Sometimes the use-count strays a bit. After a few hours of
- testing the use count is sometimes "3". If you are not like
- me and can remember what you did to get it that way, I'd
- appreciate an Email. Possibly fixed. Tell me if anyone still
- sees this.
- - TAs don't work right if you don't connect all the modem control
- signals. SXDCs do. T225 firmware problem -> Specialix.
- (Mostly fixed now, I think. Tell me if you encounter this!)
-
- Bugs & restrictions:
-
- - Arbitrary baud rates. Requires firmware update. (-> Specialix)
-
- - Low latency (mostly firmware, -> Specialix)
-
-
-
+++ /dev/null
-
- The Lockronomicon
-
-Your guide to the ancient and twisted locking policies of the tty layer and
-the warped logic behind them. Beware all ye who read on.
-
-FIXME: still need to work out the full set of BKL assumptions and document
-them so they can eventually be killed off.
-
-
-Line Discipline
----------------
-
-Line disciplines are registered with tty_register_ldisc() passing the
-discipline number and the ldisc structure. At the point of registration the
-discipline must be ready to use and it is possible it will get used before
-the call returns success. If the call returns an error then it won't get
-called. Do not re-use ldisc numbers as they are part of the userspace ABI
-and writing over an existing ldisc will cause demons to eat your computer.
-After the return the ldisc data has been copied so you may free your own
-copy of the structure. You must not re-register over the top of the line
-discipline even with the same data or your computer again will be eaten by
-demons.
-
-In order to remove a line discipline call tty_unregister_ldisc().
-In ancient times this always worked. In modern times the function will
-return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
-code manages the module counts this should not usually be a concern.
-
-Heed this warning: the reference count field of the registered copies of the
-tty_ldisc structure in the ldisc table counts the number of lines using this
-discipline. The reference count of the tty_ldisc structure within a tty
-counts the number of active users of the ldisc at this instant. In effect it
-counts the number of threads of execution within an ldisc method (plus those
-about to enter and exit although this detail matters not).
-
-Line Discipline Methods
------------------------
-
-TTY side interfaces:
-
-open() - Called when the line discipline is attached to
- the terminal. No other call into the line
- discipline for this tty will occur until it
- completes successfully. Can sleep.
-
-close() - This is called on a terminal when the line
- discipline is being unplugged. At the point of
- execution no further users will enter the
- ldisc code for this tty. Can sleep.
-
-hangup() - Called when the tty line is hung up.
- The line discipline should cease I/O to the tty.
- No further calls into the ldisc code will occur.
- Can sleep.
-
-write() - A process is writing data through the line
- discipline. Multiple write calls are serialized
- by the tty layer for the ldisc. May sleep.
-
-flush_buffer() - (optional) May be called at any point between
- open and close, and instructs the line discipline
- to empty its input buffer.
-
-chars_in_buffer() - (optional) Report the number of bytes in the input
- buffer.
-
-set_termios() - (optional) Called on termios structure changes.
- The caller passes the old termios data and the
- current data is in the tty. Called under the
- termios semaphore so allowed to sleep. Serialized
- against itself only.
-
-read() - Move data from the line discipline to the user.
- Multiple read calls may occur in parallel and the
- ldisc must deal with serialization issues. May
- sleep.
-
-poll() - Check the status for the poll/select calls. Multiple
- poll calls may occur in parallel. May sleep.
-
-ioctl() - Called when an ioctl is handed to the tty layer
- that might be for the ldisc. Multiple ioctl calls
- may occur in parallel. May sleep.
-
-Driver Side Interfaces:
-
-receive_buf() - Hand buffers of bytes from the driver to the ldisc
- for processing. Semantics currently rather
- mysterious 8(
-
-write_wakeup() - May be called at any point between open and close.
- The TTY_DO_WRITE_WAKEUP flag indicates if a call
- is needed but always races versus calls. Thus the
- ldisc must be careful about setting order and to
- handle unexpected calls. Must not sleep.
-
- The driver is forbidden from calling this directly
- from the ->write call from the ldisc as the ldisc
- is permitted to call the driver write method from
- this function. In such a situation defer it.
-
-
-Driver Access
-
-Line discipline methods can call the following methods of the underlying
-hardware driver through the function pointers within the tty->driver
-structure:
-
-write() Write a block of characters to the tty device.
- Returns the number of characters accepted. The
- character buffer passed to this method is already
- in kernel space.
-
-put_char() Queues a character for writing to the tty device.
- If there is no room in the queue, the character is
- ignored.
-
-flush_chars() (Optional) If defined, must be called after
- queueing characters with put_char() in order to
- start transmission.
-
-write_room() Returns the numbers of characters the tty driver
- will accept for queueing to be written.
-
-ioctl() Invoke device specific ioctl.
- Expects data pointers to refer to userspace.
- Returns ENOIOCTLCMD for unrecognized ioctl numbers.
-
-set_termios() Notify the tty driver that the device's termios
- settings have changed. New settings are in
- tty->termios. Previous settings should be passed in
- the "old" argument.
-
- The API is defined such that the driver should return
- the actual modes selected. This means that the
- driver function is responsible for modifying any
- bits in the request it cannot fulfill to indicate
- the actual modes being used. A device with no
- hardware capability for change (eg a USB dongle or
- virtual port) can provide NULL for this method.
-
-throttle() Notify the tty driver that input buffers for the
- line discipline are close to full, and it should
- somehow signal that no more characters should be
- sent to the tty.
-
-unthrottle() Notify the tty driver that characters can now be
- sent to the tty without fear of overrunning the
- input buffers of the line disciplines.
-
-stop() Ask the tty driver to stop outputting characters
- to the tty device.
-
-start() Ask the tty driver to resume sending characters
- to the tty device.
-
-hangup() Ask the tty driver to hang up the tty device.
-
-break_ctl() (Optional) Ask the tty driver to turn on or off
- BREAK status on the RS-232 port. If state is -1,
- then the BREAK status should be turned on; if
- state is 0, then BREAK should be turned off.
- If this routine is not implemented, use ioctls
- TIOCSBRK / TIOCCBRK instead.
-
-wait_until_sent() Waits until the device has written out all of the
- characters in its transmitter FIFO.
-
-send_xchar() Send a high-priority XON/XOFF character to the device.
-
-
-Flags
-
-Line discipline methods have access to tty->flags field containing the
-following interesting flags:
-
-TTY_THROTTLED Driver input is throttled. The ldisc should call
- tty->driver->unthrottle() in order to resume
- reception when it is ready to process more data.
-
-TTY_DO_WRITE_WAKEUP If set, causes the driver to call the ldisc's
- write_wakeup() method in order to resume
- transmission when it can accept more data
- to transmit.
-
-TTY_IO_ERROR If set, causes all subsequent userspace read/write
- calls on the tty to fail, returning -EIO.
-
-TTY_OTHER_CLOSED Device is a pty and the other side has closed.
-
-TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
- smaller chunks.
-
-
-Locking
-
-Callers to the line discipline functions from the tty layer are required to
-take line discipline locks. The same is true of calls from the driver side
-but not yet enforced.
-
-Three calls are now provided
-
- ldisc = tty_ldisc_ref(tty);
-
-takes a handle to the line discipline in the tty and returns it. If no ldisc
-is currently attached or the ldisc is being closed and re-opened at this
-point then NULL is returned. While this handle is held the ldisc will not
-change or go away.
-
- tty_ldisc_deref(ldisc)
-
-Returns the ldisc reference and allows the ldisc to be closed. Returning the
-reference takes away your right to call the ldisc functions until you take
-a new reference.
-
- ldisc = tty_ldisc_ref_wait(tty);
-
-Performs the same function as tty_ldisc_ref except that it will wait for an
-ldisc change to complete and then return a reference to the new ldisc.
-
-While these functions are slightly slower than the old code they should have
-minimal impact as most receive logic uses the flip buffers and they only
-need to take a reference when they push bits up through the driver.
-
-A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc
-functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
-fail in this situation if used within these functions. Ldisc and driver
-code calling its own functions must be careful in this case.
-
-
-Driver Interface
-----------------
-
-open() - Called when a device is opened. May sleep
-
-close() - Called when a device is closed. At the point of
- return from this call the driver must make no
- further ldisc calls of any kind. May sleep
-
-write() - Called to write bytes to the device. May not
- sleep. May occur in parallel in special cases.
- Because this includes panic paths drivers generally
- shouldn't try and do clever locking here.
-
-put_char() - Stuff a single character onto the queue. The
- driver is guaranteed following up calls to
- flush_chars.
-
-flush_chars() - Ask the kernel to write put_char queue
-
-write_room() - Return the number of characters tht can be stuffed
- into the port buffers without overflow (or less).
- The ldisc is responsible for being intelligent
- about multi-threading of write_room/write calls
-
-ioctl() - Called when an ioctl may be for the driver
-
-set_termios() - Called on termios change, serialized against
- itself by a semaphore. May sleep.
-
-set_ldisc() - Notifier for discipline change. At the point this
- is done the discipline is not yet usable. Can now
- sleep (I think)
-
-throttle() - Called by the ldisc to ask the driver to do flow
- control. Serialization including with unthrottle
- is the job of the ldisc layer.
-
-unthrottle() - Called by the ldisc to ask the driver to stop flow
- control.
-
-stop() - Ldisc notifier to the driver to stop output. As with
- throttle the serializations with start() are down
- to the ldisc layer.
-
-start() - Ldisc notifier to the driver to start output.
-
-hangup() - Ask the tty driver to cause a hangup initiated
- from the host side. [Can sleep ??]
-
-break_ctl() - Send RS232 break. Can sleep. Can get called in
- parallel, driver must serialize (for now), and
- with write calls.
-
-wait_until_sent() - Wait for characters to exit the hardware queue
- of the driver. Can sleep
-
-send_xchar() - Send XON/XOFF and if possible jump the queue with
- it in order to get fast flow control responses.
- Cannot sleep ??
-
FTRACE
P: Steven Rostedt
-M: srostedt@redhat.com
+M: rostedt@goodmis.org
S: Maintained
FUJITSU FR-V (FRV) PORT
S: Maintained
SOFTWARE RAID (Multiple Disks) SUPPORT
-P: Ingo Molnar
-M: mingo@redhat.com
P: Neil Brown
M: neilb@suse.de
L: linux-raid@vger.kernel.org
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 28
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc6
NAME = Killer Bat of Doom
# *DOCUMENTATION*
int dmabounce_sync_for_device(struct device *, dma_addr_t, unsigned long,
size_t, enum dma_data_direction);
#else
-#define dmabounce_sync_for_cpu(dev,dma,off,sz,dir) (1)
-#define dmabounce_sync_for_device(dev,dma,off,sz,dir) (1)
+static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
+ unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+ return 1;
+}
+
+static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
+ unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+ return 1;
+}
/**
};
/* types 0-3 are defined in asm/io.h */
-#define MT_CACHECLEAN 4
-#define MT_MINICLEAN 5
-#define MT_LOW_VECTORS 6
-#define MT_HIGH_VECTORS 7
-#define MT_MEMORY 8
-#define MT_ROM 9
+#define MT_UNCACHED 4
+#define MT_CACHECLEAN 5
+#define MT_MINICLEAN 6
+#define MT_LOW_VECTORS 7
+#define MT_HIGH_VECTORS 8
+#define MT_MEMORY 9
+#define MT_ROM 10
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
#include <asm/hardware/ep7212.h>
#include <asm/hardware/cs89712.h>
-/* dynamic ioremap() areas */
-#define FLASH_START 0x00000000
-#define FLASH_SIZE 0x800000
-#define FLASH_WIDTH 4
-
-#define SRAM_START 0x60000000
-#define SRAM_SIZE 0xc000
-#define SRAM_WIDTH 4
-
-#define BOOTROM_START 0x70000000
-#define BOOTROM_SIZE 0x80
-#define BOOTROM_WIDTH 4
-
-
/* static cdb89712_map_io() areas */
#define REGISTER_START 0x80000000
#define REGISTER_SIZE 0x4000
#define CEIVA_FLASH_SIZE 0x100000
#define CEIVA_FLASH_WIDTH 2
-#define SRAM_START 0x60000000
-#define SRAM_SIZE 0xc000
-#define SRAM_WIDTH 4
-
-#define BOOTROM_START 0x70000000
-#define BOOTROM_SIZE 0x80
-#define BOOTROM_WIDTH 4
-
/*
* SED1355 LCD controller
*/
.length = ISA_SIZE,
.type = MT_DEVICE
}, { /* Flash */
- .virtual = FLASH_BASE,
- .pfn = __phys_to_pfn(FLASH_START),
- .length = FLASH_SIZE,
+ .virtual = CLPS7500_FLASH_BASE,
+ .pfn = __phys_to_pfn(CLPS7500_FLASH_START),
+ .length = CLPS7500_FLASH_SIZE,
.type = MT_DEVICE
}, { /* LED */
.virtual = LED_BASE,
#define ISA_SIZE 0x00010000
#define ISA_BASE 0xe1000000
-#define FLASH_START 0x01000000 /* XXX */
-#define FLASH_SIZE 0x01000000
-#define FLASH_BASE 0xe2000000
+#define CLPS7500_FLASH_START 0x01000000 /* XXX */
+#define CLPS7500_FLASH_SIZE 0x01000000
+#define CLPS7500_FLASH_BASE 0xe2000000
#define LED_START 0x0302B000
#define LED_SIZE 0x00001000
#ifdef CONFIG_ARCH_H7202
/* FLASH */
-#define FLASH_VIRT 0xd0000000
-#define FLASH_PHYS 0x00000000
-#define FLASH_SIZE 0x02000000
+#define H720X_FLASH_VIRT 0xd0000000
+#define H720X_FLASH_PHYS 0x00000000
+#define H720X_FLASH_SIZE 0x02000000
/* onboard LAN controller */
# define ETH0_PHYS 0x08000000
*/
#define uHAL_MEMORY_SIZE INTEGRATOR_SSRAM_SIZE
-/*
- * Application Flash
- *
- */
-#define FLASH_BASE INTEGRATOR_FLASH_BASE
-#define FLASH_SIZE INTEGRATOR_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE INTEGRATOR_BOOT_ROM_HI
-#define EPROM_SIZE INTEGRATOR_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
-
/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE INTEGRATOR_BOOT_ROM_HI
/*
* Timer definitions
#define LCD_CONN_TYPE(_x) ((_x) & 0x0f)
#define LCD_CONN_WIDTH(_x) (((_x) >> 4) & 0x1f)
+#define LCD_TYPE_MASK 0xf
#define LCD_TYPE_UNKNOWN 0
#define LCD_TYPE_MONO_STN 1
#define LCD_TYPE_MONO_DSTN 2
/* Jump into ROM at address 0 */
cpu_reset(0);
break;
- case 'h':
- do_hw_reset();
- break;
case 'g':
do_gpio_reset();
break;
+ case 'h':
+ default:
+ do_hw_reset();
+ break;
}
}
static unsigned long spitz_pin_config[] __initdata = {
/* Chip Selects */
GPIO78_nCS_2, /* SCOOP #2 */
+ GPIO79_nCS_3, /* NAND */
GPIO80_nCS_4, /* SCOOP #1 */
/* LCD - 16bpp Active TFT */
GPIO51_nPIOW,
GPIO85_nPCE_1,
GPIO54_nPCE_2,
- GPIO79_PSKTSEL,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
+ GPIO104_PSKTSEL,
/* MMC */
GPIO32_MMC_CLK,
spitz_pcmcia_config.num_devs = 1;
platform_scoop_config = &spitz_pcmcia_config;
- pxa_set_i2c_info(NULL);
i2c_register_board_info(0, ARRAY_AND_SIZE(akita_i2c_board_info));
common_init();
static struct clk mmci_clk = {
.name = "MCLK",
- .rate = 33000000,
+ .rate = 24000000,
};
int clk_register(struct clk *clk)
#define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */
#define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */
-/*
- * Application Flash
- *
- */
-#define FLASH_BASE REALVIEW_FLASH_BASE
-#define FLASH_SIZE REALVIEW_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE REALVIEW_BOOT_ROM_HI
-#define EPROM_SIZE REALVIEW_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
-
/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE REALVIEW_BOOT_ROM_HI
/*
* System controller bit assignment
static struct clk mmci_clk = {
.name = "MCLK",
- .rate = 33000000,
+ .rate = 24000000,
};
int clk_register(struct clk *clk)
#define SIC_INTMASK_PCI1 (1 << SIC_INT_PCI1)
#define SIC_INTMASK_PCI2 (1 << SIC_INT_PCI2)
#define SIC_INTMASK_PCI3 (1 << SIC_INT_PCI3)
-/*
- * Application Flash
- *
- */
-#define FLASH_BASE VERSATILE_FLASH_BASE
-#define FLASH_SIZE VERSATILE_FLASH_SIZE
-#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
-#define FLASH_BLOCK_SIZE SZ_128K
-
-/*
- * Boot Flash
- *
- */
-#define EPROM_BASE VERSATILE_BOOT_ROM_HI
-#define EPROM_SIZE VERSATILE_BOOT_ROM_SIZE
-#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
/*
* Clean base - dummy
*
*/
-#define CLEAN_BASE EPROM_BASE
+#define CLEAN_BASE VERSATILE_BOOT_ROM_HI
/*
* System controller bit assignment
/*
* Clean and invalidate partial last cache line.
*/
- if (end & (CACHE_LINE_SIZE - 1)) {
+ if (start < end && end & (CACHE_LINE_SIZE - 1)) {
l2_clean_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
end &= ~(CACHE_LINE_SIZE - 1);
}
/*
* Invalidate all full cache lines between 'start' and 'end'.
*/
- while (start != end) {
+ while (start < end) {
unsigned long range_end = calc_range_end(start, end);
l2_inv_pa_range(start, range_end - CACHE_LINE_SIZE);
start = range_end;
.prot_sect = PROT_SECT_DEVICE,
.domain = DOMAIN_IO,
},
+ [MT_UNCACHED] = {
+ .prot_pte = PROT_PTE_DEVICE,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
+ .domain = DOMAIN_IO,
+ },
[MT_CACHECLEAN] = {
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
.domain = DOMAIN_KERNEL,
#include <asm/hardware/iop3xx.h>
/*
- * Standard IO mapping for all IOP3xx based systems
+ * Standard IO mapping for all IOP3xx based systems. Note that
+ * the IOP3xx OCCDR must be mapped uncached and unbuffered.
*/
static struct map_desc iop3xx_std_desc[] __initdata = {
{ /* mem mapped registers */
.virtual = IOP3XX_PERIPHERAL_VIRT_BASE,
.pfn = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
.length = IOP3XX_PERIPHERAL_SIZE,
- .type = MT_DEVICE,
+ .type = MT_UNCACHED,
}, { /* PCI IO space */
.virtual = IOP3XX_PCI_LOWER_IO_VA,
.pfn = __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA),
extern unsigned long _ramstart, _ramend, _rambase;
extern unsigned long memory_start, memory_end, physical_mem_end;
extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
- _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _ebss_b_l1[],
+ _ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
_ebss_l2[], _l2_lma_start[];
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_mapping_error
+static inline
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return 0;
+}
/*
* Map a single buffer of the indicated size for DMA in streaming mode.
if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
|| gpio == GPIO_PH14 || gpio == GPIO_PH15
|| gpio == GPIO_PJ14 || gpio == GPIO_PJ15
- || gpio > MAX_BLACKFIN_GPIOS)
+ || gpio >= MAX_BLACKFIN_GPIOS)
return -EINVAL;
return 0;
}
static u16 __init lock_kernel_check(u32 start, u32 end)
{
- if ((end <= (u32) _end && end >= (u32)_stext) ||
- (start <= (u32) _end && start >= (u32)_stext))
- return IN_KERNEL;
- return 0;
+ if (start >= (u32)_end || end <= (u32)_stext)
+ return 0;
+
+ /* This cplb block overlapped with kernel area. */
+ return IN_KERNEL;
}
static unsigned short __init
return 1;
#endif
#if L1_DATA_B_LENGTH != 0
- if (addr >= L1_DATA_B_START
+ if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1)
&& addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
return 1;
+#endif
+#if L2_LENGTH != 0
+ if (addr >= L2_START + (_ebss_l2 - _stext_l2)
+ && addr + size <= L2_START + L2_LENGTH)
+ return 1;
#endif
return 0;
}
/* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
- l1_data_a_length = _ebss_l1 - _sdata_l1;
+ l1_data_a_length = _sbss_l1 - _sdata_l1;
if (l1_data_a_length > L1_DATA_A_LENGTH)
panic("L1 Data SRAM Bank A Overflow\n");
- /* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+ /* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
- l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+ l1_data_b_length = _sbss_b_l1 - _sdata_b_l1;
if (l1_data_b_length > L1_DATA_B_LENGTH)
panic("L1 Data SRAM Bank B Overflow\n");
- /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+ /* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
l1_data_a_length, l1_data_b_length);
if (L2_LENGTH != 0) {
- l2_length = _ebss_l2 - _stext_l2;
+ l2_length = _sbss_l2 - _stext_l2;
if (l2_length > L2_LENGTH)
panic("L2 SRAM Overflow\n");
printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
bfin_compiled_revid(), bfin_revid());
}
- if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
+ if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
CPU, bfin_revid());
}
#endif
-#ifdef CONFIG_VERBOSE_DEBUG
+#ifdef CONFIG_DEBUG_VERBOSE
#define verbose_printk(fmt, arg...) \
printk(fmt, ##arg)
#else
char *name = p->comm;
struct file *file = vma->vm_file;
- if (file)
- name = d_path(&file->f_path, _tmpbuf,
+ if (file) {
+ char *d_name = d_path(&file->f_path, _tmpbuf,
sizeof(_tmpbuf));
+ if (!IS_ERR(d_name))
+ name = d_name;
+ }
/* FLAT does not have its text aligned to the start of
* the map while FDPIC ELF does ...
#endif
panic("Kernel exception");
} else {
-#ifdef CONFIG_VERBOSE_DEBUG
+#ifdef CONFIG_DEBUG_VERBOSE
unsigned long *stack;
/* Dump the user space stack */
stack = (unsigned long *)rdusp();
*/
.macro do_flush flushins:req optflushins optnopins label
+ R2 = -L1_CACHE_BYTES;
+
+ /* start = (start & -L1_CACHE_BYTES) */
+ R0 = R0 & R2;
+
/* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
R1 += -1;
- R2 = -L1_CACHE_BYTES;
R1 = R1 & R2;
R1 += L1_CACHE_BYTES;
/* Flush all cache lines assocoiated with this area of memory. */
ENTRY(_blackfin_icache_dcache_flush_range)
- do_flush IFLUSH, FLUSH
+ do_flush FLUSH, IFLUSH
ENDPROC(_blackfin_icache_dcache_flush_range)
/* Throw away all D-cached data in specified region without any obligation to
/**************************************************************************/
-static unsigned int bfin_getfreq(unsigned int cpu)
+static unsigned int bfin_getfreq_khz(unsigned int cpu)
{
/* The driver only support single cpu */
if (cpu != 0)
return -1;
- return get_cclk();
+ return get_cclk() / 1000;
}
cclk_hz = bfin_freq_table[index].frequency;
- freqs.old = bfin_getfreq(0);
+ freqs.old = bfin_getfreq_khz(0);
freqs.new = cclk_hz;
freqs.cpu = 0;
if (policy->cpu != 0)
return -EINVAL;
- cclk = get_cclk();
- sclk = get_sclk();
+ cclk = get_cclk() / 1000;
+ sclk = get_sclk() / 1000;
#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE))
min_cclk = sclk * 2;
dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */
dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1;
- pr_debug("cpufreq: freq:%d csel:%d tscale:%d\n",
+ pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n",
bfin_freq_table[index].frequency,
dpm_state_table[index].csel,
dpm_state_table[index].tscale);
static struct cpufreq_driver bfin_driver = {
.verify = bfin_verify_speed,
.target = bfin_target,
- .get = bfin_getfreq,
+ .get = bfin_getfreq_khz,
.init = __bfin_cpu_init,
.name = "bfin cpufreq",
.owner = THIS_MODULE,
p5.h = hi(ILAT);
r6 = [p5];
r7 = 0x20; /* Did I just cause anther HW error? */
- r7 = r7 & r1;
+ r6 = r7 & r6;
CC = R7 == R6;
if CC JUMP _double_fault;
#endif
return;
}
- free_l2_sram_head.next->paddr = (void *)L2_START +
- (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
- free_l2_sram_head.next->size = L2_LENGTH -
- (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+ free_l2_sram_head.next->paddr =
+ (void *)L2_START + (_ebss_l2 - _stext_l2);
+ free_l2_sram_head.next->size =
+ L2_LENGTH - (_ebss_l2 - _stext_l2);
free_l2_sram_head.next->pid = 0;
free_l2_sram_head.next->next = NULL;
/************************************************/
#define ia64_ssm IA64_INTRINSIC_MACRO(ssm)
#define ia64_rsm IA64_INTRINSIC_MACRO(rsm)
-#define ia64_getreg IA64_INTRINSIC_API(getreg)
+#define ia64_getreg IA64_INTRINSIC_MACRO(getreg)
#define ia64_setreg IA64_INTRINSIC_API(setreg)
#define ia64_set_rr IA64_INTRINSIC_API(set_rr)
#define ia64_get_rr IA64_INTRINSIC_API(get_rr)
ia64_native_rsm(mask); \
} while (0)
+/* returned ip value should be the one in the caller,
+ * not in __paravirt_getreg() */
+#define paravirt_getreg(reg) \
+ ({ \
+ unsigned long res; \
+ BUILD_BUG_ON(!__builtin_constant_p(reg)); \
+ if ((reg) == _IA64_REG_IP) \
+ res = ia64_native_getreg(_IA64_REG_IP); \
+ else \
+ res = pv_cpu_ops.getreg(reg); \
+ res; \
+ })
+
/******************************************************************************
* replacement of hand written assembly codes.
*/
END(prefetch_stack)
GLOBAL_ENTRY(kernel_execve)
+ rum psr.ac
mov r15=__NR_execve // put syscall number in place
break __BREAK_SYSCALL
br.ret.sptk.many rp
* Switch into virtual mode:
*/
movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
- |IA64_PSR_DI)
+ |IA64_PSR_DI|IA64_PSR_AC)
;;
mov cr.ipsr=r16
movl r17=1f
return previous_current;
no_mod:
- printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
+ mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
smp_processor_id(), type, msg);
return previous_current;
}
unsigned long res = -1;
switch (regnum) {
CASE_GET_REG(GP);
- CASE_GET_REG(IP);
+ /*CASE_GET_REG(IP);*/ /* returned ip value shouldn't be constant */
CASE_GET_REG(PSR);
CASE_GET_REG(TP);
CASE_GET_REG(SP);
#include <linux/kernel.h>
#include <asm/page.h>
-#include <asm/iommu.h>
dma_addr_t bad_dma_address __read_mostly;
EXPORT_SYMBOL(bad_dma_address);
__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR)
#ifdef CONFIG_IA32_SUPPORT
-__HCALL1(xen_get_eflag, HYPERPRIVOP_GET_EFLAG)
+__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG)
__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8
#endif /* CONFIG_IA32_SUPPORT */
{
int i;
- BUG_ON(IRQ_USER + cnt >= NR_IRQS);
+ BUG_ON(IRQ_USER + cnt > NR_IRQS);
m68k_first_user_vec = vec;
for (i = 0; i < cnt; i++)
irq_controller[IRQ_USER + i] = &user_irq_controller;
extern unsigned get_434_reg(unsigned reg_offs);
extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask);
extern unsigned char get_latch_u5(void);
+extern void rb532_gpio_set_ilevel(int bit, unsigned gpio);
+extern void rb532_gpio_set_istat(int bit, unsigned gpio);
#endif /* _RC32434_GPIO_H_ */
#define BTCS 0x010040
#define BTCOMPARE 0x010044
#define GPIOBASE 0x050000
-#define GPIOCFG 0x050004
-#define GPIOD 0x050008
-#define GPIOILEVEL 0x05000C
-#define GPIOISTAT 0x050010
-#define GPIONMIEN 0x050014
-#define IMASK6 0x038038
+/* Offsets relative to GPIOBASE */
+#define GPIOFUNC 0x00
+#define GPIOCFG 0x04
+#define GPIOD 0x08
+#define GPIOILEVEL 0x0C
+#define GPIOISTAT 0x10
+#define GPIONMIEN 0x14
+#define IMASK6 0x38
#define LO_WPX (1 << 0)
#define LO_ALE (1 << 1)
#define LO_CLE (1 << 2)
/*
* Initialize the count register as a clocksource
*/
-#ifdef CONFIG_CEVT_R4K
+#ifdef CONFIG_CSRC_R4K
extern int init_mips_clocksource(void);
#else
static inline int init_mips_clocksource(void)
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
- /* Calclate a somewhat reasonable rating value */
+ /* Calculate a somewhat reasonable rating value */
clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
/* XXX Check with wje if the Indy caches can differenciate between
writeback + invalidate and just invalidate. */
-struct bcache_ops indy_sc_ops = {
+static struct bcache_ops indy_sc_ops = {
.bc_enable = indy_sc_enable,
.bc_disable = indy_sc_disable,
.bc_wback_inv = indy_sc_wback_invalidate,
#include <linux/init.h>
#include <linux/smp.h>
-#include <asm-mips/addrspace.h>
-#include <asm-mips/mips-boards/launch.h>
-#include <asm-mips/mipsmtregs.h>
+#include <asm/addrspace.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/mipsmtregs.h>
int amon_cpu_avail(int cpu)
{
/* Resources and device for NAND */
static int rb532_dev_ready(struct mtd_info *mtd)
{
- return readl(IDT434_REG_BASE + GPIOD) & GPIO_RDY;
+ return gpio_get_value(GPIO_RDY);
}
static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
struct rb532_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase;
- void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value);
- int (*get_int_level)(struct gpio_chip *chip, unsigned offset);
- void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value);
- int (*get_int_status)(struct gpio_chip *chip, unsigned offset);
};
struct mpmc_device dev3;
}
EXPORT_SYMBOL(get_latch_u5);
+/* rb532_set_bit - sanely set a bit
+ *
+ * bitval: new value for the bit
+ * offset: bit index in the 4 byte address range
+ * ioaddr: 4 byte aligned address being altered
+ */
+static inline void rb532_set_bit(unsigned bitval,
+ unsigned offset, void __iomem *ioaddr)
+{
+ unsigned long flags;
+ u32 val;
+
+ bitval = !!bitval; /* map parameter to {0,1} */
+
+ local_irq_save(flags);
+
+ val = readl(ioaddr);
+ val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */
+ val |= ( bitval << offset ); /* set bit if bitval == 1 */
+ writel(val, ioaddr);
+
+ local_irq_restore(flags);
+}
+
+/* rb532_get_bit - read a bit
+ *
+ * returns the boolean state of the bit, which may be > 1
+ */
+static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr)
+{
+ return (readl(ioaddr) & (1 << offset));
+}
+
/*
* Return GPIO level */
static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- u32 mask = 1 << offset;
struct rb532_gpio_chip *gpch;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOD) & mask;
+ return rb532_get_bit(offset, gpch->regbase + GPIOD);
}
/*
static void rb532_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
struct rb532_gpio_chip *gpch;
- void __iomem *gpvr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpvr = gpch->regbase + GPIOD;
-
- local_irq_save(flags);
- tmp = readl(gpvr);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpvr);
- local_irq_restore(flags);
+ rb532_set_bit(value, offset, gpch->regbase + GPIOD);
}
/*
*/
static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 value;
struct rb532_gpio_chip *gpch;
- void __iomem *gpdr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpdr = gpch->regbase + GPIOCFG;
- local_irq_save(flags);
- value = readl(gpdr);
- value &= ~mask;
- writel(value, gpdr);
- local_irq_restore(flags);
+ if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
+ return 1; /* alternate function, GPIOCFG is ignored */
+ rb532_set_bit(0, offset, gpch->regbase + GPIOCFG);
return 0;
}
static int rb532_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
struct rb532_gpio_chip *gpch;
- void __iomem *gpdr;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- writel(mask, gpch->regbase + GPIOD);
- gpdr = gpch->regbase + GPIOCFG;
- local_irq_save(flags);
- tmp = readl(gpdr);
- tmp |= mask;
- writel(tmp, gpdr);
- local_irq_restore(flags);
+ if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
+ return 1; /* alternate function, GPIOCFG is ignored */
+ /* set the initial output value */
+ rb532_set_bit(value, offset, gpch->regbase + GPIOD);
+
+ rb532_set_bit(1, offset, gpch->regbase + GPIOCFG);
return 0;
}
-/*
- * Set the GPIO interrupt level
- */
-static void rb532_gpio_set_int_level(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
- struct rb532_gpio_chip *gpch;
- void __iomem *gpil;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpil = gpch->regbase + GPIOILEVEL;
-
- local_irq_save(flags);
- tmp = readl(gpil);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpil);
- local_irq_restore(flags);
-}
+static struct rb532_gpio_chip rb532_gpio_chip[] = {
+ [0] = {
+ .chip = {
+ .label = "gpio0",
+ .direction_input = rb532_gpio_direction_input,
+ .direction_output = rb532_gpio_direction_output,
+ .get = rb532_gpio_get,
+ .set = rb532_gpio_set,
+ .base = 0,
+ .ngpio = 32,
+ },
+ },
+};
/*
- * Get the GPIO interrupt level
+ * Set GPIO interrupt level
*/
-static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset)
+void rb532_gpio_set_ilevel(int bit, unsigned gpio)
{
- u32 mask = 1 << offset;
- struct rb532_gpio_chip *gpch;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOILEVEL) & mask;
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOILEVEL);
}
+EXPORT_SYMBOL(rb532_gpio_set_ilevel);
/*
- * Set the GPIO interrupt status
+ * Set GPIO interrupt status
*/
-static void rb532_gpio_set_int_status(struct gpio_chip *chip,
- unsigned offset, int value)
+void rb532_gpio_set_istat(int bit, unsigned gpio)
{
- unsigned long flags;
- u32 mask = 1 << offset;
- u32 tmp;
- struct rb532_gpio_chip *gpch;
- void __iomem *gpis;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- gpis = gpch->regbase + GPIOISTAT;
-
- local_irq_save(flags);
- tmp = readl(gpis);
- if (value)
- tmp |= mask;
- else
- tmp &= ~mask;
- writel(tmp, gpis);
- local_irq_restore(flags);
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOISTAT);
}
+EXPORT_SYMBOL(rb532_gpio_set_istat);
/*
- * Get the GPIO interrupt status
+ * Configure GPIO alternate function
*/
-static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset)
+static void rb532_gpio_set_func(int bit, unsigned gpio)
{
- u32 mask = 1 << offset;
- struct rb532_gpio_chip *gpch;
-
- gpch = container_of(chip, struct rb532_gpio_chip, chip);
- return readl(gpch->regbase + GPIOISTAT) & mask;
+ rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC);
}
-static struct rb532_gpio_chip rb532_gpio_chip[] = {
- [0] = {
- .chip = {
- .label = "gpio0",
- .direction_input = rb532_gpio_direction_input,
- .direction_output = rb532_gpio_direction_output,
- .get = rb532_gpio_get,
- .set = rb532_gpio_set,
- .base = 0,
- .ngpio = 32,
- },
- .get_int_level = rb532_gpio_get_int_level,
- .set_int_level = rb532_gpio_set_int_level,
- .get_int_status = rb532_gpio_get_int_status,
- .set_int_status = rb532_gpio_set_int_status,
- },
-};
-
int __init rb532_gpio_init(void)
{
struct resource *r;
return -ENXIO;
}
- /* Set the interrupt status and level for the CF pin */
- rb532_gpio_set_int_level(&rb532_gpio_chip->chip, CF_GPIO_NUM, 1);
- rb532_gpio_set_int_status(&rb532_gpio_chip->chip, CF_GPIO_NUM, 0);
+ /* configure CF_GPIO_NUM as CFRDY IRQ source */
+ rb532_gpio_set_func(0, CF_GPIO_NUM);
+ rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM);
+ rb532_gpio_set_ilevel(1, CF_GPIO_NUM);
+ rb532_gpio_set_istat(0, CF_GPIO_NUM);
return 0;
}
#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */
-extern unsigned long cpu_present_mask;
-
#define raw_smp_processor_id() (current_thread_info()->cpu)
#else /* CONFIG_SMP */
* being 64 bit in both cases.
*/
-static long translate_usr_offset(long offset)
+static compat_ulong_t translate_usr_offset(compat_ulong_t offset)
{
if (offset < 0)
- return -1;
+ return sizeof(struct pt_regs);
else if (offset <= 32*4) /* gr[0..31] */
return offset * 2 + 4;
else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
else if (offset < sizeof(struct pt_regs)/2 + 32*4)
return offset * 2 + 4 - 32*8;
else
- return -1;
+ return sizeof(struct pt_regs);
}
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
if (addr & (sizeof(compat_uint_t)-1))
break;
addr = translate_usr_offset(addr);
- if (addr < 0)
+ if (addr >= sizeof(struct pt_regs))
break;
tmp = *(compat_uint_t *) ((char *) task_regs(child) + addr);
if (addr & (sizeof(compat_uint_t)-1))
break;
addr = translate_usr_offset(addr);
- if (addr < 0)
+ if (addr >= sizeof(struct pt_regs))
break;
if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
/* Special case, fp regs are 64 bits anyway */
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
- l %r1,BASED(.Ltrace_irq_on)
+ basr %r2,%r0
+ l %r1,BASED(.Ltrace_irq_on_caller)
basr %r14,%r1
.endm
.macro TRACE_IRQS_OFF
- l %r1,BASED(.Ltrace_irq_off)
+ basr %r2,%r0
+ l %r1,BASED(.Ltrace_irq_off_caller)
basr %r14,%r1
.endm
.macro TRACE_IRQS_CHECK
+ basr %r2,%r0
tm SP_PSW(%r15),0x03 # irqs enabled?
jz 0f
- l %r1,BASED(.Ltrace_irq_on)
+ l %r1,BASED(.Ltrace_irq_on_caller)
basr %r14,%r1
j 1f
-0: l %r1,BASED(.Ltrace_irq_off)
+0: l %r1,BASED(.Ltrace_irq_off_caller)
basr %r14,%r1
1:
.endm
.Lschedtail: .long schedule_tail
.Lsysc_table: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
-.Ltrace_irq_on: .long trace_hardirqs_on
-.Ltrace_irq_off:
- .long trace_hardirqs_off
+.Ltrace_irq_on_caller:
+ .long trace_hardirqs_on_caller
+.Ltrace_irq_off_caller:
+ .long trace_hardirqs_off_caller
+#endif
+#ifdef CONFIG_LOCKDEP
.Llockdep_sys_exit:
.long lockdep_sys_exit
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
- brasl %r14,trace_hardirqs_on
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_on_caller
.endm
.macro TRACE_IRQS_OFF
- brasl %r14,trace_hardirqs_off
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_off_caller
.endm
.macro TRACE_IRQS_CHECK
+ basr %r2,%r0
tm SP_PSW(%r15),0x03 # irqs enabled?
jz 0f
- brasl %r14,trace_hardirqs_on
+ brasl %r14,trace_hardirqs_on_caller
j 1f
-0: brasl %r14,trace_hardirqs_off
+0: brasl %r14,trace_hardirqs_off_caller
1:
.endm
#else
return;
}
trace_hardirqs_on();
+ /* Don't trace preempt off for idle. */
+ stop_critical_timings();
/* Wait for external, I/O or machine check interrupt. */
__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT);
+ start_critical_timings();
}
void cpu_idle(void)
if (memory_chunk[i].type != CHUNK_READ_WRITE)
continue;
start_chunk = PFN_DOWN(memory_chunk[i].addr);
- end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1;
+ end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
end_chunk = min(end_chunk, end_pfn);
if (start_chunk >= end_chunk)
continue;
add_active_range(0, start_chunk, end_chunk);
pfn = max(start_chunk, start_pfn);
- for (; pfn <= end_chunk; pfn++)
+ for (; pfn < end_chunk; pfn++)
page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
}
{
int ret = sys_newuname(name);
- if (current->personality == PER_LINUX32 && !ret) {
+ if (personality(current->personality) == PER_LINUX32 && !ret) {
ret = copy_to_user(name->machine, "s390\0\0\0\0", 8);
if (ret) ret = -EFAULT;
}
static struct timer_list topology_timer;
static void set_topology_timer(void);
static DECLARE_WORK(topology_work, topology_work_fn);
+/* topology_lock protects the core linked list */
+static DEFINE_SPINLOCK(topology_lock);
cpumask_t cpu_core_map[NR_CPUS];
cpumask_t cpu_coregroup_map(unsigned int cpu)
{
struct core_info *core = &core_info;
+ unsigned long flags;
cpumask_t mask;
cpus_clear(mask);
if (!machine_has_topology)
return cpu_present_map;
- mutex_lock(&smp_cpu_state_mutex);
+ spin_lock_irqsave(&topology_lock, flags);
while (core) {
if (cpu_isset(cpu, core->mask)) {
mask = core->mask;
}
core = core->next;
}
- mutex_unlock(&smp_cpu_state_mutex);
+ spin_unlock_irqrestore(&topology_lock, flags);
if (cpus_empty(mask))
mask = cpumask_of_cpu(cpu);
return mask;
union tl_entry *tle, *end;
struct core_info *core = &core_info;
- mutex_lock(&smp_cpu_state_mutex);
+ spin_lock_irq(&topology_lock);
clear_cores();
tle = info->tle;
end = (union tl_entry *)((unsigned long)info + info->length);
}
tle = next_tle(tle);
}
- mutex_unlock(&smp_cpu_state_mutex);
+ spin_unlock_irq(&topology_lock);
}
static void topology_update_polarization_simple(void)
*/
#define xlate_dev_kmem_ptr(p) p
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
#endif /* __KERNEL__ */
#endif /* __ASM_SH_IO_H */
extern void page_table_range_init(unsigned long start, unsigned long end,
pgd_t *pgd);
+#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
+extern void kmap_coherent_init(void);
+#else
+#define kmap_coherent_init() do { } while (0)
+#endif
+
#include <asm-generic/pgtable.h>
#endif /* __ASM_SH_PGTABLE_H */
},{
.mapbase = 0xa4e30000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 56, 56, 56, 56 },
},{
.mapbase = 0xa4e40000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 88, 88, 88, 88 },
},{
.mapbase = 0xa4e50000,
.flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
+ .type = PORT_SCIFA,
.irqs = { 109, 109, 109, 109 },
}, {
.flags = 0,
#endif
static struct uart_port scif_port = {
+ .type = PORT_SCIF,
.mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
.membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
};
while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
;
- sci_out(&scif_port, SCxTDR, c);
sci_in(&scif_port, SCxSR);
sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+ sci_out(&scif_port, SCxTDR, c);
while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
;
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+ ctrl_outl(tmu_latest_interval[TMU0], TMU0_TCOR);
break;
case CLOCK_EVT_MODE_ONESHOT:
ctrl_outl(0, TMU0_TCOR);
.section __ex_table, "a"; \
.long 9999b, 6000f ; \
.previous
+#define EX_NO_POP(...) \
+ 9999: __VA_ARGS__ ; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6005f ; \
+ .previous
ENTRY(__copy_user)
! Check if small number of bytes
mov #11,r0
bt 1f
2:
-EX( mov.b @r5+,r0 )
+EX_NO_POP( mov.b @r5+,r0 )
dt r6
-EX( mov.b r0,@r4 )
+EX_NO_POP( mov.b r0,@r4 )
bf/s 2b
add #1,r4
# Exception handler:
.section .fixup, "ax"
-6000:
+6005:
mov.l 8000f,r1
mov r3,r0
jmp @r1
# Makefile for the Linux SuperH-specific parts of the memory manager.
#
-obj-y := init.o extable_32.o consistent.o
+obj-y := init.o extable_32.o consistent.o mmap.o
ifndef CONFIG_CACHE_OFF
cache-$(CONFIG_CPU_SH2) := cache-sh2.o
# Makefile for the Linux SuperH-specific parts of the memory manager.
#
-obj-y := init.o consistent.o
+obj-y := init.o consistent.o mmap.o
mmu-y := tlb-nommu.o pg-nommu.o extable_32.o
mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \
void __init paging_init(void)
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
+ unsigned long vaddr;
int nid;
/* We don't need to map the kernel through the TLB, as
* check for a null value. */
set_TTB(swapper_pg_dir);
- /* Populate the relevant portions of swapper_pg_dir so that
+ /*
+ * Populate the relevant portions of swapper_pg_dir so that
* we can use the fixmap entries without calling kmalloc.
- * pte's will be filled in by __set_fixmap(). */
- page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir);
+ * pte's will be filled in by __set_fixmap().
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ page_table_range_init(vaddr, 0, swapper_pg_dir);
+
+ kmap_coherent_init();
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
--- /dev/null
+/*
+ * arch/sh/mm/mmap.c
+ *
+ * Copyright (C) 2008 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem. This
+ * might go away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t count)
+{
+ if (addr < __MEMORY_START)
+ return 0;
+ if (addr + count > __pa(high_memory))
+ return 0;
+
+ return 1;
+}
+
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+ return 1;
+}
* Released under the terms of the GNU GPL v2.0.
*/
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <linux/highmem.h>
#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
+
+static pte_t *kmap_coherent_pte;
+
+void __init kmap_coherent_init(void)
+{
+ unsigned long vaddr;
+
+ /* cache the first coherent kmap pte */
+ vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+ kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+
static inline void *kmap_coherent(struct page *page, unsigned long addr)
{
enum fixed_addresses idx;
update_mmu_cache(NULL, vaddr, pte);
+ set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
+
return (void *)vaddr;
}
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
+#ifndef __KERNEL__
cc_t c_cc[NCCS]; /* control characters */
-#ifdef __KERNEL__
+#else
+ cc_t c_cc[NCCS+2]; /* kernel needs 2 more to hold vmin/vtime */
#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
- cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
#endif
};
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- cc_t _x_cc[2]; /* padding to match ktermios */
+ cc_t c_cc[NCCS+2]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
+ cc_t c_cc[NCCS+2]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
#define __NR_dup3 320
#define __NR_pipe2 321
#define __NR_inotify_init1 322
+#define __NR_accept4 323
-#define NR_SYSCALLS 323
+#define NR_SYSCALLS 324
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
* it never had the plain ones and there is no value to adding those
#define __NR_dup3 320
#define __NR_pipe2 321
#define __NR_inotify_init1 322
+#define __NR_accept4 323
-#define NR_SYSCALLS 323
+#define NR_SYSCALLS 324
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
op->dev.parent = parent;
op->dev.bus = &of_platform_bus_type;
if (!parent)
- strcpy(op->dev.bus_id, "root");
+ dev_set_name(&op->dev, "root");
else
- sprintf(op->dev.bus_id, "%08x", dp->node);
+ dev_set_name(&op->dev, "%08x", dp->node);
if (of_device_register(op)) {
printk("%s: Could not register of device.\n",
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
sys32_socketcall: /* %o0=call, %o1=args */
cmp %o0, 1
bl,pn %xcc, do_einval
- cmp %o0, 17
+ cmp %o0, 18
bg,pn %xcc, do_einval
sub %o0, 1, %o0
sllx %o0, 5, %o0
nop
nop
nop
+do_sys_accept4: /* sys_accept4(int, struct sockaddr *, int *, int) */
+63: ldswa [%o1 + 0x0] %asi, %o0
+ sethi %hi(sys_accept4), %g1
+64: lduwa [%o1 + 0x8] %asi, %o2
+65: ldswa [%o1 + 0xc] %asi, %o3
+ jmpl %g1 + %lo(sys_accept4), %g0
+66: lduwa [%o1 + 0x4] %asi, %o1
+ nop
+ nop
.section __ex_table,"a"
.align 4
.word 57b, __retl_efault, 58b, __retl_efault
.word 59b, __retl_efault, 60b, __retl_efault
.word 61b, __retl_efault, 62b, __retl_efault
+ .word 63b, __retl_efault, 64b, __retl_efault
+ .word 65b, __retl_efault, 66b, __retl_efault
.previous
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
#endif /* CONFIG_COMPAT */
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
extern void block_signals(void);
extern void unblock_signals(void);
-#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \
(flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \
set_signals(flags); } while(0)
-#define local_irq_save(flags) do { local_save_flags(flags); \
- local_irq_disable(); } while(0)
+#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \
+ raw_local_irq_disable(); } while(0)
-#define local_irq_enable() unblock_signals()
-#define local_irq_disable() block_signals()
+#define raw_local_irq_enable() unblock_signals()
+#define raw_local_irq_disable() block_signals()
#define irqs_disabled() \
({ \
unsigned long flags; \
- local_save_flags(flags); \
+ raw_local_save_flags(flags); \
(flags == 0); \
})
config X86_SMP
bool
depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64)
- select USE_GENERIC_SMP_HELPERS
default y
+config USE_GENERIC_SMP_HELPERS
+ def_bool y
+ depends on SMP
+
config X86_32_SMP
def_bool y
depends on X86_32 && SMP
config NUMA
bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)"
depends on SMP
- depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && BROKEN)
+ depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
help
--- /dev/null
+/*
+ * Copyright © 2008 Ingo Molnar
+ *
+ * This program 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.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+void *
+iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+
+void
+iounmap_atomic(void *kvaddr, enum km_type type);
extern struct dma_mapping_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;
-extern int dmar_disabled;
extern unsigned long iommu_nr_pages(unsigned long addr, unsigned long len);
extern int early_pfn_to_nid(unsigned long pfn);
+extern void resume_map_numa_kva(pgd_t *pgd);
+
#else /* !CONFIG_NUMA */
#define get_memcfg_numa get_memcfg_numa_flat
+static inline void resume_map_numa_kva(pgd_t *pgd) {}
+
#endif /* CONFIG_NUMA */
#ifdef CONFIG_DISCONTIGMEM
int __ret_gu; \
unsigned long __val_gu; \
__chk_user_ptr(ptr); \
+ might_fault(); \
switch (sizeof(*(ptr))) { \
case 1: \
__get_user_x(1, __ret_gu, __val_gu, ptr); \
int __ret_pu; \
__typeof__(*(ptr)) __pu_val; \
__chk_user_ptr(ptr); \
+ might_fault(); \
__pu_val = x; \
switch (sizeof(*(ptr))) { \
case 1: \
static __always_inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
- might_sleep();
- return __copy_to_user_inatomic(to, from, n);
+ might_fault();
+ return __copy_to_user_inatomic(to, from, n);
}
static __always_inline unsigned long
static __always_inline unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
- might_sleep();
+ might_fault();
if (__builtin_constant_p(n)) {
unsigned long ret;
static __always_inline unsigned long __copy_from_user_nocache(void *to,
const void __user *from, unsigned long n)
{
- might_sleep();
+ might_fault();
if (__builtin_constant_p(n)) {
unsigned long ret;
int __copy_from_user(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
+
+ might_fault();
if (!__builtin_constant_p(size))
return copy_user_generic(dst, (__force void *)src, size);
switch (size) {
return ret;
case 10:
__get_user_asm(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 16);
+ ret, "q", "", "=r", 10);
if (unlikely(ret))
return ret;
__get_user_asm(*(u16 *)(8 + (char *)dst),
int __copy_to_user(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
+
+ might_fault();
if (!__builtin_constant_p(size))
return copy_user_generic((__force void *)dst, src, size);
switch (size) {
int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
{
int ret = 0;
+
+ might_fault();
if (!__builtin_constant_p(size))
return copy_user_generic((__force void *)dst,
(__force void *)src, size);
__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
#define __NR_timerfd_gettime 287
__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
-#define __NR_paccept 288
-__SYSCALL(__NR_paccept, sys_paccept)
+#define __NR_accept4 288
+__SYSCALL(__NR_accept4, sys_accept4)
#define __NR_signalfd4 289
__SYSCALL(__NR_signalfd4, sys_signalfd4)
#define __NR_eventfd2 290
address >>= PAGE_SHIFT;
iommu_area_free(dom->bitmap, address, pages);
- if (address + pages >= dom->next_bit)
+ if (address >= dom->next_bit)
dom->need_flush = true;
}
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
-int amd_iommu_isolate; /* if 1, device isolation is enabled */
+int amd_iommu_isolate = 1; /* if 1, device isolation is enabled */
bool amd_iommu_unmap_flush; /* if true, flush on every unmap */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
for (; *str; ++str) {
if (strncmp(str, "isolate", 7) == 0)
amd_iommu_isolate = 1;
- if (strncmp(str, "fullflush", 11) == 0)
+ if (strncmp(str, "share", 5) == 0)
+ amd_iommu_isolate = 0;
+ if (strncmp(str, "fullflush", 9) == 0)
amd_iommu_unmap_flush = true;
}
struct ds_context *context = *p_context;
if (!context) {
+ spin_unlock(&ds_lock);
+
context = kzalloc(sizeof(*context), GFP_KERNEL);
- if (!context)
+ if (!context) {
+ spin_lock(&ds_lock);
return NULL;
+ }
context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL);
if (!context->ds) {
kfree(context);
+ spin_lock(&ds_lock);
return NULL;
}
+ spin_lock(&ds_lock);
+ /*
+ * Check for race - another CPU could have allocated
+ * it meanwhile:
+ */
+ if (*p_context) {
+ kfree(context->ds);
+ kfree(context);
+ return *p_context;
+ }
+
*p_context = context;
context->this = p_context;
spin_lock(&ds_lock);
- if (!check_tracer(task))
- return -EPERM;
-
error = -ENOMEM;
context = ds_alloc_context(task);
if (!context)
goto out_unlock;
+ error = -EPERM;
+ if (!check_tracer(task))
+ goto out_unlock;
+
error = -EALREADY;
if (context->owner[qual] == current)
goto out_unlock;
}
#endif
-#ifdef CONFIG_DMAR
-static void __init intel_g33_dmar(int num, int slot, int func)
-{
- struct acpi_table_header *dmar_tbl;
- acpi_status status;
-
- status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl);
- if (ACPI_SUCCESS(status)) {
- printk(KERN_INFO "BIOS BUG: DMAR advertised on Intel G31/G33 chipset -- ignoring\n");
- dmar_disabled = 1;
- }
-}
-#endif
-
#define QFLAG_APPLY_ONCE 0x1
#define QFLAG_APPLIED 0x2
#define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED)
PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd },
-#ifdef CONFIG_DMAR
- { PCI_VENDOR_ID_INTEL, 0x29c0,
- PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar },
-#endif
{}
};
{
struct acpi_table_header *header = NULL;
int i = 0;
- acpi_size tbl_size;
- while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) {
+ while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) {
if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
struct oem_table *t = (struct oem_table *)header;
oem_addrX = t->OEMTableAddr;
oem_size = t->OEMTableSize;
- early_acpi_os_unmap_memory(header, tbl_size);
*oem_addr = (unsigned long)__acpi_map_table(oem_addrX,
oem_size);
return 0;
}
- early_acpi_os_unmap_memory(header, tbl_size);
}
return -1;
}
void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
{
- if (!oem_addr)
- return;
-
- __acpi_unmap_table((char *)oem_addr, oem_size);
}
#endif
cfg->vector = 0;
cpus_clear(cfg->domain);
+
+ if (likely(!cfg->move_in_progress))
+ return;
+ cpus_and(mask, cfg->old_domain, cpu_online_map);
+ for_each_cpu_mask_nr(cpu, mask) {
+ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
+ vector++) {
+ if (per_cpu(vector_irq, cpu)[vector] != irq)
+ continue;
+ per_cpu(vector_irq, cpu)[vector] = -1;
+ break;
+ }
+ }
+ cfg->move_in_progress = 0;
}
void __setup_vector_irq(int cpu)
DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
},
},
+ { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
+ .callback = set_bios_reboot,
+ .ident = "Dell OptiPlex 330",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
+ DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
+ },
+ },
{ /* Handle problems with rebooting on Dell 2400's */
.callback = set_bios_reboot,
.ident = "Dell PowerEdge 2400",
.callback = dmi_low_memory_corruption,
.ident = "Phoenix BIOS",
.matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
},
},
#endif
cycles_t start, now, prev, end;
int i;
+ rdtsc_barrier();
start = get_cycles();
+ rdtsc_barrier();
/*
* The measurement runs for 20 msecs:
*/
*/
__raw_spin_lock(&sync_lock);
prev = last_tsc;
+ rdtsc_barrier();
now = get_cycles();
+ rdtsc_barrier();
last_tsc = now;
__raw_spin_unlock(&sync_lock);
#define __do_strncpy_from_user(dst, src, count, res) \
do { \
int __d0, __d1, __d2; \
- might_sleep(); \
+ might_fault(); \
__asm__ __volatile__( \
" testl %1,%1\n" \
" jz 2f\n" \
#define __do_clear_user(addr,size) \
do { \
int __d0; \
- might_sleep(); \
+ might_fault(); \
__asm__ __volatile__( \
"0: rep; stosl\n" \
" movl %2,%0\n" \
unsigned long
clear_user(void __user *to, unsigned long n)
{
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_WRITE, to, n))
__do_clear_user(to, n);
return n;
unsigned long mask = -__addr_ok(s);
unsigned long res, tmp;
- might_sleep();
+ might_fault();
__asm__ __volatile__(
" testl %0, %0\n"
#define __do_strncpy_from_user(dst,src,count,res) \
do { \
long __d0, __d1, __d2; \
- might_sleep(); \
+ might_fault(); \
__asm__ __volatile__( \
" testq %1,%1\n" \
" jz 2f\n" \
unsigned long __clear_user(void __user *addr, unsigned long size)
{
long __d0;
- might_sleep();
+ might_fault();
/* no memory constraint because it doesn't change any memory gcc knows
about */
asm volatile(
* This file provides all the same external entries as smp.c but uses
* the voyager hal to provide the functionality
*/
+#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kernel_stat.h>
x86_write_percpu(cpu_number, hard_smp_processor_id());
}
+static void voyager_send_call_func(cpumask_t callmask)
+{
+ __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
+ send_CPI(mask, VIC_CALL_FUNCTION_CPI);
+}
+
+static void voyager_send_call_func_single(int cpu)
+{
+ send_CPI(1 << cpu, VIC_CALL_FUNCTION_SINGLE_CPI);
+}
+
struct smp_ops smp_ops = {
.smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu,
.smp_prepare_cpus = voyager_smp_prepare_cpus,
.smp_send_stop = voyager_smp_send_stop,
.smp_send_reschedule = voyager_smp_send_reschedule,
- .send_call_func_ipi = native_send_call_func_ipi,
- .send_call_func_single_ipi = native_send_call_func_single_ipi,
+ .send_call_func_ipi = voyager_send_call_func,
+ .send_call_func_single_ipi = voyager_send_call_func_single,
};
}
}
+#ifdef CONFIG_HIBERNATION
+/**
+ * resume_map_numa_kva - add KVA mapping to the temporary page tables created
+ * during resume from hibernation
+ * @pgd_base - temporary resume page directory
+ */
+void resume_map_numa_kva(pgd_t *pgd_base)
+{
+ int node;
+
+ for_each_online_node(node) {
+ unsigned long start_va, start_pfn, size, pfn;
+
+ start_va = (unsigned long)node_remap_start_vaddr[node];
+ start_pfn = node_remap_start_pfn[node];
+ size = node_remap_size[node];
+
+ printk(KERN_DEBUG "%s: node %d\n", __FUNCTION__, node);
+
+ for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) {
+ unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
+ pgd_t *pgd = pgd_base + pgd_index(vaddr);
+ pud_t *pud = pud_offset(pgd, vaddr);
+ pmd_t *pmd = pmd_offset(pud, vaddr);
+
+ set_pmd(pmd, pfn_pmd(start_pfn + pfn,
+ PAGE_KERNEL_LARGE_EXEC));
+
+ printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n",
+ __FUNCTION__, vaddr, start_pfn + pfn);
+ }
+ }
+}
+#endif
+
static unsigned long calculate_numa_remap_pages(void)
{
int nid;
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/mmzone.h>
/* Defined in hibernate_asm_32.S */
extern int restore_image(void);
}
}
}
+
+ resume_map_numa_kva(pgd_base);
+
return 0;
}
return PTR_ERR(bio);
if (bio->bi_size != len) {
+ /*
+ * Grab an extra reference to this bio, as bio_unmap_user()
+ * expects to be able to drop it twice as it happens on the
+ * normal IO completion path
+ */
+ bio_get(bio);
bio_endio(bio, 0);
bio_unmap_user(bio);
return -EINVAL;
bdev_map = kobj_map_init(base_probe, &block_class_lock);
blk_dev_init();
+ register_blkdev(BLOCK_EXT_MAJOR, "blkext");
+
#ifndef CONFIG_SYSFS_DEPRECATED
/* create top-level block dir */
block_depr = kobject_create_and_add("block", NULL);
struct disk_part_iter piter;
long long start, length;
int partno;
- int err;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
disk_part_iter_exit(&piter);
/* all seems OK */
- err = add_partition(disk, partno, start, length,
- ADDPART_FLAG_NONE);
+ part = add_partition(disk, partno, start, length,
+ ADDPART_FLAG_NONE);
mutex_unlock(&bdev->bd_mutex);
- return err;
+ return IS_ERR(part) ? PTR_ERR(part) : 0;
case BLKPG_DEL_PARTITION:
part = disk_get_part(disk, partno);
if (!part)
dev->wakeup.state.enabled ? "enabled" : "disabled");
if (ldev)
seq_printf(seq, "%s:%s",
- dev_name(ldev) ? ldev->bus->name : "no-bus",
+ ldev->bus ? ldev->bus->name : "no-bus",
dev_name(ldev));
seq_printf(seq, "\n");
put_device(ldev);
/* ATA PIO protocol */
if (unlikely((status & ATA_DRQ) == 0)) {
/* handle BSY=0, DRQ=0 as error */
- if (likely(status & (ATA_ERR | ATA_DF)))
+ if (likely(status & (ATA_ERR | ATA_DF))) {
/* device stops HSM for abort/error */
qc->err_mask |= AC_ERR_DEV;
- else {
+
+ /* If diagnostic failed and this is
+ * IDENTIFY, it's likely a phantom
+ * device. Mark hint.
+ */
+ if (qc->dev->horkage &
+ ATA_HORKAGE_DIAGNOSTIC)
+ qc->err_mask |=
+ AC_ERR_NODEV_HINT;
+ } else {
/* HSM violation. Let EH handle this.
* Phantom devices also trigger this
* condition. Mark hint.
---help---
If you want to use the floppy disk drive(s) of your PC under Linux,
say Y. Information about this driver, especially important for IBM
- Thinkpad users, is contained in <file:Documentation/floppy.txt>.
+ Thinkpad users, is contained in
+ <file:Documentation/blockdev/floppy.txt>.
That file also contains the location of the Floppy driver FAQ as
well as location of the fdutils package used to configure additional
parameters of the driver at run time.
your computer's parallel port. Most of them are actually IDE devices
using a parallel port IDE adapter. This option enables the PARIDE
subsystem which contains drivers for many of these external drives.
- Read <file:Documentation/paride.txt> for more information.
+ Read <file:Documentation/blockdev/paride.txt> for more information.
If you have said Y to the "Parallel-port support" configuration
option, you may share a single port between your printer and other
help
This is the driver for Compaq Smart Array controllers. Everyone
using these boards should say Y here. See the file
- <file:Documentation/cpqarray.txt> for the current list of boards
- supported by this driver, and for further information on the use of
- this driver.
+ <file:Documentation/blockdev/cpqarray.txt> for the current list of
+ boards supported by this driver, and for further information on the
+ use of this driver.
config BLK_CPQ_CISS_DA
tristate "Compaq Smart Array 5xxx support"
help
This is the driver for Compaq Smart Array 5xxx controllers.
Everyone using these boards should say Y here.
- See <file:Documentation/cciss.txt> for the current list of
+ See <file:Documentation/blockdev/cciss.txt> for the current list of
boards supported by this driver, and for further information
on the use of this driver.
help
When enabled (Y), this option allows SCSI tape drives and SCSI medium
changers (tape robots) to be accessed via a Compaq 5xxx array
- controller. (See <file:Documentation/cciss.txt> for more details.)
+ controller. (See <file:Documentation/blockdev/cciss.txt> for more details.)
"SCSI support" and "SCSI tape support" must also be enabled for this
option to work.
help
This driver adds support for the Mylex DAC960, AcceleRAID, and
eXtremeRAID PCI RAID controllers. See the file
- <file:Documentation/README.DAC960> for further information about
- this driver.
+ <file:Documentation/blockdev/README.DAC960> for further information
+ about this driver.
To compile this driver as a module, choose M here: the
module will be called DAC960.
userland (making server and client physically the same computer,
communicating using the loopback network device).
- Read <file:Documentation/nbd.txt> for more information, especially
- about where to find the server code, which runs in user space and
- does not need special kernel support.
+ Read <file:Documentation/blockdev/nbd.txt> for more information,
+ especially about where to find the server code, which runs in user
+ space and does not need special kernel support.
Note that this has nothing to do with the network file systems NFS
or Coda; you can say N here even if you intend to use NFS or Coda.
store a copy of a minimal root file system off of a floppy into RAM
during the initial install of Linux.
- Note that the kernel command line option "ramdisk=XX" is now
- obsolete. For details, read <file:Documentation/ramdisk.txt>.
+ Note that the kernel command line option "ramdisk=XX" is now obsolete.
+ For details, read <file:Documentation/blockdev/ramdisk.txt>.
To compile this driver as a module, choose M here: the
module will be called rd.
h->maxSG = seg;
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n",
+ printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n",
creq->nr_sectors, seg);
#endif /* CCISS_DEBUG */
c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
#ifdef CCISS_DEBUG
- printk("address 0 = %x\n", c->paddr);
+ printk("address 0 = %lx\n", c->paddr);
#endif /* CCISS_DEBUG */
c->vaddr = remap_pci_mem(c->paddr, 0x250);
#endif /* CCISS_DEBUG */
cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
#ifdef CCISS_DEBUG
- printk("cfg base address index = %x\n", cfg_base_addr_index);
+ printk("cfg base address index = %llx\n",
+ (unsigned long long)cfg_base_addr_index);
#endif /* CCISS_DEBUG */
if (cfg_base_addr_index == -1) {
printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
#ifdef CCISS_DEBUG
- printk("cfg offset = %x\n", cfg_offset);
+ printk("cfg offset = %llx\n", (unsigned long long)cfg_offset);
#endif /* CCISS_DEBUG */
c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
cfg_base_addr_index) +
printk("\n");
} else
DPRINT("botched floppy option\n");
- DPRINT("Read Documentation/floppy.txt\n");
+ DPRINT("Read Documentation/blockdev/floppy.txt\n");
return 0;
}
/*
* Reset management
- * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
- * XXX Make usb_sync_reset asynchronous.
*/
static void ub_reset_enter(struct ub_dev *sc, int try)
spin_unlock_irqrestore(sc->lock, flags);
}
+/*
+ * XXX Reset brackets are too much hassle to implement, so just stub them
+ * in order to prevent forced unbinding (which deadlocks solid when our
+ * ->disconnect method waits for the reset to complete and this kills keventd).
+ *
+ * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device,
+ * or else the post_reset is invoked, and restats I/O on a locked device.
+ */
+static int ub_pre_reset(struct usb_interface *iface) {
+ return 0;
+}
+
+static int ub_post_reset(struct usb_interface *iface) {
+ return 0;
+}
+
/*
* This is called from a process context.
*/
.probe = ub_probe,
.disconnect = ub_disconnect,
.id_table = ub_usb_ids,
+ .pre_reset = ub_pre_reset,
+ .post_reset = ub_post_reset,
};
static int __init ub_init(void)
static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
{
struct request_queue *rq;
+ elevator_t *old_e;
rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
if (rq == NULL)
return -1;
- elevator_init(rq, "noop");
+ old_e = rq->elevator;
+ if (IS_ERR_VALUE(elevator_init(rq, "noop")))
+ printk(KERN_WARNING
+ "blkfront: Switch elevator failed, use default\n");
+ else
+ elevator_exit(old_e);
/* Hard sector size and max sectors impersonate the equiv. hardware. */
blk_queue_hardsect_size(rq, sector_size);
which give you many serial ports. You would need something like this
to connect more than two modems to your Linux box, for instance in
order to become a dial-in server. If you have a card like that, say
- Y here and read <file:Documentation/computone.txt>.
+ Y here and read <file:Documentation/serial/computone.txt>.
To compile this driver as module, choose M here: the
module will be called ip2.
This driver supports Comtrol RocketPort and RocketModem PCI boards.
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
modems. For information about the RocketPort/RocketModem boards
- and this driver read <file:Documentation/rocket.txt>.
+ and this driver read <file:Documentation/serial/rocket.txt>.
To compile this driver as a module, choose M here: the
module will be called rocket.
your Linux box, for instance in order to become a dial-in server.
For information about the Cyclades-Z card, read
- <file:Documentation/README.cycladesZ>.
+ <file:Documentation/serial/README.cycladesZ>.
To compile this driver as a module, choose M here: the
module will be called cyclades.
box, for instance in order to become a dial-in server. This driver
supports the original PC (ISA) boards as well as PCI, and EISA. If
you have a card like this, say Y here and read the file
- <file:Documentation/digiepca.txt>.
+ <file:Documentation/serial/digiepca.txt>.
To compile this driver as a module, choose M here: the
module will be called epca.
which gives you many serial ports. You would need something like
this to connect more than two modems to your Linux box, for instance
in order to become a dial-in server. If you have a card like that,
- say Y here and read the file <file:Documentation/riscom8.txt>.
+ say Y here and read the file <file:Documentation/serial/riscom8.txt>.
Also it's possible to say M here and compile this driver as kernel
loadable module; the module will be called riscom8.
your Linux box, for instance in order to become a dial-in server.
If you have a card like that, say Y here and read the file
- <file:Documentation/specialix.txt>. Also it's possible to say M here
- and compile this driver as kernel loadable module which will be
+ <file:Documentation/serial/specialix.txt>. Also it's possible to say
+ M here and compile this driver as kernel loadable module which will be
called specialix.
config SX
depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
This is a driver for the SX and SI multiport serial cards.
- Please read the file <file:Documentation/sx.txt> for details.
+ Please read the file <file:Documentation/serial/sx.txt> for details.
This driver can only be built as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
like this to connect more than two modems to your Linux box, for
instance in order to become a dial-in server. If you say Y here,
you will be asked for your specific card model in the next
- questions. Make sure to read <file:Documentation/stallion.txt> in
- this case. If you have never heard about all this, it's safe to
+ questions. Make sure to read <file:Documentation/serial/stallion.txt>
+ in this case. If you have never heard about all this, it's safe to
say N.
config STALLION
help
If you have an EasyIO or EasyConnection 8/32 multiport Stallion
card, then this is for you; say Y. Make sure to read
- <file:Documentation/stallion.txt>.
+ <file:Documentation/serial/stallion.txt>.
To compile this driver as a module, choose M here: the
module will be called stallion.
help
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
serial multiport card, say Y here. Make sure to read
- <file:Documentation/stallion.txt>.
+ <file:Documentation/serial/stallion.txt>.
To compile this driver as a module, choose M here: the
module will be called istallion.
/*
* There is a bunch of documentation about the card, jumpers, config
* settings, restrictions, cables, device names and numbers in
- * Documentation/specialix.txt
+ * Documentation/serial/specialix.txt
*/
#include <linux/module.h>
continue;
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
- seq_printf(s, " gpio-%-3d (%-12s) %s %s",
+ seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
gpio, gdesc->label,
is_out ? "out" : "in ",
chip->get
static struct apple_key_translation apple_fn_keys[] = {
{ KEY_BACKSPACE, KEY_DELETE },
+ { KEY_ENTER, KEY_INSERT },
{ KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
- { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
- { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
+ { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
{ KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
{ KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
{ KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
- { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
+ { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
goto err_bus;
#ifdef CONFIG_HID_COMPAT
- hid_compat_wq = create_workqueue("hid_compat");
+ hid_compat_wq = create_singlethread_workqueue("hid_compat");
if (!hid_compat_wq) {
hidraw_exit();
goto err;
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
static struct cdev hidraw_cdev;
static struct class *hidraw_class;
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
-static DEFINE_SPINLOCK(minors_lock);
+static DEFINE_MUTEX(minors_lock);
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct hidraw_list *list;
int err = 0;
- lock_kernel();
if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
err = -ENOMEM;
goto out;
}
- spin_lock(&minors_lock);
+ lock_kernel();
+ mutex_lock(&minors_lock);
if (!hidraw_table[minor]) {
printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
minor);
file->private_data = list;
dev = hidraw_table[minor];
- if (!dev->open++)
- dev->hid->ll_driver->open(dev->hid);
+ if (!dev->open++) {
+ err = dev->hid->ll_driver->open(dev->hid);
+ if (err < 0)
+ dev->open--;
+ }
out_unlock:
- spin_unlock(&minors_lock);
-out:
+ mutex_unlock(&minors_lock);
unlock_kernel();
+out:
return err;
}
result = -EINVAL;
- spin_lock(&minors_lock);
+ mutex_lock(&minors_lock);
for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
if (hidraw_table[minor])
break;
}
- spin_unlock(&minors_lock);
-
if (result) {
+ mutex_unlock(&minors_lock);
kfree(dev);
goto out;
}
NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
- spin_lock(&minors_lock);
hidraw_table[minor] = NULL;
- spin_unlock(&minors_lock);
+ mutex_unlock(&minors_lock);
result = PTR_ERR(dev->dev);
kfree(dev);
goto out;
}
+ mutex_unlock(&minors_lock);
init_waitqueue_head(&dev->wait);
INIT_LIST_HEAD(&dev->list);
hidraw->exist = 0;
- spin_lock(&minors_lock);
+ mutex_lock(&minors_lock);
hidraw_table[hidraw->minor] = NULL;
- spin_unlock(&minors_lock);
+ mutex_unlock(&minors_lock);
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
unsigned int n, insize = 0;
int ret;
+ clear_bit(HID_DISCONNECTED, &usbhid->iofl);
+
usbhid->bufsize = HID_MIN_BUFFER_SIZE;
hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
}
}
- if (!usbhid->urbin) {
- err_hid("couldn't find an input interrupt endpoint");
- ret = -ENODEV;
- goto fail;
- }
-
init_waitqueue_head(&usbhid->wait);
INIT_WORK(&usbhid->reset_work, hid_reset);
setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
usb_free_urb(usbhid->urbin);
usb_free_urb(usbhid->urbout);
usb_free_urb(usbhid->urbctrl);
+ usbhid->urbin = NULL;
+ usbhid->urbout = NULL;
+ usbhid->urbctrl = NULL;
hid_free_buffers(dev, hid);
mutex_unlock(&usbhid->setup);
return ret;
usb_free_urb(usbhid->urbin);
usb_free_urb(usbhid->urbctrl);
usb_free_urb(usbhid->urbout);
+ usbhid->urbin = NULL; /* don't mess up next start */
+ usbhid->urbctrl = NULL;
+ usbhid->urbout = NULL;
hid_free_buffers(hid_to_usb_dev(hid), hid);
mutex_unlock(&usbhid->setup);
static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
+ struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_device *dev = interface_to_usbdev(intf);
struct usbhid_device *usbhid;
struct hid_device *hid;
+ unsigned int n, has_in = 0;
size_t len;
int ret;
dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
+ for (n = 0; n < interface->desc.bNumEndpoints; n++)
+ if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
+ has_in++;
+ if (!has_in) {
+ dev_err(&intf->dev, "couldn't find an input interrupt "
+ "endpoint\n");
+ return -ENODEV;
+ }
+
hid = hid_allocate_device();
if (IS_ERR(hid))
return PTR_ERR(hid);
/* Set 13: iMac 8,1 */
{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
"TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
+/* Set 14: iMac 6,1 */
+ { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
+ "TO0P", "Tp0P", NULL },
};
/* List of keys used to read/write fan speeds */
{ .accelerometer = 1, .light = 1, .temperature_set = 12 },
/* iMac 8: light sensor only, temperature set 13 */
{ .accelerometer = 0, .light = 0, .temperature_set = 13 },
+/* iMac 6: light sensor only, temperature set 14 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 14 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
&applesmc_dmi_data[4]},
+ { applesmc_dmi_match, "Apple MacPro", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
+ &applesmc_dmi_data[4]},
{ applesmc_dmi_match, "Apple iMac 8", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
&applesmc_dmi_data[13]},
+ { applesmc_dmi_match, "Apple iMac 6", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") },
+ &applesmc_dmi_data[14]},
{ applesmc_dmi_match, "Apple iMac 5", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/freezer.h>
-#include <linux/version.h>
#include <linux/uaccess.h>
#include <acpi/acpi_drivers.h>
#include <asm/atomic.h>
} else
data = i2c_op(pd, OP_RX, 0);
- pd->msg->buf[real_pos] = data;
+ if (real_pos >= 0)
+ pd->msg->buf[real_pos] = data;
} while (0);
pd->pos++;
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
+ PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, ide_ids);
/* slarp reply, send own ip/netmask; if values are nonsense remote
* should think we are unable to provide it with an address via SLARP */
p += put_u32(p, CISCO_SLARP_REPLY);
- p += put_u32(p, addr); // address
- p += put_u32(p, mask); // netmask
+ *(__be32 *)p = addr; // address
+ p += 4;
+ *(__be32 *)p = mask; // netmask
+ p += 4;
p += put_u16(p, 0); // unused
isdn_net_write_super(lp, skb);
__choose_pgpath(m);
pgpath = m->current_pgpath;
- m->pgpath_to_activate = m->current_pgpath;
if ((pgpath && !m->queue_io) ||
(!pgpath && !m->queue_if_no_path))
must_queue = 0;
- if (m->pg_init_required && !m->pg_init_in_progress) {
+ if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
+ m->pgpath_to_activate = pgpath;
m->pg_init_count++;
m->pg_init_required = 0;
m->pg_init_in_progress = 1;
m->hw_handler_name = NULL;
return -EINVAL;
}
+
+ if (hw_argc > 1)
+ DMWARN("Ignoring user-specified arguments for "
+ "hardware handler \"%s\"", m->hw_handler_name);
consume(as, hw_argc - 1);
return 0;
del_timer_sync(&ms->timer);
flush_workqueue(ms->kmirrord_wq);
+ flush_scheduled_work();
dm_kcopyd_client_destroy(ms->kcopyd_client);
destroy_workqueue(ms->kmirrord_wq);
free_context(ms, ti, ms->nr_mirrors);
int r;
r = dm_register_target(&stripe_target);
- if (r < 0)
+ if (r < 0) {
DMWARN("target registration failed");
+ return r;
+ }
kstriped = create_singlethread_workqueue("kstriped");
if (!kstriped) {
dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending);
}
-static int end_io_acct(struct dm_io *io)
+static void end_io_acct(struct dm_io *io)
{
struct mapped_device *md = io->md;
struct bio *bio = io->bio;
dm_disk(md)->part0.in_flight = pending =
atomic_dec_return(&md->pending);
- return !pending;
+ /* nudge anyone waiting on suspend queue */
+ if (!pending)
+ wake_up(&md->wait);
}
/*
spin_unlock_irqrestore(&io->md->pushback_lock, flags);
}
- if (end_io_acct(io))
- /* nudge anyone waiting on suspend queue */
- wake_up(&io->md->wait);
+ end_io_acct(io);
if (io->error != DM_ENDIO_REQUEUE) {
blk_add_trace_bio(io->md->queue, io->bio,
static int dm_any_congested(void *congested_data, int bdi_bits)
{
- int r;
- struct mapped_device *md = (struct mapped_device *) congested_data;
- struct dm_table *map = dm_get_table(md);
+ int r = bdi_bits;
+ struct mapped_device *md = congested_data;
+ struct dm_table *map;
- if (!map || test_bit(DMF_BLOCK_IO, &md->flags))
- r = bdi_bits;
- else
- r = dm_table_any_congested(map, bdi_bits);
+ atomic_inc(&md->pending);
+
+ if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
+ map = dm_get_table(md);
+ if (map) {
+ r = dm_table_any_congested(map, bdi_bits);
+ dm_table_put(map);
+ }
+ }
+
+ if (!atomic_dec_return(&md->pending))
+ /* nudge anyone waiting on suspend queue */
+ wake_up(&md->wait);
- dm_table_put(map);
return r;
}
/*
- * experimental driver for simple i2c audio chips.
+ * Driver for simple i2c audio chips.
*
* Copyright (c) 2000 Gerd Knorr
* based on code by:
* Steve VanDeBogart (vandebo@uclink.berkeley.edu)
* Greg Alexander (galexand@acm.org)
*
+ * Copyright(c) 2005-2008 Mauro Carvalho Chehab
+ * - Some cleanups, code fixes, etc
+ * - Convert it to V4L2 API
+ *
* This code is placed under the terms of the GNU General Public License
*
* OPTIONS:
#include <media/tvaudio.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv-legacy.h>
typedef int (*initialize)(struct CHIPSTATE*);
typedef int (*getmode)(struct CHIPSTATE*);
typedef void (*setmode)(struct CHIPSTATE*, int mode);
-typedef void (*checkmode)(struct CHIPSTATE*);
/* i2c command */
typedef struct AUDIOCMD {
#define CHIP_HAS_VOLUME 1
#define CHIP_HAS_BASSTREBLE 2
#define CHIP_HAS_INPUTSEL 4
+#define CHIP_NEED_CHECKMODE 8
/* various i2c command sequences */
audiocmd init;
getmode getmode;
setmode setmode;
- /* check / autoswitch audio after channel switches */
- checkmode checkmode;
-
/* input switch register + values for v4l inputs */
int inputreg;
int inputmap[4];
int inputmute;
int inputmask;
};
-static struct CHIPDESC chiplist[];
/* current state of the chip */
struct CHIPSTATE {
struct i2c_client *c;
- /* index into CHIPDESC array */
- int type;
+ /* chip-specific description - should point to
+ an entry at CHIPDESC table */
+ struct CHIPDESC *desc;
/* shadow register set */
audiocmd shadow;
{
unsigned char buffer[2];
- if (-1 == subaddr) {
+ if (subaddr < 0) {
v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n",
chip->c->name, val);
chip->shadow.bytes[1] = val;
return -1;
}
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n",
chip->c->name, subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
return 0;
}
-static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask)
+static int chip_write_masked(struct CHIPSTATE *chip,
+ int subaddr, int val, int mask)
{
if (mask != 0) {
- if (-1 == subaddr) {
+ if (subaddr < 0) {
val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
}
}
if (0 == cmd->count)
return 0;
+ if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register range: %d to %d\n",
+ cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
+ return -EINVAL;
+ }
+
+ /* FIXME: it seems that the shadow bytes are wrong bellow !*/
+
/* update our shadow register set; print bytes if (debug > 0) */
v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:",
chip->c->name, name,cmd->bytes[0]);
static int chip_thread(void *data)
{
struct CHIPSTATE *chip = data;
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
+ int mode;
v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name);
set_freezable();
continue;
/* have a look what's going on */
- desc->checkmode(chip);
+ mode = desc->getmode(chip);
+ if (mode == chip->prevmode)
+ continue;
+
+ /* chip detected a new audio mode - set it */
+ v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n",
+ chip->c->name);
+
+ chip->prevmode = mode;
+
+ if (mode & V4L2_TUNER_MODE_STEREO)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ else if (mode & V4L2_TUNER_MODE_LANG1)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG1);
+ else if (mode & V4L2_TUNER_MODE_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG2);
+ else
+ desc->setmode(chip, V4L2_TUNER_MODE_MONO);
/* schedule next check */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
return 0;
}
-static void generic_checkmode(struct CHIPSTATE *chip)
-{
- struct CHIPDESC *desc = chiplist + chip->type;
- int mode = desc->getmode(chip);
-
- if (mode == chip->prevmode)
- return;
-
- v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name);
- chip->prevmode = mode;
-
- if (mode & V4L2_TUNER_MODE_STEREO)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- else if (mode & V4L2_TUNER_MODE_LANG1)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG1);
- else if (mode & V4L2_TUNER_MODE_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG2);
- else
- desc->setmode(chip,V4L2_TUNER_MODE_MONO);
-}
-
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda9840 */
char *name;
audiocmd cmd;
} tda9874a_modelist[9] = {
- { "A2, B/G",
+ { "A2, B/G", /* default */
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} },
{ "A2, M (Korea)",
{ 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} },
{ 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} },
{ "NICAM, B/G",
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} },
- { "NICAM, D/K", /* default */
+ { "NICAM, D/K",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} },
{ "NICAM, L",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }
{
if (tda9874a_SIF > 2)
tda9874a_SIF = 1;
- if (tda9874a_STD > 8)
+ if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist))
tda9874a_STD = 0;
if(tda9874a_AMSEL > 1)
tda9874a_AMSEL = 0;
static int tda8425_initialize(struct CHIPSTATE *chip)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF};
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 5,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.checkit = tda9840_checkit,
.getmode = tda9840_getmode,
.setmode = tda9840_setmode,
- .checkmode = generic_checkmode,
.init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN
/* ,TDA9840_SW, TDA9840_MONO */} }
},
{
.name = "tda9873h",
- .checkit = tda9873_checkit,
.insmodopt = &tda9873,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
.addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 3,
- .flags = CHIP_HAS_INPUTSEL,
+ .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .checkit = tda9873_checkit,
.getmode = tda9873_getmode,
.setmode = tda9873_setmode,
- .checkmode = generic_checkmode,
.init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
.inputreg = TDA9873_SW,
},
{
.name = "tda9874h/a",
- .checkit = tda9874a_checkit,
- .initialize = tda9874a_initialize,
.insmodopt = &tda9874a,
.addr_lo = I2C_ADDR_TDA9874 >> 1,
.addr_hi = I2C_ADDR_TDA9874 >> 1,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .initialize = tda9874a_initialize,
+ .checkit = tda9874a_checkit,
.getmode = tda9874a_getmode,
.setmode = tda9874a_setmode,
- .checkmode = generic_checkmode,
},
{
.name = "tda9850",
.rightreg = TDA9855_VR,
.bassreg = TDA9855_BA,
.treblereg = TDA9855_TR,
+
+ /* callbacks */
.volfunc = tda9855_volume,
.bassfunc = tda9855_bass,
.treblefunc = tda9855_treble,
-
.getmode = tda985x_getmode,
.setmode = tda985x_setmode,
.rightreg = TEA6300_VL,
.bassreg = TEA6300_BA,
.treblereg = TEA6300_TR,
+
+ /* callbacks */
.volfunc = tea6300_shift10,
.bassfunc = tea6300_shift12,
.treblefunc = tea6300_shift12,
},
{
.name = "tea6320",
- .initialize = tea6320_initialize,
.insmodopt = &tea6320,
.addr_lo = I2C_ADDR_TEA6300 >> 1,
.addr_hi = I2C_ADDR_TEA6300 >> 1,
.rightreg = TEA6320_V,
.bassreg = TEA6320_BA,
.treblereg = TEA6320_TR,
+
+ /* callbacks */
+ .initialize = tea6320_initialize,
.volfunc = tea6320_volume,
.bassfunc = tea6320_shift11,
.treblefunc = tea6320_shift11,
.rightreg = TDA8425_VR,
.bassreg = TDA8425_BA,
.treblereg = TDA8425_TR,
+
+ /* callbacks */
+ .initialize = tda8425_initialize,
.volfunc = tda8425_shift10,
.bassfunc = tda8425_shift12,
.treblefunc = tda8425_shift12,
+ .setmode = tda8425_setmode,
.inputreg = TDA8425_S1,
.inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },
.inputmute = TDA8425_S1_OFF,
- .setmode = tda8425_setmode,
- .initialize = tda8425_initialize,
},
{
.name = "pic16c54 (PV951)",
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 2,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.getmode = ta8874z_getmode,
.setmode = ta8874z_setmode,
- .checkmode = generic_checkmode,
.init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
},
}
if (desc->name == NULL) {
v4l_dbg(1, debug, client, "no matching chip description found\n");
+ kfree(chip);
return -EIO;
}
v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name);
/* fill required data structures */
if (!id)
strlcpy(client->name, desc->name, I2C_NAME_SIZE);
- chip->type = desc-chiplist;
+ chip->desc = desc;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
chip->audmode = V4L2_TUNER_MODE_LANG1;
chip_cmd(chip,"init",&desc->init);
if (desc->flags & CHIP_HAS_VOLUME) {
- chip->left = desc->leftinit ? desc->leftinit : 65535;
- chip->right = desc->rightinit ? desc->rightinit : 65535;
- chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
- chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+ if (!desc->volfunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without volume controls
+ */
+ v4l_info(chip->c, "volume callback undefined!\n");
+ desc->flags &= ~CHIP_HAS_VOLUME;
+ } else {
+ chip->left = desc->leftinit ? desc->leftinit : 65535;
+ chip->right = desc->rightinit ? desc->rightinit : 65535;
+ chip_write(chip, desc->leftreg,
+ desc->volfunc(chip->left));
+ chip_write(chip, desc->rightreg,
+ desc->volfunc(chip->right));
+ }
}
if (desc->flags & CHIP_HAS_BASSTREBLE) {
- chip->treble = desc->trebleinit ? desc->trebleinit : 32768;
- chip->bass = desc->bassinit ? desc->bassinit : 32768;
- chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
- chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
+ if (!desc->bassfunc || !desc->treblefunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without bass/treble controls
+ */
+ v4l_info(chip->c, "bass/treble callbacks undefined!\n");
+ desc->flags &= ~CHIP_HAS_BASSTREBLE;
+ } else {
+ chip->treble = desc->trebleinit ?
+ desc->trebleinit : 32768;
+ chip->bass = desc->bassinit ?
+ desc->bassinit : 32768;
+ chip_write(chip, desc->bassreg,
+ desc->bassfunc(chip->bass));
+ chip_write(chip, desc->treblereg,
+ desc->treblefunc(chip->treble));
+ }
}
chip->thread = NULL;
- if (desc->checkmode) {
+ if (desc->flags & CHIP_NEED_CHECKMODE) {
+ if (!desc->getmode || !desc->setmode) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without kthread
+ */
+ v4l_info(chip->c, "set/get mode callbacks undefined!\n");
+ return 0;
+ }
/* start async thread */
init_timer(&chip->wt);
chip->wt.function = chip_thread_wake;
static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
ctrl->value = chip->bass;
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
ctrl->value = chip->treble;
return 0;
}
static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
chip->bass = ctrl->value;
chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
-
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
chip->treble = ctrl->value;
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
unsigned int cmd, void *arg)
{
struct CHIPSTATE *chip = i2c_get_clientdata(client);
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
- v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd);
+ if (debug > 0) {
+ v4l_i2c_print_ioctl(chip->c, cmd);
+ printk("\n");
+ }
switch (cmd) {
case AUDC_SET_RADIO:
break;
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
return -EINVAL;
break;
default:
break;
case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
- if (desc->checkmode && desc->setmode) {
+
+ /* For chips that provide getmode and setmode, and doesn't
+ automatically follows the stereo carrier, a kthread is
+ created to set the audio standard. In this case, when then
+ the video channel is changed, tvaudio starts on MONO mode.
+ After waiting for 2 seconds, the kernel thread is called,
+ to follow whatever audio standard is pointed by the
+ audio carrier.
+ */
+ if (chip->thread) {
desc->setmode(chip,V4L2_TUNER_MODE_MONO);
if (chip->prevmode != V4L2_TUNER_MODE_MONO)
chip->prevmode = -1; /* reset previous mode */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
- /* the thread will call checkmode() later */
}
break;
.legacy_probe = chip_legacy_probe,
.id_table = chip_id,
};
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
{
uint8_t v[3];
- chip->events_mask &= ~events;
+ chip->events_mask |= events;
v[0] = (chip->events_mask & 0xff);
v[1] = (chip->events_mask >> 8) & 0xff;
ret = i2c_master_send(wm8350->i2c_client, ®, 1);
if (ret < 0)
return ret;
- return i2c_master_recv(wm8350->i2c_client, dest, bytes);
+ ret = i2c_master_recv(wm8350->i2c_client, dest, bytes);
+ if (ret < 0)
+ return ret;
+ if (ret != bytes)
+ return -EIO;
+ return 0;
}
static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
{
/* we add 1 byte for device register */
u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+ int ret;
if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
return -EINVAL;
msg[0] = reg;
memcpy(&msg[1], src, bytes);
- return i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+ ret = i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+ if (ret < 0)
+ return ret;
+ if (ret != bytes + 1)
+ return -EIO;
+ return 0;
}
static int wm8350_i2c_probe(struct i2c_client *i2c,
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/idr.h>
+#include <linux/sched.h>
#include <linux/c2port.h>
+ifdef CONFIG_SGI_GRU_DEBUG
+ EXTRA_CFLAGS += -DDEBUG
+endif
+
obj-$(CONFIG_SGI_GRU) := gru.o
gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
-
+/* dynamic ioremap() areas */
+#define FLASH_START 0x00000000
+#define FLASH_SIZE 0x800000
+#define FLASH_WIDTH 4
+
+#define SRAM_START 0x60000000
+#define SRAM_SIZE 0xc000
+#define SRAM_WIDTH 4
+
+#define BOOTROM_START 0x70000000
+#define BOOTROM_SIZE 0x80
+#define BOOTROM_WIDTH 4
static struct mtd_info *flash_mtd;
static struct map_info h720x_map = {
.name = "H720X",
.bankwidth = 4,
- .size = FLASH_SIZE,
- .phys = FLASH_PHYS,
+ .size = H720X_FLASH_SIZE,
+ .phys = H720X_FLASH_PHYS,
};
static struct mtd_partition h720x_partitions[] = {
char *part_type = NULL;
- h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE);
+ h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
if (!h720x_map.virt) {
printk(KERN_ERR "H720x-MTD: ioremap failed\n");
* atl1e_hash_mc_addr
* purpose
* set hash value for a multicast address
- * hash calcu processing :
- * 1. calcu 32bit CRC for multicast address
- * 2. reverse crc with MSB to LSB
*/
u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
{
int i;
crc32 = ether_crc_le(6, mc_addr);
- crc32 = ~crc32;
for (i = 0; i < 32; i++)
value |= (((crc32 >> i) & 1) << (31 - i));
{
struct atl1_adapter *adapter = netdev_priv(netdev);
- wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+ wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
- if (adapter->wol & ATLX_WUFC_EX)
- wol->wolopts |= WAKE_UCAST;
- if (adapter->wol & ATLX_WUFC_MC)
- wol->wolopts |= WAKE_MCAST;
- if (adapter->wol & ATLX_WUFC_BC)
- wol->wolopts |= WAKE_BCAST;
if (adapter->wol & ATLX_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
{
struct atl1_adapter *adapter = netdev_priv(netdev);
- if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
+ WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
- if (wol->wolopts & WAKE_UCAST)
- adapter->wol |= ATLX_WUFC_EX;
- if (wol->wolopts & WAKE_MCAST)
- adapter->wol |= ATLX_WUFC_MC;
- if (wol->wolopts & WAKE_BCAST)
- adapter->wol |= ATLX_WUFC_BC;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= ATLX_WUFC_MAG;
return 0;
ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
- err = atl2_request_irq(adapter);
- if (netif_running(netdev) && err)
- return err;
+ if (netif_running(netdev)) {
+ err = atl2_request_irq(adapter);
+ if (err)
+ return err;
+ }
atl2_reset_hw(&adapter->hw);
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.5.23-k4"DRV_EXT
+#define DRV_VERSION "3.5.23-k6"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
#define PFX DRV_NAME ": "
struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
- sizeof(struct rfd), PCI_DMA_TODEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
}
return 0;
/* Need to sync before taking a peek at cb_complete bit */
pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,
- sizeof(struct rfd), PCI_DMA_FROMDEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
rfd_status = le16_to_cpu(rfd->status);
DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status);
/* Get data */
pci_unmap_single(nic->pdev, rx->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
/* If this buffer has the el bit, but we think the receiver
* is still running, check to see if it really stopped while
new_before_last_rfd->command |= cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev,
new_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
/* Now that we have a new stopping point, we can clear the old
* stopping point. We must sync twice to get the proper
old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
pci_dma_sync_single_for_device(nic->pdev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
- PCI_DMA_TODEVICE);
+ PCI_DMA_BIDIRECTIONAL);
}
if(restart_required) {
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) {
pci_unmap_single(nic->pdev, rx->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
dev_kfree_skb(rx->skb);
}
}
before_last->command |= cpu_to_le16(cb_el);
before_last->size = 0;
pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
- sizeof(struct rfd), PCI_DMA_TODEVICE);
+ sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
nic->ru_running = RU_SUSPENDED;
msleep(10);
pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
- RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
skb->data, ETH_DATA_LEN))
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
- if (e1000_wol_exclusion(adapter, wol))
+ if (e1000_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
/* apply any specific unsupported masks here */
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
- if (e1000_wol_exclusion(adapter, wol))
+ if (e1000_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
switch (hw->device_id) {
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* print bus type/speed/width info */
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
unsigned long led_status;
unsigned int flags;
+ unsigned int flags2;
struct work_struct downshift_task;
struct work_struct update_phy_task;
};
struct e1000_info {
enum e1000_mac_type mac;
unsigned int flags;
+ unsigned int flags2;
u32 pba;
s32 (*get_variants)(struct e1000_adapter *);
struct e1000_mac_operations *mac_ops;
#define FLAG_RX_RESTART_NOW (1 << 30)
#define FLAG_MSI_TEST_FAILED (1 << 31)
+/* CRC Stripping defines */
+#define FLAG2_CRC_STRIPPING (1 << 0)
+
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
wol->supported = 0;
wol->wolopts = 0;
- if (!(adapter->flags & FLAG_HAS_WOL))
+ if (!(adapter->flags & FLAG_HAS_WOL) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
wol->supported = WAKE_UCAST | WAKE_MCAST |
if (wol->wolopts & WAKE_MAGICSECURE)
return -EOPNOTSUPP;
- if (!(adapter->flags & FLAG_HAS_WOL))
+ if (!(adapter->flags & FLAG_HAS_WOL) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
/* these settings will always override what we currently have */
if (wol->wolopts & WAKE_ARP)
adapter->wol |= E1000_WUFC_ARP;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
goto next_desc;
}
+ /* adjust length to remove Ethernet CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ length -= 4;
+
total_rx_bytes += length;
total_rx_packets++;
pci_dma_sync_single_for_device(pdev, ps_page->dma,
PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ /* remove the CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ l1 -= 4;
+
skb_put(skb, l1);
goto copydone;
} /* if */
skb->truesize += length;
}
+ /* strip the ethernet crc, problem is we're using pages now so
+ * this whole operation can get a little cpu intensive
+ */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ pskb_trim(skb, skb->len - 4);
+
copydone:
total_rx_bytes += skb->len;
total_rx_packets++;
else
rctl |= E1000_RCTL_LPE;
- /* Enable hardware CRC frame stripping */
- rctl |= E1000_RCTL_SECRC;
+ /* Some systems expect that the CRC is included in SMBUS traffic. The
+ * hardware strips the CRC before sending to both SMBUS (BMC) and to
+ * host memory when this is enabled
+ */
+ if (adapter->flags2 & FLAG2_CRC_STRIPPING)
+ rctl |= E1000_RCTL_SECRC;
/* Setup buffer sizes */
rctl &= ~E1000_RCTL_SZ_4096;
adapter->ei = ei;
adapter->pba = ei->pba;
adapter->flags = ei->flags;
+ adapter->flags2 = ei->flags2;
adapter->hw.adapter = adapter;
adapter->hw.mac.type = ei->mac;
adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* reset the hardware with the new settings */
e1000e_reset(adapter);
err_sw_init:
if (adapter->hw.flash_address)
iounmap(adapter->hw.flash_address);
+ e1000e_reset_interrupt_capability(adapter);
err_flashmap:
iounmap(adapter->hw.hw_addr);
err_ioremap:
*/
E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+/*
+ * Enable CRC Stripping
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \
+ "the CRC");
+
struct e1000_option {
enum { enable_option, range_option, list_option } type;
const char *name;
adapter->flags |= FLAG_SMART_POWER_DOWN;
}
}
+ { /* CRC Stripping */
+ const struct e1000_option opt = {
+ .type = enable_option,
+ .name = "CRC Stripping",
+ .err = "defaulting to enabled",
+ .def = OPTION_ENABLED
+ };
+
+ if (num_CrcStripping > bd) {
+ unsigned int crc_stripping = CrcStripping[bd];
+ e1000_validate_option(&crc_stripping, &opt, adapter);
+ if (crc_stripping == OPTION_ENABLED)
+ adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ }
+ }
{ /* Kumeran Lock Loss Workaround */
const struct e1000_option opt = {
.type = enable_option,
if (bdp->status & TXBD_DEF)
dev->stats.collisions++;
+ /* Unmap the DMA memory */
+ dma_unmap_single(&priv->dev->dev, bdp->bufPtr,
+ bdp->length, DMA_TO_DEVICE);
+
/* Free the sk buffer associated with this TxBD */
dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
skb = priv->rx_skbuff[priv->skb_currx];
+ dma_unmap_single(&priv->dev->dev, bdp->bufPtr,
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
+
/* We drop the frame if we failed to allocate a new buffer */
if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
bdp->status & RXBD_ERR)) {
if (unlikely(!newskb))
newskb = skb;
- if (skb) {
- dma_unmap_single(&priv->dev->dev,
- bdp->bufPtr,
- priv->rx_buffer_size,
- DMA_FROM_DEVICE);
-
+ if (skb)
dev_kfree_skb_any(skb);
- }
} else {
/* Increment the number of packets */
dev->stats.rx_packets++;
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
- if (igb_wol_exclusion(adapter, wol))
+ if (igb_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return;
/* apply any specific unsupported masks here */
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
- if (igb_wol_exclusion(adapter, wol))
+ if (igb_wol_exclusion(adapter, wol) ||
+ !device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
switch (hw->device_id) {
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
return 0;
}
state &= ~PCIE_LINK_STATE_L0S;
pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL,
state);
- printk(KERN_INFO "Disabling ASPM L0s upstream switch "
- "port %x:%x.%x\n", us_dev->bus->number,
- PCI_SLOT(us_dev->devfn),
- PCI_FUNC(us_dev->devfn));
+ dev_info(&pdev->dev,
+ "Disabling ASPM L0s upstream switch port %s\n",
+ pci_name(us_dev));
}
default:
break;
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
+ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* reset the hardware with the new settings */
igb_reset(adapter);
struct ipg_rx *rxfd = sp->rxd + entry;
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
sp->rx_buff[entry] = NULL;
*/
if (sp->rx_buff[entry]) {
pci_unmap_single(sp->pdev,
- le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(sp->rx_buff[entry]);
if (jumbo->found_start)
dev_kfree_skb_irq(jumbo->skb);
- pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN),
+ pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb_put(skb, sp->rxfrag_size);
unsigned int entry = curr % IPG_RFDLIST_LENGTH;
struct ipg_rx *rxfd = sp->rxd + entry;
- if (!(rxfd->rfs & le64_to_cpu(IPG_RFS_RFDDONE)))
+ if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE)))
break;
switch (ipg_nic_rx_check_frame_type(dev)) {
return;
}
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
+/**
+ * ixgbe_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+{
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ int i;
+ for (i = 0; i < adapter->num_msix_vectors; i++)
+ synchronize_irq(adapter->msix_entries[i].vector);
+ } else {
+ synchronize_irq(adapter->pdev->irq);
+ }
+}
+
+/**
+ * ixgbe_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+{
+ u32 mask;
+ mask = IXGBE_EIMS_ENABLE_MASK;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+}
/**
* ixgbe_intr - legacy mode Interrupt Handler
}
}
-/**
- * ixgbe_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
-{
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
- IXGBE_WRITE_FLUSH(&adapter->hw);
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- int i;
- for (i = 0; i < adapter->num_msix_vectors; i++)
- synchronize_irq(adapter->msix_entries[i].vector);
- } else {
- synchronize_irq(adapter->pdev->irq);
- }
-}
-
-/**
- * ixgbe_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
-{
- u32 mask;
- mask = IXGBE_EIMS_ENABLE_MASK;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
- IXGBE_WRITE_FLUSH(&adapter->hw);
-}
-
/**
* ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts
*
skb_put(skb, framesize);
skb->protocol = eth_type_trans(skb, jme->dev);
- if (jme_rxsum_ok(jme, rxdesc->descwb.flags))
+ if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
- if (rxdesc->descwb.flags & RXWBFLAG_TAGON) {
+ if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
if (jme->vlgrp) {
jme->jme_vlan_rx(skb, jme->vlgrp,
- le32_to_cpu(rxdesc->descwb.vlan));
+ le16_to_cpu(rxdesc->descwb.vlan));
NET_STAT(jme).rx_bytes += 4;
}
} else {
jme->jme_rx(skb);
}
- if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) ==
- RXWBFLAG_DEST_MUL)
+ if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) ==
+ cpu_to_le16(RXWBFLAG_DEST_MUL))
++(NET_STAT(jme).multicast);
jme->dev->last_rx = jiffies;
rxdesc = rxring->desc;
rxdesc += i;
- if ((rxdesc->descwb.flags & RXWBFLAG_OWN) ||
+ if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) ||
!(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL))
goto out;
}
static int
-jme_tx_tso(struct sk_buff *skb,
- u16 *mss, u8 *flags)
+jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags)
{
- *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT;
+ *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT);
if (*mss) {
*flags |= TXFLAG_LSEN;
}
static inline void
-jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags)
+jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags)
{
if (vlan_tx_tag_present(skb)) {
*flags |= TXFLAG_TAGON;
- *vlan = vlan_tx_tag_get(skb);
+ *vlan = cpu_to_le16(vlan_tx_tag_get(skb));
}
}
/* Configure port */
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
priv->rx_skb_size + ETH_FCS_LEN,
- mdev->profile.tx_pause,
- mdev->profile.tx_ppp,
- mdev->profile.rx_pause,
- mdev->profile.rx_ppp);
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
if (err) {
mlx4_err(mdev, "Failed setting port general configurations"
" for port %d, with error %d\n", priv->port, err);
int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
{
struct mlx4_en_profile *params = &mdev->profile;
+ int i;
params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF);
params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF);
params->rss_xor = (rss_xor != 0);
params->rss_mask = rss_mask & 0x1f;
params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
- params->rx_pause = pprx;
- params->rx_ppp = pfcrx;
- params->tx_pause = pptx;
- params->tx_ppp = pfctx;
- if (params->rx_ppp || params->tx_ppp) {
+ for (i = 1; i <= MLX4_MAX_PORTS; i++) {
+ params->prof[i].rx_pause = pprx;
+ params->prof[i].rx_ppp = pfcrx;
+ params->prof[i].tx_pause = pptx;
+ params->prof[i].tx_ppp = pfctx;
+ }
+ if (pfcrx || pfctx) {
params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM;
params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM;
} else {
struct mlx4_en_dev *mdev = priv->mdev;
int err;
- mdev->profile.tx_pause = pause->tx_pause != 0;
- mdev->profile.rx_pause = pause->rx_pause != 0;
+ priv->prof->tx_pause = pause->tx_pause != 0;
+ priv->prof->rx_pause = pause->rx_pause != 0;
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
priv->rx_skb_size + ETH_FCS_LEN,
- mdev->profile.tx_pause,
- mdev->profile.tx_ppp,
- mdev->profile.rx_pause,
- mdev->profile.rx_ppp);
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
if (err)
mlx4_err(mdev, "Failed setting pause params to\n");
struct ethtool_pauseparam *pause)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- pause->tx_pause = mdev->profile.tx_pause;
- pause->rx_pause = mdev->profile.rx_pause;
+ pause->tx_pause = priv->prof->tx_pause;
+ pause->rx_pause = priv->prof->rx_pause;
}
static void mlx4_en_get_ringparam(struct net_device *dev,
u32 rx_ring_num;
u32 tx_ring_size;
u32 rx_ring_size;
+ u8 rx_pause;
+ u8 rx_ppp;
+ u8 tx_pause;
+ u8 tx_ppp;
};
struct mlx4_en_profile {
int rx_moder_cnt;
int rx_moder_time;
int auto_moder;
- u8 rx_pause;
- u8 rx_ppp;
- u8 tx_pause;
- u8 tx_ppp;
u8 no_reset;
struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
};
if (skb != NULL) {
if (skb_queue_len(&mp->rx_recycle) <
mp->default_rx_ring_size &&
- skb_recycle_check(skb, mp->skb_size))
+ skb_recycle_check(skb, mp->skb_size +
+ dma_get_cache_alignment() - 1))
__skb_queue_head(&mp->rx_recycle, skb);
else
dev_kfree_skb(skb);
struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
if (pd == NULL || pd->shared_smi == NULL) {
- mdiobus_free(msp->smi_bus);
mdiobus_unregister(msp->smi_bus);
+ mdiobus_free(msp->smi_bus);
}
if (msp->err_interrupt != NO_IRQ)
free_irq(msp->err_interrupt, msp);
#define DRV_MODULE_NAME "niu"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.9"
-#define DRV_MODULE_RELDATE "May 4, 2008"
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "Nov 14, 2008"
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
}
/* Mode is always 10G fiber. */
-static int serdes_init_niu(struct niu *np)
+static int serdes_init_niu_10g_fiber(struct niu *np)
{
struct niu_link_config *lp = &np->link_config;
u32 tx_cfg, rx_cfg;
return 0;
}
+static int serdes_init_niu_1g_serdes(struct niu *np)
+{
+ struct niu_link_config *lp = &np->link_config;
+ u16 pll_cfg, pll_sts;
+ int max_retry = 100;
+ u64 sig, mask, val;
+ u32 tx_cfg, rx_cfg;
+ unsigned long i;
+ int err;
+
+ tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV |
+ PLL_TX_CFG_RATE_HALF);
+ rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
+ PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
+ PLL_RX_CFG_RATE_HALF);
+
+ if (np->port == 0)
+ rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE;
+
+ if (lp->loopback_mode == LOOPBACK_PHY) {
+ u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
+
+ mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_TEST_CFG_L, test_cfg);
+
+ tx_cfg |= PLL_TX_CFG_ENTEST;
+ rx_cfg |= PLL_RX_CFG_ENTEST;
+ }
+
+ /* Initialize PLL for 1G */
+ pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X);
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_CFG_L, pll_cfg);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_1g_serdes: "
+ "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ return err;
+ }
+
+ pll_sts = PLL_CFG_ENPLL;
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_STS_L, pll_sts);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_1g_serdes: "
+ "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ return err;
+ }
+
+ udelay(200);
+
+ /* Initialize all 4 lanes of the SERDES. */
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_tx_cfg(np, i, tx_cfg);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_rx_cfg(np, i, rx_cfg);
+ if (err)
+ return err;
+ }
+
+ switch (np->port) {
+ case 0:
+ val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
+ mask = val;
+ break;
+
+ case 1:
+ val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
+ mask = val;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ while (max_retry--) {
+ sig = nr64(ESR_INT_SIGNALS);
+ if ((sig & mask) == val)
+ break;
+
+ mdelay(500);
+ }
+
+ if ((sig & mask) != val) {
+ dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
+ "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int serdes_init_niu_10g_serdes(struct niu *np)
+{
+ struct niu_link_config *lp = &np->link_config;
+ u32 tx_cfg, rx_cfg, pll_cfg, pll_sts;
+ int max_retry = 100;
+ u64 sig, mask, val;
+ unsigned long i;
+ int err;
+
+ tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV);
+ rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
+ PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
+ PLL_RX_CFG_EQ_LP_ADAPTIVE);
+
+ if (lp->loopback_mode == LOOPBACK_PHY) {
+ u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
+
+ mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_TEST_CFG_L, test_cfg);
+
+ tx_cfg |= PLL_TX_CFG_ENTEST;
+ rx_cfg |= PLL_RX_CFG_ENTEST;
+ }
+
+ /* Initialize PLL for 10G */
+ pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X);
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_10g_serdes: "
+ "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
+ return err;
+ }
+
+ pll_sts = PLL_CFG_ENPLL;
+
+ err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
+ ESR2_TI_PLL_STS_L, pll_sts & 0xffff);
+ if (err) {
+ dev_err(np->device, PFX "NIU Port %d "
+ "serdes_init_niu_10g_serdes: "
+ "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
+ return err;
+ }
+
+ udelay(200);
+
+ /* Initialize all 4 lanes of the SERDES. */
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_tx_cfg(np, i, tx_cfg);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < 4; i++) {
+ err = esr2_set_rx_cfg(np, i, rx_cfg);
+ if (err)
+ return err;
+ }
+
+ /* check if serdes is ready */
+
+ switch (np->port) {
+ case 0:
+ mask = ESR_INT_SIGNALS_P0_BITS;
+ val = (ESR_INT_SRDY0_P0 |
+ ESR_INT_DET0_P0 |
+ ESR_INT_XSRDY_P0 |
+ ESR_INT_XDP_P0_CH3 |
+ ESR_INT_XDP_P0_CH2 |
+ ESR_INT_XDP_P0_CH1 |
+ ESR_INT_XDP_P0_CH0);
+ break;
+
+ case 1:
+ mask = ESR_INT_SIGNALS_P1_BITS;
+ val = (ESR_INT_SRDY0_P1 |
+ ESR_INT_DET0_P1 |
+ ESR_INT_XSRDY_P1 |
+ ESR_INT_XDP_P1_CH3 |
+ ESR_INT_XDP_P1_CH2 |
+ ESR_INT_XDP_P1_CH1 |
+ ESR_INT_XDP_P1_CH0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ while (max_retry--) {
+ sig = nr64(ESR_INT_SIGNALS);
+ if ((sig & mask) == val)
+ break;
+
+ mdelay(500);
+ }
+
+ if ((sig & mask) != val) {
+ pr_info(PFX "NIU Port %u signal bits [%08x] are not "
+ "[%08x] for 10G...trying 1G\n",
+ np->port, (int) (sig & mask), (int) val);
+
+ /* 10G failed, try initializing at 1G */
+ err = serdes_init_niu_1g_serdes(np);
+ if (!err) {
+ np->flags &= ~NIU_FLAGS_10G;
+ np->mac_xcvr = MAC_XCVR_PCS;
+ } else {
+ dev_err(np->device, PFX "Port %u 10G/1G SERDES "
+ "Link Failed \n", np->port);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val)
{
int err;
.link_status = link_status_10g_serdes,
};
+static const struct niu_phy_ops phy_ops_10g_serdes_niu = {
+ .serdes_init = serdes_init_niu_10g_serdes,
+ .link_status = link_status_10g_serdes,
+};
+
+static const struct niu_phy_ops phy_ops_1g_serdes_niu = {
+ .serdes_init = serdes_init_niu_1g_serdes,
+ .link_status = link_status_1g_serdes,
+};
+
static const struct niu_phy_ops phy_ops_1g_rgmii = {
.xcvr_init = xcvr_init_1g_rgmii,
.link_status = link_status_1g_rgmii,
};
static const struct niu_phy_ops phy_ops_10g_fiber_niu = {
- .serdes_init = serdes_init_niu,
+ .serdes_init = serdes_init_niu_10g_fiber,
.xcvr_init = xcvr_init_10g,
.link_status = link_status_10g,
};
u32 phy_addr_base;
};
-static const struct niu_phy_template phy_template_niu = {
+static const struct niu_phy_template phy_template_niu_10g_fiber = {
.ops = &phy_ops_10g_fiber_niu,
.phy_addr_base = 16,
};
+static const struct niu_phy_template phy_template_niu_10g_serdes = {
+ .ops = &phy_ops_10g_serdes_niu,
+ .phy_addr_base = 0,
+};
+
+static const struct niu_phy_template phy_template_niu_1g_serdes = {
+ .ops = &phy_ops_1g_serdes_niu,
+ .phy_addr_base = 0,
+};
+
static const struct niu_phy_template phy_template_10g_fiber = {
.ops = &phy_ops_10g_fiber,
.phy_addr_base = 8,
u32 phy_addr_off = 0;
if (plat_type == PLAT_TYPE_NIU) {
- tp = &phy_template_niu;
- phy_addr_off += np->port;
+ switch (np->flags &
+ (NIU_FLAGS_10G |
+ NIU_FLAGS_FIBER |
+ NIU_FLAGS_XCVR_SERDES)) {
+ case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
+ /* 10G Serdes */
+ tp = &phy_template_niu_10g_serdes;
+ break;
+ case NIU_FLAGS_XCVR_SERDES:
+ /* 1G Serdes */
+ tp = &phy_template_niu_1g_serdes;
+ break;
+ case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
+ /* 10G Fiber */
+ default:
+ tp = &phy_template_niu_10g_fiber;
+ phy_addr_off += np->port;
+ break;
+ }
} else {
switch (np->flags &
(NIU_FLAGS_10G |
np->flags |= NIU_FLAGS_10G;
np->flags &= ~NIU_FLAGS_FIBER;
np->mac_xcvr = MAC_XCVR_XPCS;
+ } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) {
+ /* 10G Serdes or 1G Serdes, default to 10G */
+ np->flags |= NIU_FLAGS_10G;
+ np->flags &= ~NIU_FLAGS_FIBER;
+ np->flags |= NIU_FLAGS_XCVR_SERDES;
+ np->mac_xcvr = MAC_XCVR_XPCS;
} else {
return -EINVAL;
}
u32 val;
int err;
+ num_10g = num_1g = 0;
+
if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) ||
!strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) {
num_10g = 0;
parent->num_ports = 2;
val = (phy_encode(PORT_TYPE_10G, 0) |
phy_encode(PORT_TYPE_10G, 1));
+ } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) &&
+ (parent->plat_type == PLAT_TYPE_NIU)) {
+ /* this is the Monza case */
+ if (np->flags & NIU_FLAGS_10G) {
+ val = (phy_encode(PORT_TYPE_10G, 0) |
+ phy_encode(PORT_TYPE_10G, 1));
+ } else {
+ val = (phy_encode(PORT_TYPE_1G, 0) |
+ phy_encode(PORT_TYPE_1G, 1));
+ }
} else {
err = fill_phy_probe_info(np, parent, info);
if (err)
dev->name,
(np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
(np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
- (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
+ (np->flags & NIU_FLAGS_FIBER ? "FIBER" :
+ (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" :
+ "COPPER")),
(np->mac_xcvr == MAC_XCVR_MII ? "MII" :
(np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
np->vpd.phy_type);
#define PLL_CFG_LD_SHIFT 8
#define PLL_CFG_MPY 0x0000001e
#define PLL_CFG_MPY_SHIFT 1
+#define PLL_CFG_MPY_4X 0x0
+#define PLL_CFG_MPY_5X 0x00000002
+#define PLL_CFG_MPY_6X 0x00000004
+#define PLL_CFG_MPY_8X 0x00000008
+#define PLL_CFG_MPY_10X 0x0000000a
+#define PLL_CFG_MPY_12X 0x0000000c
+#define PLL_CFG_MPY_12P5X 0x0000000e
#define PLL_CFG_ENPLL 0x00000001
#define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002)
#define PLL_TX_CFG_INVPAIR 0x00000080
#define PLL_TX_CFG_RATE 0x00000060
#define PLL_TX_CFG_RATE_SHIFT 5
+#define PLL_TX_CFG_RATE_FULL 0x0
+#define PLL_TX_CFG_RATE_HALF 0x20
+#define PLL_TX_CFG_RATE_QUAD 0x40
#define PLL_TX_CFG_BUSWIDTH 0x0000001c
#define PLL_TX_CFG_BUSWIDTH_SHIFT 2
#define PLL_TX_CFG_ENTEST 0x00000002
#define PLL_RX_CFG_INVPAIR 0x00000080
#define PLL_RX_CFG_RATE 0x00000060
#define PLL_RX_CFG_RATE_SHIFT 5
+#define PLL_RX_CFG_RATE_FULL 0x0
+#define PLL_RX_CFG_RATE_HALF 0x20
+#define PLL_RX_CFG_RATE_QUAD 0x40
#define PLL_RX_CFG_BUSWIDTH 0x0000001c
#define PLL_RX_CFG_BUSWIDTH_SHIFT 2
#define PLL_RX_CFG_ENTEST 0x00000002
return 0;
}
+static int m88e1118_config_aneg(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_M1011_PHY_SCR,
+ MII_M1011_PHY_SCR_AUTO_CROSS);
+ if (err < 0)
+ return err;
+
+ err = genphy_config_aneg(phydev);
+ return 0;
+}
+
+static int m88e1118_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ /* Change address */
+ err = phy_write(phydev, 0x16, 0x0002);
+ if (err < 0)
+ return err;
+
+ /* Enable 1000 Mbit */
+ err = phy_write(phydev, 0x15, 0x1070);
+ if (err < 0)
+ return err;
+
+ /* Change address */
+ err = phy_write(phydev, 0x16, 0x0003);
+ if (err < 0)
+ return err;
+
+ /* Adjust LED Control */
+ err = phy_write(phydev, 0x10, 0x021e);
+ if (err < 0)
+ return err;
+
+ /* Reset address */
+ err = phy_write(phydev, 0x16, 0x0);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static int m88e1145_config_init(struct phy_device *phydev)
{
int err;
.config_intr = &marvell_config_intr,
.driver = { .owner = THIS_MODULE },
},
+ {
+ .phy_id = 0x01410e10,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1118",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1118_config_init,
+ .config_aneg = &m88e1118_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
{
.phy_id = 0x01410cd0,
.phy_id_mask = 0xfffffff0,
BUG_ON(bus->state != MDIOBUS_REGISTERED);
bus->state = MDIOBUS_UNREGISTERED;
- device_unregister(&bus->dev);
+ device_del(&bus->dev);
for (i = 0; i < PHY_MAX_ADDR; i++) {
if (bus->phy_map[i])
device_unregister(&bus->phy_map[i]->dev);
if (r)
return ERR_PTR(r);
- /* If the phy_id is all Fs, there is no device there */
- if (0xffffffff == phy_id)
+ /* If the phy_id is all Fs or all 0s, there is no device there */
+ if ((0xffff == phy_id) || (0x00 == phy_id))
return NULL;
dev = phy_device_create(bus, addr, phy_id);
*/
int genphy_config_aneg(struct phy_device *phydev)
{
- int result = 0;
+ int result;
- if (AUTONEG_ENABLE == phydev->autoneg) {
- int result = genphy_config_advert(phydev);
+ if (AUTONEG_ENABLE != phydev->autoneg)
+ return genphy_setup_forced(phydev);
+
+ result = genphy_config_advert(phydev);
+
+ if (result < 0) /* error */
+ return result;
- if (result < 0) /* error */
- return result;
+ if (result == 0) {
+ /* Advertisment hasn't changed, but maybe aneg was never on to
+ * begin with? Or maybe phy was isolated? */
+ int ctl = phy_read(phydev, MII_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
+ result = 1; /* do restart aneg */
+ }
- /* Only restart aneg if we are advertising something different
- * than we were before. */
- if (result > 0)
- result = genphy_restart_aneg(phydev);
- } else
- result = genphy_setup_forced(phydev);
+ /* Only restart aneg if we are advertising something different
+ * than we were before. */
+ if (result > 0)
+ result = genphy_restart_aneg(phydev);
return result;
}
linkState = LS_UP;
} else {
linkState = LS_DOWN;
- if (netif_msg_link(qdev))
- printk(KERN_WARNING PFX
- "%s: Link is down.\n", qdev->ndev->name);
}
return linkState;
}
ql_mac_enable(qdev, 1);
}
- if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: Change port_link_state LS_DOWN to LS_UP.\n",
- qdev->ndev->name);
qdev->port_link_state = LS_UP;
netif_start_queue(qdev->ndev);
netif_carrier_on(qdev->ndev);
/* Fall Through */
case LS_DOWN:
- if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: port_link_state = LS_DOWN.\n",
- qdev->ndev->name);
if (curr_link_state == LS_UP) {
if (netif_msg_link(qdev))
- printk(KERN_DEBUG PFX
- "%s: curr_link_state = LS_UP.\n",
+ printk(KERN_INFO PFX "%s: Link is up.\n",
qdev->ndev->name);
if (ql_is_auto_neg_complete(qdev))
ql_finish_auto_neg(qdev);
if (qdev->port_link_state == LS_UP)
ql_link_down_detect_clear(qdev);
+ qdev->port_link_state = LS_UP;
}
break;
* See if the link is currently down or went down and came
* back up
*/
- if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) {
+ if (curr_link_state == LS_DOWN) {
if (netif_msg_link(qdev))
printk(KERN_INFO PFX "%s: Link is down.\n",
qdev->ndev->name);
qdev->port_link_state = LS_DOWN;
}
+ if (ql_link_down_detect(qdev))
+ qdev->port_link_state = LS_DOWN;
break;
}
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
struct sh_eth_private *mdp = netdev_priv(ndev);
struct sh_eth_txdesc *txdesc;
u32 entry;
- int flags;
+ unsigned long flags;
spin_lock_irqsave(&mdp->lock, flags);
if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
/* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii";
mdp->mii_bus->parent = &ndev->dev;
- mdp->mii_bus->id[0] = id;
+ snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id);
/* PHY IRQ */
mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
val = SMC_GET_BYTE_TEST(lp);
DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
if (val != 0x87654321) {
- printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
+ printk(KERN_ERR "Invalid chip endian 0x%08x\n",val);
retval = -ENODEV;
goto err_out;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
base = (u32 __iomem *)&ugeth->ug_regs->tx64;
for (i = 0; i < UEC_HW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = in_be32(&base[i]);
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram;
for (i = 0; i < UEC_TX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram;
for (i = 0; i < UEC_RX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
}
mode = AX88178_MEDIUM_DEFAULT;
if (ecmd.speed == SPEED_1000)
- mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
+ mode |= AX_MEDIUM_GM;
else if (ecmd.speed == SPEED_100)
mode |= AX_MEDIUM_PS;
else
mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+ mode |= AX_MEDIUM_ENCK;
+
if (ecmd.duplex == DUPLEX_FULL)
mode |= AX_MEDIUM_FD;
else
// Apple USB Ethernet Adapter
USB_DEVICE(0x05ac, 0x1402),
.driver_info = (unsigned long) &ax88772_info,
+}, {
+ // Cables-to-Go USB Ethernet Adapter
+ USB_DEVICE(0x0b95, 0x772a),
+ .driver_info = (unsigned long) &ax88772_info,
},
{ }, // END
};
}
mac_set_cam_mask(regs, vptr->mCAMmask);
- rx_mode = (RCR_AM | RCR_AB);
+ rx_mode = RCR_AM | RCR_AB | RCR_AP;
}
if (dev->mtu > 1500)
rx_mode |= RCR_AL;
rxq->queue[i] = NULL;
- pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
+ pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->aligned_dma_addr,
priv->hw_params.rx_buf_size,
PCI_DMA_FROMDEVICE);
pkt = (struct iwl_rx_packet *)rxb->skb->data;
rxb->skb = NULL;
}
- pci_unmap_single(priv->pci_dev, rxb->dma_addr,
- priv->hw_params.rx_buf_size,
+ pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
spin_lock_irqsave(&rxq->lock, flags);
list_add_tail(&rxb->list, &priv->rxq.rx_used);
mutex_lock(&priv->mutex);
iwl_alive_start(priv);
mutex_unlock(&priv->mutex);
- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
}
static void iwl4965_bg_rf_kill(struct work_struct *work)
#define DEFAULT_LONG_RETRY_LIMIT 4U
struct iwl_rx_mem_buffer {
- dma_addr_t dma_addr;
+ dma_addr_t real_dma_addr;
+ dma_addr_t aligned_dma_addr;
struct sk_buff *skb;
struct list_head list;
};
list_del(element);
/* Point to Rx buffer via next RBD in circular buffer */
- rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+ rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
/* Alloc a new receive buffer */
- rxb->skb = alloc_skb(priv->hw_params.rx_buf_size,
+ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
__GFP_NOWARN | GFP_ATOMIC);
if (!rxb->skb) {
if (net_ratelimit())
list_del(element);
/* Get physical address of RB/SKB */
- rxb->dma_addr =
- pci_map_single(priv->pci_dev, rxb->skb->data,
- priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
+ rxb->real_dma_addr = pci_map_single(
+ priv->pci_dev,
+ rxb->skb->data,
+ priv->hw_params.rx_buf_size + 256,
+ PCI_DMA_FROMDEVICE);
+ /* dma address must be no more than 36 bits */
+ BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));
+ /* and also 256 byte aligned! */
+ rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
+ skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
+
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
}
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
+ rxq->pool[i].real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(rxq->pool[i].skb);
}
* to an SKB, so we need to unmap and free potential storage */
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
+ rxq->pool[i].real_dma_addr,
+ priv->hw_params.rx_buf_size + 256,
PCI_DMA_FROMDEVICE);
priv->alloc_rxb_skb--;
dev_kfree_skb(rxq->pool[i].skb);
mutex_lock(&priv->mutex);
iwl3945_alive_start(priv);
mutex_unlock(&priv->mutex);
- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
}
static void iwl3945_bg_rf_kill(struct work_struct *work)
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail),
+ skb_tail_pointer(skb),
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp);
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
config PARPORT_PC
tristate "PC-style hardware"
depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
- (!M68K || ISA) && !MN10300 && !AVR32
+ (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
iommu->flush.flush_context = __iommu_flush_context;
iommu->flush.flush_iotlb = __iommu_flush_iotlb;
printk(KERN_INFO "IOMMU 0x%Lx: using Register based "
- "invalidation\n", drhd->reg_base_addr);
+ "invalidation\n",
+ (unsigned long long)drhd->reg_base_addr);
} else {
iommu->flush.flush_context = qi_flush_context;
iommu->flush.flush_iotlb = qi_flush_iotlb;
printk(KERN_INFO "IOMMU 0x%Lx: using Queued "
- "invalidation\n", drhd->reg_base_addr);
+ "invalidation\n",
+ (unsigned long long)drhd->reg_base_addr);
}
}
union acpi_object in_params[4];
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *out_obj;
- u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE];
+ u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE];
/* Setting up input parameters */
input.count = 4;
status = AE_TYPE;
goto out_kfree;
}
- osc_dw0 = *((u32 *)out_obj->buffer.pointer);
- if (osc_dw0) {
- if (osc_dw0 & OSC_REQUEST_ERROR)
+ /* Need to ignore the bit0 in result code */
+ errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+ if (errors) {
+ if (errors & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
- if (osc_dw0 & OSC_INVALID_UUID_ERROR)
+ if (errors & OSC_INVALID_UUID_ERROR)
printk(KERN_DEBUG "_OSC invalid UUID\n");
- if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
+ if (errors & OSC_INVALID_REVISION_ERROR)
printk(KERN_DEBUG "_OSC invalid revision\n");
- if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
+ if (errors & OSC_CAPABILITIES_MASK_ERROR) {
if (flags & OSC_QUERY_ENABLE)
goto out_success;
printk(KERN_DEBUG "_OSC FW not grant req. control\n");
if (!(cap & PCI_EXP_DEVCAP_FLR))
return -ENOTTY;
- if (!dev->msi_enabled && !dev->msix_enabled)
+ if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
disable_irq(dev->irq);
pci_save_state(dev);
r = pci_execute_reset_function(dev);
pci_restore_state(dev);
- if (!dev->msi_enabled && !dev->msix_enabled)
+ if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
enable_irq(dev->irq);
return r;
char *buf;
buf = kmalloc(256, GFP_KERNEL);
- if (buf == NULL)
+ if (buf == NULL) {
dev_printk(KERN_WARNING, &s->dev,
"no memory for verifying CIS\n");
return -ENOMEM;
+ }
list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len;
spin_lock_init(&socket->lock);
- if (socket->resource_ops->init) {
- ret = socket->resource_ops->init(socket);
- if (ret)
- return (ret);
- }
-
/* try to obtain a socket number [yes, it gets ugly if we
* register more than 2^sizeof(unsigned int) pcmcia
* sockets... but the socket number is deprecated
/* set proper values in socket->dev */
dev_set_drvdata(&socket->dev, socket);
socket->dev.class = &pcmcia_socket_class;
- snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock);
+ dev_set_name(&socket->dev, "pcmcia_socket%u", socket->sock);
/* base address = 0, map = 0 */
socket->cis_mem.flags = 0;
mutex_init(&socket->skt_mutex);
spin_lock_init(&socket->thread_lock);
+ if (socket->resource_ops->init) {
+ ret = socket->resource_ops->init(socket);
+ if (ret)
+ goto err;
+ }
+
tsk = kthread_run(pccardd, socket, "pccardd");
if (IS_ERR(tsk)) {
ret = PTR_ERR(tsk);
{
struct pcmcia_device *p_dev, *tmp_dev;
unsigned long flags;
- int bus_id_len;
s = pcmcia_get_socket(s);
if (!s)
/* by default don't allow DMA */
p_dev->dma_mask = DMA_MASK_NONE;
p_dev->dev.dma_mask = &p_dev->dma_mask;
- bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
-
- p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+ dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ if (!dev_name(&p_dev->dev))
+ goto err_free;
+ p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
if (!p_dev->devname)
goto err_free;
- sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
if (p_dev->func == tmp_dev->func) {
p_dev->function_config = tmp_dev->function_config;
+ p_dev->io = tmp_dev->io;
+ p_dev->irq = tmp_dev->irq;
kref_get(&p_dev->function_config->ref);
}
/* We only allow changing Vpp1 and Vpp2 to the same value */
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- if (mod->Vpp1 != mod->Vpp2)
+ if (mod->Vpp1 != mod->Vpp2) {
ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
return -EINVAL;
+ }
s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket)) {
dev_printk(KERN_WARNING, &s->dev,
======================================================================*/
static struct resource *
-make_resource(resource_size_t b, resource_size_t n, int flags, char *name)
+make_resource(resource_size_t b, resource_size_t n, int flags, const char *name)
{
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
static struct resource *nonstatic_find_io_region(unsigned long base, int num,
unsigned long align, struct pcmcia_socket *s)
{
- struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id);
+ struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev));
struct socket_data *s_data = s->resource_data;
struct pcmcia_align_data data;
unsigned long min = base;
static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
u_long align, int low, struct pcmcia_socket *s)
{
- struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id);
+ struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev));
struct socket_data *s_data = s->resource_data;
struct pcmcia_align_data data;
unsigned long min, max;
-/* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems.
+/* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems.
*
* Copyright (C) 2008 David S. Miller <davem@davemloft.net>
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <asm/hypervisor.h>
-MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
-MODULE_DESCRIPTION("SUN4V RTC driver");
-MODULE_LICENSE("GPL");
-
-struct sun4v_rtc {
- struct rtc_device *rtc;
- spinlock_t lock;
-};
-
static unsigned long hypervisor_get_time(void)
{
unsigned long ret, time;
static int sun4v_read_time(struct device *dev, struct rtc_time *tm)
{
- struct sun4v_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, secs;
-
- spin_lock_irqsave(&p->lock, flags);
- secs = hypervisor_get_time();
- spin_unlock_irqrestore(&p->lock, flags);
-
- rtc_time_to_tm(secs, tm);
-
+ rtc_time_to_tm(hypervisor_get_time(), tm);
return 0;
}
static int sun4v_set_time(struct device *dev, struct rtc_time *tm)
{
- struct sun4v_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, secs;
+ unsigned long secs;
int err;
err = rtc_tm_to_time(tm, &secs);
if (err)
return err;
- spin_lock_irqsave(&p->lock, flags);
- err = hypervisor_set_time(secs);
- spin_unlock_irqrestore(&p->lock, flags);
-
- return err;
+ return hypervisor_set_time(secs);
}
static const struct rtc_class_ops sun4v_rtc_ops = {
.set_time = sun4v_set_time,
};
-static int __devinit sun4v_rtc_probe(struct platform_device *pdev)
+static int __init sun4v_rtc_probe(struct platform_device *pdev)
{
- struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
-
- if (!p)
- return -ENOMEM;
-
- spin_lock_init(&p->lock);
-
- p->rtc = rtc_device_register("sun4v", &pdev->dev,
+ struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev,
&sun4v_rtc_ops, THIS_MODULE);
- if (IS_ERR(p->rtc)) {
- int err = PTR_ERR(p->rtc);
- kfree(p);
- return err;
- }
- platform_set_drvdata(pdev, p);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(pdev, rtc);
return 0;
}
-static int __devexit sun4v_rtc_remove(struct platform_device *pdev)
+static int __exit sun4v_rtc_remove(struct platform_device *pdev)
{
- struct sun4v_rtc *p = platform_get_drvdata(pdev);
-
- rtc_device_unregister(p->rtc);
- kfree(p);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ rtc_device_unregister(rtc);
return 0;
}
.name = "rtc-sun4v",
.owner = THIS_MODULE,
},
- .probe = sun4v_rtc_probe,
- .remove = __devexit_p(sun4v_rtc_remove),
+ .remove = __exit_p(sun4v_rtc_remove),
};
static int __init sun4v_rtc_init(void)
{
- return platform_driver_register(&sun4v_rtc_driver);
+ return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe);
}
static void __exit sun4v_rtc_exit(void)
module_init(sun4v_rtc_init);
module_exit(sun4v_rtc_exit);
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("SUN4V RTC driver");
+MODULE_LICENSE("GPL");
goto restart;
}
+ /* log sense for fatal error */
+ if (cqr->status == DASD_CQR_FAILED) {
+ dasd_log_sense(cqr, &cqr->irb);
+ }
+
/* First of all call extended error reporting. */
if (dasd_eer_enabled(base) &&
cqr->status == DASD_CQR_FAILED) {
case 0x0120:
break;
default:
+ pr_warning("assign storage failed (cmd=0x%08x, "
+ "response=0x%04x, rn=0x%04x)\n", cmd,
+ sccb->header.response_code, rn);
rc = -EIO;
break;
}
replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
if (replacing_cdev) {
sch_attach_disconnected_device(sch, replacing_cdev);
+ /* Release reference from get_disc_ccwdev_by_dev_id() */
+ put_device(&cdev->dev);
return;
}
replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id);
if (replacing_cdev) {
sch_attach_orphaned_device(sch, replacing_cdev);
+ /* Release reference from get_orphaned_ccwdev_by_dev_id() */
+ put_device(&cdev->dev);
return;
}
sch_create_and_recog_new_device(sch);
return rc;
}
- rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
+ rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
if (rc) {
s390_root_dev_unregister(kvm_root);
return rc;
}
- kvm_devices = (void *) PFN_PHYS(max_pfn);
+ kvm_devices = (void *) real_memory_size;
ctl_set_bit(0, 9);
register_external_interrupt(0x2603, kvm_extint_handler);
atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set(&port->refcount, 0);
- dev_set_name(&port->sysfs_device, "0x%016llx", wwpn);
+ dev_set_name(&port->sysfs_device, "0x%016llx",
+ (unsigned long long)wwpn);
port->sysfs_device.parent = &adapter->ccw_device->dev;
port->sysfs_device.release = zfcp_sysfs_port_release;
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
NULL);
zfcp_erp_wait(adapter);
- goto out;
+ up(&zfcp_data.config_sema);
+ flush_work(&adapter->scan_work);
+ return 0;
out_scsi_register:
zfcp_erp_thread_kill(adapter);
dump->offset = offset;
dump->size = min(from_len - offset, room);
memcpy(dump->data, from + offset, dump->size);
- debug_event(dbf, level, dump, dump->size);
+ debug_event(dbf, level, dump, dump->size + sizeof(*dump));
}
}
t.tv_sec, t.tv_nsec);
zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
} else {
- zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset,
+ zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset,
dump->total_size);
if ((dump->offset + dump->size) == dump->total_size)
p += sprintf(p, "\n");
break;
zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
+ p += sprintf(*p, "\n");
break;
case FSF_QTCB_OPEN_PORT_WITH_DID:
else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
zfcp_hba_dbf_view_berr(&p, &r->u.berr);
- p += sprintf(p, "\n");
+ if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0)
+ p += sprintf(p, "\n");
return p - out_buf;
}
struct ct_hdr *hdr = sg_virt(ct->req);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
+ int level = 3;
unsigned long flags;
spin_lock_irqsave(&adapter->san_dbf_lock, flags);
oct->options = hdr->options;
oct->max_res_size = hdr->max_res_size;
oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
- ZFCP_DBF_CT_PAYLOAD);
- memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len);
- debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+ ZFCP_DBF_SAN_MAX_PAYLOAD);
+ debug_event(adapter->san_dbf, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ (void *)hdr + sizeof(struct ct_hdr), oct->len);
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
struct ct_hdr *hdr = sg_virt(ct->resp);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
+ int level = 3;
unsigned long flags;
spin_lock_irqsave(&adapter->san_dbf_lock, flags);
rct->expl = hdr->reason_code_expl;
rct->vendor_unique = hdr->vendor_unique;
rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
- ZFCP_DBF_CT_PAYLOAD);
- memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len);
- debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+ ZFCP_DBF_SAN_MAX_PAYLOAD);
+ debug_event(adapter->san_dbf, level, r, sizeof(*r));
+ zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+ (void *)hdr + sizeof(struct ct_hdr), rct->len);
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
rec->u.els.ls_code = ls_code;
debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
- buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD));
+ buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
}
char *out_buf, const char *in_buf)
{
struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
- char *buffer = NULL;
- int buflen = 0, total = 0;
char *p = out_buf;
if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
- total = ct->len;
- buffer = ct->payload;
- buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
} else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
- total = ct->len;
- buffer = ct->payload;
- buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
} else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
struct zfcp_san_dbf_record_els *els = &r->u.els;
zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
- total = els->len;
- buffer = els->payload;
- buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
}
-
- zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total);
- if (buflen == total)
- p += sprintf(p, "\n");
-
return p - out_buf;
}
u8 options;
u16 max_res_size;
u32 len;
-#define ZFCP_DBF_CT_PAYLOAD 24
- u8 payload[ZFCP_DBF_CT_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record_ct_response {
u8 expl;
u8 vendor_unique;
u32 len;
- u8 payload[ZFCP_DBF_CT_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record_els {
u8 ls_code;
u32 len;
-#define ZFCP_DBF_ELS_PAYLOAD 32
-#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
- u8 payload[ZFCP_DBF_ELS_PAYLOAD];
} __attribute__ ((packed));
struct zfcp_san_dbf_record {
struct zfcp_san_dbf_record_ct_response ct_resp;
struct zfcp_san_dbf_record_els els;
} u;
+#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
+ u8 payload[32];
} __attribute__ ((packed));
struct zfcp_scsi_dbf_record {
ZFCP_STATUS_ERP_TIMEDOUT)) {
act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
zfcp_rec_dbf_event_action(142, act);
+ act->fsf_req->erp_action = NULL;
}
if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
zfcp_rec_dbf_event_action(143, act);
if (!req)
return NULL;
memset(req, 0, sizeof(*req));
+ req->pool = pool;
return req;
}
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
+ unsigned long flags;
int idx;
/* put allocated FSF request into hash table */
- spin_lock(&adapter->req_list_lock);
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
idx = zfcp_reqlist_hash(req->req_id);
list_add_tail(&req->list, &adapter->req_list[idx]);
- spin_unlock(&adapter->req_list_lock);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
- req->qdio_outb_usage = atomic_read(&req_q->count);
+ req->qdio_outb_usage = atomic_read(&adapter->req_q.count);
req->issued = get_clock();
if (zfcp_qdio_send(req)) {
- /* Queues are down..... */
del_timer(&req->timer);
- spin_lock(&adapter->req_list_lock);
- zfcp_reqlist_remove(adapter, req);
- spin_unlock(&adapter->req_list_lock);
- /* undo changes in request queue made for this request */
- atomic_add(req->sbal_number, &req_q->count);
- req_q->first -= req->sbal_number;
- req_q->first += QDIO_MAX_BUFFERS_PER_Q;
- req_q->first %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
+ /* lookup request again, list might have changed */
+ if (zfcp_reqlist_find_safe(adapter, req))
+ zfcp_reqlist_remove(adapter, req);
+ spin_unlock_irqrestore(&adapter->req_list_lock, flags);
zfcp_erp_adapter_reopen(adapter, 0, 116, req);
return -EIO;
}
static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
{
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
- WARN_ON(!unit);
- if (unit) {
- atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
- sdpnt->hostdata = NULL;
- unit->device = NULL;
- zfcp_erp_unit_failed(unit, 12, NULL);
- zfcp_unit_put(unit);
- }
+ atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
+ unit->device = NULL;
+ zfcp_erp_unit_failed(unit, 12, NULL);
+ zfcp_unit_put(unit);
}
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
hba_status = detailed_status >> 8;
// calculate resid for sg
- scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
+ scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20));
pHba = (adpt_hba*) cmd->device->host->hostdata[0];
case I2O_SCSI_DSC_SUCCESS:
cmd->result = (DID_OK << 16);
// handle underflow
- if(readl(reply+5) < cmd->underflow ) {
+ if (readl(reply+20) < cmd->underflow) {
cmd->result = (DID_ERROR <<16);
printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);
}
scb_t *scb;
int rval;
+ scmd = scsi_allocate_command(GFP_KERNEL);
+ if (!scmd)
+ return -ENOMEM;
+
/*
* The internal commands share one command id and hence are
* serialized. This is so because we want to reserve maximum number of
scb = &adapter->int_scb;
memset(scb, 0, sizeof(scb_t));
- scmd = &adapter->int_scmd;
- memset(scmd, 0, sizeof(Scsi_Cmnd));
-
sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
scmd->device = sdev;
+ memset(adapter->int_cdb, 0, sizeof(adapter->int_cdb));
+ scmd->cmnd = adapter->int_cdb;
scmd->device->host = adapter->host;
scmd->host_scribble = (void *)scb;
scmd->cmnd[0] = MEGA_INTERNAL_CMD;
mutex_unlock(&adapter->int_mtx);
+ scsi_free_command(GFP_KERNEL, scmd);
+
return rval;
}
u8 sglen; /* f/w supported scatter-gather list length */
+ unsigned char int_cdb[MAX_COMMAND_SIZE];
scb_t int_scb;
- Scsi_Cmnd int_scmd;
struct mutex int_mtx; /* To synchronize the internal
commands */
struct completion int_waitq; /* wait queue for internal
uint8_t fcode_revision[16];
uint32_t fw_revision[4];
- uint16_t fdt_odd_index;
uint32_t fdt_wrt_disable;
uint32_t fdt_erase_cmd;
uint32_t fdt_block_size;
qla2100_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
qla2300_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags = 0;
uint32_t cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
qla24xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
pcie_set_readrq(ha->pdev, 2048);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
ha->chip_revision = ha->pdev->revision;
qla25xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
- uint32_t d;
pci_set_master(ha->pdev);
pci_try_set_mwi(ha->pdev);
if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
pcie_set_readrq(ha->pdev, 2048);
- /* Reset expansion ROM address decode enable */
- pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
- d &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
+ pci_disable_rom(ha->pdev);
ha->chip_revision = ha->pdev->revision;
&ha->fw_minor_version,
&ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size);
- qla2x00_resize_request_q(ha);
ha->flags.npiv_supported = 0;
if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) ||
IS_QLA84XX(ha)) &&
ha->max_npiv_vports =
MIN_MULTI_ID_FABRIC - 1;
}
+ qla2x00_resize_request_q(ha);
if (ql2xallocfwdump)
qla2x00_alloc_fw_dump(ha);
*cur_iocb_cnt = mcp->mb[7];
if (orig_iocb_cnt)
*orig_iocb_cnt = mcp->mb[10];
- if (max_npiv_vports)
+ if (ha->flags.npiv_supported && max_npiv_vports)
*max_npiv_vports = mcp->mb[11];
}
if (ha->isp_ops->abort_command(ha, sp)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, ha->host_no));
+ ret = FAILED;
} else {
DEBUG3(printk("%s(%ld): abort_command "
"mbx success.\n", __func__, ha->host_no));
static void
qla2xxx_get_fdt_info(scsi_qla_host_t *ha)
{
+#define FLASH_BLK_SIZE_4K 0x1000
#define FLASH_BLK_SIZE_32K 0x8000
#define FLASH_BLK_SIZE_64K 0x10000
const char *loc, *locations[] = { "MID", "FDT" };
loc = locations[1];
mid = le16_to_cpu(fdt->man_id);
fid = le16_to_cpu(fdt->id);
- ha->fdt_odd_index = mid == 0x1f;
ha->fdt_wrt_disable = fdt->wrt_disable_bits;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
ha->fdt_block_size = le32_to_cpu(fdt->block_size);
ha->fdt_block_size = FLASH_BLK_SIZE_64K;
break;
case 0x1f: /* Atmel 26DF081A. */
- ha->fdt_odd_index = 1;
- ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ ha->fdt_block_size = FLASH_BLK_SIZE_4K;
ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
}
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x "
- "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
+ "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid,
ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
- ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
+ ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable,
ha->fdt_block_size));
}
qla24xx_unprotect_flash(ha);
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
- if (ha->fdt_odd_index) {
- findex = faddr << 2;
- fdata = findex & sec_mask;
- } else {
- findex = faddr;
- fdata = (findex & sec_mask) << 2;
- }
+
+ findex = faddr;
+ fdata = (findex & sec_mask) << 2;
/* Are we at the beginning of a sector? */
if ((findex & rest_addr) == 0) {
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k8"
+#define QLA2XXX_VERSION "8.02.01-k9"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
* LLD/transport was disrupted during processing of the IO.
* The transport class is now blocked/blocking,
* and the transport will decide what to do with the IO
- * based on its timers and recovery capablilities.
+ * based on its timers and recovery capablilities if
+ * there are enough retries.
*/
- return ADD_TO_MLQUEUE;
+ goto maybe_retry;
case DID_TRANSPORT_FAILFAST:
/*
* The transport decided to failfast the IO (most likely
status = sci_in(port, SCxSR);
} while (!(status & SCxSR_TDxE(port)));
- sci_out(port, SCxTDR, c);
sci_in(port, SCxSR); /* Dummy read */
sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ sci_out(port, SCxTDR, c);
spin_unlock_irqrestore(&port->lock, flags);
}
return;
}
- if (port->type == PORT_SCIF)
- count = scif_txroom(port);
- else
+ if (port->type == PORT_SCI)
count = sci_txroom(port);
+ else
+ count = scif_txroom(port);
do {
unsigned char c;
} else {
ctrl = sci_in(port, SCSCR);
- if (port->type == PORT_SCIF) {
+ if (port->type != PORT_SCI) {
sci_in(port, SCxSR); /* Dummy read */
sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
}
return;
while (1) {
- if (port->type == PORT_SCIF)
- count = scif_rxroom(port);
- else
+ if (port->type == PORT_SCI)
count = sci_rxroom(port);
+ else
+ count = scif_rxroom(port);
/* Don't copy more bytes than there is room for in the buffer */
count = tty_buffer_request_room(tty, count);
#if defined(SCIF_ORER)
/* XXX: Handle SCIF overrun error */
- if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+ if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
sci_out(port, SCLSR, 0);
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
copied++;
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
- if (port->type == PORT_SCIF)
+ if (port->type != PORT_SCI)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
smr_val = sci_in(port, SCSMR) & 3;
case PORT_SCI: return "sci";
case PORT_SCIF: return "scif";
case PORT_IRDA: return "irda";
+ case PORT_SCIFA: return "scifa";
}
return NULL;
s->init_pins = sci_init_pins_sci;
break;
case PORT_SCIF:
+ case PORT_SCIFA:
s->init_pins = sci_init_pins_scif;
break;
case PORT_IRDA:
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
static inline unsigned int sci_##name##_in(struct uart_port *port) \
{ \
- if (port->type == PORT_SCI) { \
- SCI_IN(sci_size, sci_offset) \
- } else { \
- SCI_IN(scif_size, scif_offset); \
+ if (port->type == PORT_SCIF) { \
+ SCI_IN(scif_size, scif_offset) \
+ } else { /* PORT_SCI or PORT_SCIFA */ \
+ SCI_IN(sci_size, sci_offset); \
} \
} \
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
{ \
- if (port->type == PORT_SCI) { \
- SCI_OUT(sci_size, sci_offset, value) \
- } else { \
- SCI_OUT(scif_size, scif_offset, value); \
+ if (port->type == PORT_SCIF) { \
+ SCI_OUT(scif_size, scif_offset, value) \
+ } else { /* PORT_SCI or PORT_SCIFA */ \
+ SCI_OUT(sci_size, sci_offset, value); \
} \
}
} else
drv_data->tx_map_len = drv_data->len;
- /* Stream map the rx buffer */
- drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
- drv_data->rx_map_len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, drv_data->rx_dma))
- return 0;
-
- /* Stream map the tx buffer */
+ /* Stream map the tx buffer. Always do DMA_TO_DEVICE first
+ * so we flush the cache *before* invalidating it, in case
+ * the tx and rx buffers overlap.
+ */
drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
- drv_data->tx_map_len,
- DMA_TO_DEVICE);
+ drv_data->tx_map_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, drv_data->tx_dma))
+ return 0;
- if (dma_mapping_error(dev, drv_data->tx_dma)) {
- dma_unmap_single(dev, drv_data->rx_dma,
+ /* Stream map the rx buffer */
+ drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
drv_data->rx_map_len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, drv_data->rx_dma)) {
+ dma_unmap_single(dev, drv_data->tx_dma,
+ drv_data->tx_map_len, DMA_TO_DEVICE);
return 0;
}
if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
return -1;
- /* NULL rx means write-only transfer and no map needed
- since rx DMA will not be used */
- if (drv_data->rx) {
- buf = drv_data->rx;
- drv_data->rx_dma = dma_map_single(
- dev,
- buf,
- drv_data->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dev, drv_data->rx_dma))
- return -1;
- drv_data->rx_dma_needs_unmap = 1;
- }
-
if (drv_data->tx == NULL) {
/* Read only message --> use drv_data->dummy_dma_buf for dummy
writes to achive reads */
buf,
drv_data->tx_map_len,
DMA_TO_DEVICE);
- if (dma_mapping_error(dev, drv_data->tx_dma)) {
- if (drv_data->rx_dma) {
- dma_unmap_single(dev,
- drv_data->rx_dma,
- drv_data->len,
- DMA_FROM_DEVICE);
- drv_data->rx_dma_needs_unmap = 0;
- }
+ if (dma_mapping_error(dev, drv_data->tx_dma))
return -1;
- }
drv_data->tx_dma_needs_unmap = 1;
+ /* NULL rx means write-only transfer and no map needed
+ * since rx DMA will not be used */
+ if (drv_data->rx) {
+ buf = drv_data->rx;
+ drv_data->rx_dma = dma_map_single(dev,
+ buf,
+ drv_data->len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, drv_data->rx_dma)) {
+ if (drv_data->tx_dma) {
+ dma_unmap_single(dev,
+ drv_data->tx_dma,
+ drv_data->tx_map_len,
+ DMA_TO_DEVICE);
+ drv_data->tx_dma_needs_unmap = 0;
+ }
+ return -1;
+ }
+ drv_data->rx_dma_needs_unmap = 1;
+ }
+
return 0;
}
}
/*
- * Finish write.
+ * Finish write. Caller must hold acm->write_lock
*/
static void acm_write_done(struct acm *acm, struct acm_wb *wb)
{
- unsigned long flags;
-
- spin_lock_irqsave(&acm->write_lock, flags);
wb->use = 0;
acm->transmitting--;
- spin_unlock_irqrestore(&acm->write_lock, flags);
}
/*
{
struct acm_wb *wb = urb->context;
struct acm *acm = wb->instance;
+ unsigned long flags;
if (verbose || urb->status
|| (urb->actual_length != urb->transfer_buffer_length))
urb->transfer_buffer_length,
urb->status);
+ spin_lock_irqsave(&acm->write_lock, flags);
acm_write_done(acm, wb);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
if (ACM_READY(acm))
schedule_work(&acm->work);
else
continue;
dev_dbg(&dev->dev, "unregistering interface %s\n",
dev_name(&interface->dev));
+ interface->unregistering = 1;
usb_remove_sysfs_intf_files(interface);
device_del(&interface->dev);
}
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
- if (intf->sysfs_files_created)
+ if (intf->sysfs_files_created || intf->unregistering)
return 0;
/* The interface string may be present in some altsettings
* Must be called when a user of a urb is finished with it. When the last user
* of the urb calls this function, the memory of the urb is freed.
*
- * Note: The transfer buffer associated with the urb is not freed, that must be
- * done elsewhere.
+ * Note: The transfer buffer associated with the urb is not freed unless the
+ * URB_FREE_BUFFER transfer flag is set.
*/
void usb_free_urb(struct urb *urb)
{
notify->wLength = cpu_to_le16(length);
memcpy(buf, data, length);
+ /* ep_queue() can complete immediately if it fills the fifo... */
+ spin_unlock(&acm->lock);
status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ spin_lock(&acm->lock);
+
if (status < 0) {
ERROR(acm->port.func.config->cdev,
"acm ttyGS%d can't notify serial state, %d\n",
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
- .bAlternateSetting = 1,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CDC_DATA,
.bInterfaceSubClass = 0,
__le32 *data = req->buf;
int status;
- if (atomic_inc_return(&rndis->notify_count))
+ if (atomic_inc_return(&rndis->notify_count) != 1)
return;
/* Send RNDIS RESPONSE_AVAILABLE notification; a
config USB_ISP1760_HCD
tristate "ISP 1760 HCD support"
- depends on USB && EXPERIMENTAL
+ depends on USB && EXPERIMENTAL && (PCI || PPC_OF)
---help---
The ISP1760 chip is a USB 2.0 host controller.
This driver does not support isochronous transfers or OTG.
+ This USB controller is usually attached to a non-DMA-Master
+ capable bus. NXP's eval kit brings this chip on PCI card
+ where the chip itself is behind a PLB to simulate such
+ a bus.
To compile this driver as a module, choose M here: the
- module will be called isp1760-hcd.
-
-config USB_ISP1760_PCI
- bool "Support for the PCI bus"
- depends on USB_ISP1760_HCD && PCI
- ---help---
- Enables support for the device present on the PCI bus.
- This should only be required if you happen to have the eval kit from
- NXP and you are going to test it.
-
-config USB_ISP1760_OF
- bool "Support for the OF platform bus"
- depends on USB_ISP1760_HCD && PPC_OF
- ---help---
- Enables support for the device present on the PowerPC
- OpenFirmware platform bus.
+ module will be called isp1760.
config USB_OHCI_HCD
tristate "OHCI HCD support"
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 status, pcd_status = 0, cmd;
+ u32 status, masked_status, pcd_status = 0, cmd;
int bh;
spin_lock (&ehci->lock);
goto dead;
}
- status &= INTR_MASK;
- if (!status) { /* irq sharing? */
+ masked_status = status & INTR_MASK;
+ if (!masked_status) { /* irq sharing? */
spin_unlock(&ehci->lock);
return IRQ_NONE;
}
/* clear (just) interrupts */
- ehci_writel(ehci, status, &ehci->regs->status);
+ ehci_writel(ehci, masked_status, &ehci->regs->status);
cmd = ehci_readl(ehci, &ehci->regs->command);
bh = 0;
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
+ ehci_err(ehci, "fatal error\n");
dbg_cmd(ehci, "fatal", cmd);
dbg_status(ehci, "fatal", status);
- if (status & STS_HALT) {
- ehci_err (ehci, "fatal error\n");
+ ehci_halt(ehci);
dead:
- ehci_reset (ehci);
- ehci_writel(ehci, 0, &ehci->regs->configured_flag);
- /* generic layer kills/unlinks all urbs, then
- * uses ehci_stop to clean up the rest
- */
- bh = 1;
- }
+ ehci_reset(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+ bh = 1;
}
if (bh)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ struct pci_dev *p_smbus;
+ u8 rev;
u32 temp;
int retval;
pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
}
break;
+ case PCI_VENDOR_ID_ATI:
+ /* SB700 old version has a bug in EHCI controller,
+ * which causes usb devices lose response in some cases.
+ */
+ if (pdev->device == 0x4396) {
+ p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
+ PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+ NULL);
+ if (!p_smbus)
+ break;
+ rev = p_smbus->revision;
+ if ((rev == 0x3a) || (rev == 0x3b)) {
+ u8 tmp;
+ pci_read_config_byte(pdev, 0x53, &tmp);
+ pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
+ }
+ pci_dev_put(p_smbus);
+ }
+ break;
}
ehci_reset(ehci);
tmp = hcd->irq;
+ ehci_shutdown(hcd);
usb_remove_hcd(hcd);
ps3_system_bus_set_driver_data(dev, NULL);
*/
stream->usecs = HS_USECS_ISO (maxp);
bandwidth = stream->usecs * 8;
- bandwidth /= 1 << (interval - 1);
+ bandwidth /= interval;
} else {
u32 addr;
} else
stream->raw_mask = smask_out [hs_transfers - 1];
bandwidth = stream->usecs + stream->c_usecs;
- bandwidth /= 1 << (interval + 2);
+ bandwidth /= interval << 3;
/* stream->splits gets created from raw_mask later */
stream->address = cpu_to_hc32(ehci, addr);
#include "../core/hcd.h"
#include "isp1760-hcd.h"
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
#include <linux/of.h>
#include <linux/of_platform.h>
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
static int of_isp1760_probe(struct of_device *dev,
const struct of_device_id *match)
{
};
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
static u32 nxp_pci_io_base;
static u32 iolength;
static u32 pci_mem_phy0;
static int __init isp1760_init(void)
{
- int ret = -ENODEV;
+ int ret;
init_kmem_once();
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
ret = of_register_platform_driver(&isp1760_of_driver);
if (ret) {
deinit_kmem_cache();
return ret;
}
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
ret = pci_register_driver(&isp1761_pci_driver);
if (ret)
goto unreg_of;
#endif
return ret;
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
unreg_of:
#endif
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
deinit_kmem_cache();
static void __exit isp1760_exit(void)
{
-#ifdef CONFIG_USB_ISP1760_OF
+#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
-#ifdef CONFIG_USB_ISP1760_PCI
+#ifdef CONFIG_PCI
pci_unregister_driver(&isp1761_pci_driver);
#endif
deinit_kmem_cache();
return result;
}
-static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
+static int ps3_ohci_remove(struct ps3_system_bus_device *dev)
{
unsigned int tmp;
struct usb_hcd *hcd =
tmp = hcd->irq;
+ ohci_shutdown(hcd);
usb_remove_hcd(hcd);
ps3_system_bus_set_driver_data(dev, NULL);
{
struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
unsigned long flags;
+ int port;
spin_lock_irqsave(&r8a66597->lock, flags);
- r8a66597_root_hub_control(r8a66597, 0);
- r8a66597_root_hub_control(r8a66597, 1);
+ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+ r8a66597_root_hub_control(r8a66597, port);
spin_unlock_irqrestore(&r8a66597->lock, flags);
}
{ USB_DEVICE(0x0711, 0x0900) },
{ USB_DEVICE(0x0711, 0x0901) },
{ USB_DEVICE(0x0711, 0x0902) },
+ { USB_DEVICE(0x0711, 0x0903) },
{ USB_DEVICE(0x0711, 0x0918) },
{ USB_DEVICE(0x182d, 0x021c) },
{ USB_DEVICE(0x182d, 0x0269) },
__func__);
retval = -EFAULT;
} else {
- dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n",
+ dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n",
__func__, usb_data.count, usb_data.pipe);
}
}
if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
- step_len = min(nbytes, (size_t)ep->len_cap);
+ step_len = ep->len_cap;
+ step_len -= rp->b_read - sizeof(struct mon_bin_hdr);
+ if (step_len > nbytes)
+ step_len = nbytes;
offset = rp->b_out + PKT_SIZE;
offset += rp->b_read - sizeof(struct mon_bin_hdr);
if (offset >= rp->b_size)
-unsigned debug;
-module_param(debug, uint, S_IRUGO | S_IWUSR);
+unsigned musb_debug;
+module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
"host"
#endif
", debug=%d\n",
- musb_driver_name, debug);
+ musb_driver_name, musb_debug);
return platform_driver_probe(&musb_driver, musb_probe);
}
__func__, __LINE__ , ## args); \
} } while (0)
-extern unsigned debug;
+extern unsigned musb_debug;
static inline int _dbg_level(unsigned l)
{
- return debug >= l;
+ return musb_debug >= l;
}
#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args)
switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ /* fifo policy for these lists, except that NAKing
+ * should rotate a qh to the end (for fairness).
+ */
+ if (qh->mux == 1) {
+ head = qh->ring.prev;
+ list_del(&qh->ring);
+ kfree(qh);
+ qh = first_qh(head);
+ break;
+ }
+
case USB_ENDPOINT_XFER_ISOC:
case USB_ENDPOINT_XFER_INT:
/* this is where periodic bandwidth should be
kfree(qh);
qh = NULL;
break;
-
- case USB_ENDPOINT_XFER_CONTROL:
- case USB_ENDPOINT_XFER_BULK:
- /* fifo policy for these lists, except that NAKing
- * should rotate a qh to the end (for fairness).
- */
- head = qh->ring.prev;
- list_del(&qh->ring);
- kfree(qh);
- qh = first_qh(head);
- break;
}
}
return qh;
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
#ifdef CONFIG_USB_INVENTRA_DMA
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = xfer_len;
+
+ /* even if there was an error, we did the dma
+ * for iso_frame_desc->length
+ */
+ if (d->status != EILSEQ && d->status != -EOVERFLOW)
+ d->status = 0;
+
+ if (++qh->iso_idx >= urb->number_of_packets)
+ done = true;
+ else
+ done = false;
+
+ } else {
/* done if urb buffer is full or short packet is recd */
done = (urb->actual_length + xfer_len >=
urb->transfer_buffer_length
|| dma->actual_len < qh->maxpacket);
+ }
/* send IN token for next packet, without AUTOREQ */
if (!done) {
if (dma) {
struct dma_controller *c;
u16 rx_count;
- int ret;
+ int ret, length;
+ dma_addr_t buf;
rx_count = musb_readw(epio, MUSB_RXCOUNT);
c = musb->dma_controller;
+ if (usb_pipeisoc(pipe)) {
+ int status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+
+ if (iso_err) {
+ status = -EILSEQ;
+ urb->error_count++;
+ }
+ if (rx_count > d->length) {
+ if (status == 0) {
+ status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ DBG(2, "** OVERFLOW %d into %d\n",\
+ rx_count, d->length);
+
+ length = d->length;
+ } else
+ length = rx_count;
+ d->status = status;
+ buf = urb->transfer_dma + d->offset;
+ } else {
+ length = rx_count;
+ buf = urb->transfer_dma +
+ urb->actual_length;
+ }
+
dma->desired_mode = 0;
#ifdef USE_MODE1
/* because of the issue below, mode 1 will
urb->actual_length)
> qh->maxpacket)
dma->desired_mode = 1;
+ if (rx_count < hw_ep->max_packet_sz_rx) {
+ length = rx_count;
+ dma->bDesiredMode = 0;
+ } else {
+ length = urb->transfer_buffer_length;
+ }
#endif
/* Disadvantage of using mode 1:
*/
ret = c->channel_program(
dma, qh->maxpacket,
- dma->desired_mode,
- urb->transfer_dma
- + urb->actual_length,
- (dma->desired_mode == 0)
- ? rx_count
- : urb->transfer_buffer_length);
+ dma->desired_mode, buf, length);
if (!ret) {
c->channel_release(dma);
}
}
- if (dma && usb_pipeisoc(pipe)) {
- struct usb_iso_packet_descriptor *d;
- int iso_stat = status;
-
- d = urb->iso_frame_desc + qh->iso_idx;
- d->actual_length += xfer_len;
- if (iso_err) {
- iso_stat = -EILSEQ;
- urb->error_count++;
- }
- d->status = iso_stat;
- }
-
finish:
urb->actual_length += xfer_len;
qh->offset += xfer_len;
struct list_head *head = NULL;
/* use fixed hardware for control and bulk */
- switch (qh->type) {
- case USB_ENDPOINT_XFER_CONTROL:
+ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
head = &musb->control;
hw_ep = musb->control_ep;
- break;
- case USB_ENDPOINT_XFER_BULK:
- hw_ep = musb->bulk_ep;
- if (is_in)
- head = &musb->in_bulk;
- else
- head = &musb->out_bulk;
- break;
- }
- if (head) {
- idle = list_empty(head);
- list_add_tail(&qh->ring, head);
goto success;
}
else
diff = hw_ep->max_packet_sz_tx - qh->maxpacket;
- if (diff > 0 && best_diff > diff) {
+ if (diff >= 0 && best_diff > diff) {
best_diff = diff;
best_end = epnum;
}
}
- if (best_end < 0)
+ /* use bulk reserved ep1 if no other ep is free */
+ if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
+ hw_ep = musb->bulk_ep;
+ if (is_in)
+ head = &musb->in_bulk;
+ else
+ head = &musb->out_bulk;
+ goto success;
+ } else if (best_end < 0) {
return -ENOSPC;
+ }
idle = 1;
+ qh->mux = 0;
hw_ep = musb->endpoints + best_end;
musb->periodic[best_end] = qh;
DBG(4, "qh %p periodic slot %d\n", qh, best_end);
success:
+ if (head) {
+ idle = list_empty(head);
+ list_add_tail(&qh->ring, head);
+ qh->mux = 1;
+ }
qh->hw_ep = hw_ep;
qh->hep->hcpriv = qh;
if (idle)
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
- if (usb_pipein(urb->pipe))
- sched = &musb->in_bulk;
- else
- sched = &musb->out_bulk;
- break;
+ if (qh->mux == 1) {
+ if (usb_pipein(urb->pipe))
+ sched = &musb->in_bulk;
+ else
+ sched = &musb->out_bulk;
+ break;
+ }
default:
/* REVISIT when we get a schedule tree, periodic
* transfers won't always be at the head of a
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
- if (is_in)
- sched = &musb->in_bulk;
- else
- sched = &musb->out_bulk;
- break;
+ if (qh->mux == 1) {
+ if (is_in)
+ sched = &musb->in_bulk;
+ else
+ sched = &musb->out_bulk;
+ break;
+ }
default:
/* REVISIT when we get a schedule tree, periodic transfers
* won't always be at the head of a singleton queue...
struct list_head ring; /* of musb_qh */
/* struct musb_qh *next; */ /* for periodic tree */
+ u8 mux; /* qh multiplexed to hw_ep */
unsigned offset; /* in urb->transfer_buffer */
unsigned segsize; /* current xfer fragment */
{
struct musb *musb = (void *)_musb;
unsigned long flags;
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
u8 power;
+#endif
u8 devctl;
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (musb->board_mode != MUSB_OTG) {
ERR("Changing mode currently only supported in OTG mode\n");
- return;
+ return -EINVAL;
}
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
static int debug;
static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
+ { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
+ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
#define NOVATELWIRELESS_VENDOR_ID 0x1410
+/* YISO PRODUCTS */
+
+#define YISO_VENDOR_ID 0x0EAB
+#define YISO_PRODUCT_U893 0xC893
+
/* MERLIN EVDO PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_V640 0x1100
#define NOVATELWIRELESS_PRODUCT_V620 0x1110
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
+ { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
# USB Storage driver configuration
#
-comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'"
-comment "may also be needed; see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;"
+comment "see USB_STORAGE Help for more information"
depends on USB
config USB_STORAGE
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Patch for Nokia 5310 capacity */
+UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591,
+ "Nokia",
+ "5310",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Mario Rettig <mariorettig@web.de> */
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
"Nokia",
US_FL_MAX_SECTORS_64 ),
/* Reported by Cedric Godin <cedric@belbone.be> */
-UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551,
+UNUSUAL_DEV( 0x0421, 0x04b9, 0x0500, 0x0551,
"Nokia",
"5300",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
/* Reported by Richard Nauber <RichardNauber@web.de> */
-UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601,
+UNUSUAL_DEV( 0x0421, 0x04fa, 0x0550, 0x0660,
"Nokia",
"6300",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Submitted by Ricky Wong Yung Fei <evilbladewarrior@gmail.com> */
+/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */
+UNUSUAL_DEV( 0x0421, 0x00f5, 0x0000, 0x0470,
+ "Nokia",
+ "7610 Supernova",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
"SMSC",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Reported by paul ready <lxtwin@homecall.co.uk> */
+UNUSUAL_DEV( 0x04b0, 0x0419, 0x0100, 0x0200,
+ "NIKON",
+ "NIKON DSC D300",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Reported by Doug Maxey (dwm@austin.ibm.com) */
UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110,
"IBM",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
+/* Reported by Luciano Rocha <luciano@eurotux.com> */
+UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001,
+ "Argosy",
+ "Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Flag will support Bulk devices which use a standards-violating 32-byte
* Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with
bl = backlight_device_register("backlight", &sinfo->pdev->dev,
sinfo, &atmel_lcdc_bl_ops);
- if (IS_ERR(sinfo->backlight)) {
+ if (IS_ERR(bl)) {
dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
PTR_ERR(bl));
return;
default:
dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
pdev->id);
+ kfree(data);
return -EINVAL;
}
data, &da903x_backlight_ops);
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
+ kfree(data);
return PTR_ERR(bl);
}
mutex_lock(&ld->ops_lock);
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
- if (event == FB_EVENT_BLANK)
- ld->ops->set_power(ld, *(int *)evdata->data);
- else
- ld->ops->set_mode(ld, evdata->data);
+ if (event == FB_EVENT_BLANK) {
+ if (ld->ops->set_power)
+ ld->ops->set_power(ld, *(int *)evdata->data);
+ } else {
+ if (ld->ops->set_mode)
+ ld->ops->set_mode(ld, evdata->data);
+ }
}
mutex_unlock(&ld->ops_lock);
return 0;
#ifndef MODULE
static int __init cirrusfb_setup(char *options) {
- char *this_opt, s[32];
- int i;
+ char *this_opt;
DPRINTK("ENTER\n");
greenshift = info->var.green.offset;
blueshift = info->var.blue.offset;
- for (i = 32; i < logo->clutsize; i++)
+ for (i = 32; i < 32 + logo->clutsize; i++)
palette[i] = i << redshift | i << greenshift | i << blueshift;
}
static int pxafb_smart_init(struct pxafb_info *fbi)
{
+ if (!(fbi->lccr0 | LCCR0_LCDT))
+ return 0;
+
fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
"lcd_refresh");
if (IS_ERR(fbi->smart_thread)) {
fbi->cmap_inverse = inf->cmap_inverse;
fbi->cmap_static = inf->cmap_static;
- switch (lcd_conn & 0xf) {
+ switch (lcd_conn & LCD_TYPE_MASK) {
case LCD_TYPE_MONO_STN:
fbi->lccr0 = LCCR0_CMS;
break;
unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
+ tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
+
+#ifdef CONFIG_FB_TMIO_ACCELL
/*
* We were in polling mode and now we got correct irq.
* Switch back to IRQ-based sync of command FIFO
par->use_polling = false;
}
- tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
-
-#ifdef CONFIG_FB_TMIO_ACCELL
if (bbisc & 1)
wake_up(&par->wait_acc);
#endif
static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
{
struct fb_info *info = platform_get_drvdata(dev);
+#ifdef CONFIG_FB_TMIO_ACCELL
struct tmiofb_par *par = info->par;
+#endif
struct mfd_cell *cell = dev->dev.platform_data;
int retval = 0;
info->fbops->fb_sync(info);
+#ifdef CONFIG_FB_TMIO_ACCELL
/*
* The fb should be usable even if interrupts are disabled (and they are
* during suspend/resume). Switch temporary to forced polling.
*/
printk(KERN_INFO "tmiofb: switching to polling\n");
par->use_polling = true;
+#endif
tmiofb_hw_stop(dev);
if (cell->suspend)
return count;
}
-static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
+static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
{
struct proc_dir_entry *entry;
- viafb_entry = proc_mkdir("viafb", NULL);
+ *viafb_entry = proc_mkdir("viafb", NULL);
if (viafb_entry) {
- entry = create_proc_entry("dvp0", 0, viafb_entry);
+ entry = create_proc_entry("dvp0", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dvp0_proc_read;
entry->write_proc = viafb_dvp0_proc_write;
}
- entry = create_proc_entry("dvp1", 0, viafb_entry);
+ entry = create_proc_entry("dvp1", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dvp1_proc_read;
entry->write_proc = viafb_dvp1_proc_write;
}
- entry = create_proc_entry("dfph", 0, viafb_entry);
+ entry = create_proc_entry("dfph", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dfph_proc_read;
entry->write_proc = viafb_dfph_proc_write;
}
- entry = create_proc_entry("dfpl", 0, viafb_entry);
+ entry = create_proc_entry("dfpl", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_dfpl_proc_read;
if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
lvds_chip_name || VT1636_LVDS ==
viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
- entry = create_proc_entry("vt1636", 0, viafb_entry);
+ entry = create_proc_entry("vt1636", 0, *viafb_entry);
if (entry) {
entry->owner = THIS_MODULE;
entry->read_proc = viafb_vt1636_proc_read;
remove_proc_entry("dfpl", viafb_entry);
remove_proc_entry("vt1636", viafb_entry);
remove_proc_entry("vt1625", viafb_entry);
+ remove_proc_entry("viafb", NULL);
}
static int __devinit via_pci_probe(void)
viafbinfo->node, viafbinfo->fix.id, default_var.xres,
default_var.yres, default_var.bits_per_pixel);
- viafb_init_proc(viaparinfo->proc_entry);
+ viafb_init_proc(&viaparinfo->proc_entry);
viafb_init_dac(IGA2);
return 0;
}
static u8 omap_w1_read_byte(void *_hdq);
static void omap_w1_write_byte(void *_hdq, u8 byte);
static u8 omap_w1_reset_bus(void *_hdq);
-static void omap_w1_search_bus(void *_hdq, u8 search_type,
- w1_slave_found_callback slave_found);
+static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
+ u8 search_type, w1_slave_found_callback slave_found);
static struct w1_bus_master omap_w1_master = {
}
/* W1 search callback function */
-static void omap_w1_search_bus(void *_hdq, u8 search_type,
- w1_slave_found_callback slave_found)
+static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
+ u8 search_type, w1_slave_found_callback slave_found)
{
u64 module_id, rn_le, cs, id;
cs = w1_calc_crc8((u8 *)&rn_le, 7);
id = (cs << 56) | module_id;
- slave_found(_hdq, id);
+ slave_found(master_dev, id);
}
static int _omap_hdq_reset(struct hdq_data *hdq_data)
static void scrub_page(struct page *page)
{
#ifdef CONFIG_XEN_SCRUB_PAGES
- if (PageHighMem(page)) {
- void *v = kmap(page);
- clear_page(v);
- kunmap(v);
- } else {
- void *v = page_address(page);
- clear_page(v);
- }
+ clear_highpage(page);
#endif
}
sends, and also let tcp autotune the socket send and receive buffers.
This reduces the number of EAGAIN errors returned by TCP/IP in
high stress workloads (and the number of retries on socket writes
-when sending large SMBWriteX requests).
+when sending large SMBWriteX requests). Fix case in which a portion of
+data can in some cases not get written to the file on the server before the
+file is closed. Fix DFS parsing to properly handle path consumed field,
+and to handle certain codepage conversions better. Fix mount and
+umount race that can cause oops in mount or umount or reconnect.
Version 1.54
------------
#ifdef CONFIG_PROC_FS
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
- struct list_head *tmp;
- struct list_head *tmp1;
+ struct list_head *tmp1, *tmp2, *tmp3;
struct mid_q_entry *mid_entry;
+ struct TCP_Server_Info *server;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
- int i;
+ int i, j;
+ __u32 dev_type;
seq_puts(m,
"Display Internal CIFS Data Structures for Debugging\n"
seq_printf(m, "Servers:");
i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
i++;
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
- (ses->serverNOS == NULL)) {
- seq_printf(m, "\nentry for %s not fully "
- "displayed\n\t", ses->serverName);
- } else {
- seq_printf(m,
- "\n%d) Name: %s Domain: %s Mounts: %d OS:"
- " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ if ((ses->serverDomain == NULL) ||
+ (ses->serverOS == NULL) ||
+ (ses->serverNOS == NULL)) {
+ seq_printf(m, "\n%d) entry for %s not fully "
+ "displayed\n\t", i, ses->serverName);
+ } else {
+ seq_printf(m,
+ "\n%d) Name: %s Domain: %s Uses: %d OS:"
+ " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
" session status: %d\t",
i, ses->serverName, ses->serverDomain,
- atomic_read(&ses->inUse),
- ses->serverOS, ses->serverNOS,
+ ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->status);
- }
- if (ses->server) {
+ }
seq_printf(m, "TCP status: %d\n\tLocal Users To "
- "Server: %d SecMode: 0x%x Req On Wire: %d",
- ses->server->tcpStatus,
- atomic_read(&ses->server->socketUseCount),
- ses->server->secMode,
- atomic_read(&ses->server->inFlight));
+ "Server: %d SecMode: 0x%x Req On Wire: %d",
+ server->tcpStatus, server->srv_count,
+ server->secMode,
+ atomic_read(&server->inFlight));
#ifdef CONFIG_CIFS_STATS2
seq_printf(m, " In Send: %d In MaxReq Wait: %d",
- atomic_read(&ses->server->inSend),
- atomic_read(&ses->server->num_waiters));
+ atomic_read(&server->inSend),
+ atomic_read(&server->num_waiters));
#endif
- seq_puts(m, "\nMIDs:\n");
+ seq_puts(m, "\n\tShares:");
+ j = 0;
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3, struct cifsTconInfo,
+ tcon_list);
+ ++j;
+ dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+ seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
+ tcon->treeName, tcon->tc_count);
+ if (tcon->nativeFileSystem) {
+ seq_printf(m, "Type: %s ",
+ tcon->nativeFileSystem);
+ }
+ seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
+ "\nPathComponentMax: %d Status: 0x%d",
+ le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+ le32_to_cpu(tcon->fsAttrInfo.Attributes),
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+ tcon->tidStatus);
+ if (dev_type == FILE_DEVICE_DISK)
+ seq_puts(m, " type: DISK ");
+ else if (dev_type == FILE_DEVICE_CD_ROM)
+ seq_puts(m, " type: CDROM ");
+ else
+ seq_printf(m, " type: %d ", dev_type);
+
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_putc(m, '\n');
+ }
+
+ seq_puts(m, "\n\tMIDs:\n");
spin_lock(&GlobalMid_Lock);
- list_for_each(tmp1, &ses->server->pending_mid_q) {
- mid_entry = list_entry(tmp1, struct
- mid_q_entry,
+ list_for_each(tmp3, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp3, struct mid_q_entry,
qhead);
- seq_printf(m, "State: %d com: %d pid:"
+ seq_printf(m, "\tState: %d com: %d pid:"
" %d tsk: %p mid %d\n",
mid_entry->midState,
(int)mid_entry->command,
}
spin_unlock(&GlobalMid_Lock);
}
-
- }
- read_unlock(&GlobalSMBSeslock);
- seq_putc(m, '\n');
-
- seq_puts(m, "Shares:");
-
- i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- __u32 dev_type;
- i++;
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
- seq_printf(m, "\n%d) %s Uses: %d ", i,
- tcon->treeName, atomic_read(&tcon->useCount));
- if (tcon->nativeFileSystem) {
- seq_printf(m, "Type: %s ",
- tcon->nativeFileSystem);
- }
- seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
- "\nPathComponentMax: %d Status: %d",
- le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
- le32_to_cpu(tcon->fsAttrInfo.Attributes),
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
- tcon->tidStatus);
- if (dev_type == FILE_DEVICE_DISK)
- seq_puts(m, " type: DISK ");
- else if (dev_type == FILE_DEVICE_CD_ROM)
- seq_puts(m, " type: CDROM ");
- else
- seq_printf(m, " type: %d ", dev_type);
-
- if (tcon->tidStatus == CifsNeedReconnect)
- seq_puts(m, "\tDISCONNECTED ");
}
- read_unlock(&GlobalSMBSeslock);
-
+ read_unlock(&cifs_tcp_ses_lock);
seq_putc(m, '\n');
/* BB add code to dump additional info such as TCP session info now */
{
char c;
int rc;
- struct list_head *tmp;
+ struct list_head *tmp1, *tmp2, *tmp3;
+ struct TCP_Server_Info *server;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
rc = get_user(c, buffer);
return rc;
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
- read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2
atomic_set(&totBufAllocCount, 0);
atomic_set(&totSmBufAllocCount, 0);
#endif /* CONFIG_CIFS_STATS2 */
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo,
- cifsConnectionList);
- atomic_set(&tcon->num_smbs_sent, 0);
- atomic_set(&tcon->num_writes, 0);
- atomic_set(&tcon->num_reads, 0);
- atomic_set(&tcon->num_oplock_brks, 0);
- atomic_set(&tcon->num_opens, 0);
- atomic_set(&tcon->num_closes, 0);
- atomic_set(&tcon->num_deletes, 0);
- atomic_set(&tcon->num_mkdirs, 0);
- atomic_set(&tcon->num_rmdirs, 0);
- atomic_set(&tcon->num_renames, 0);
- atomic_set(&tcon->num_t2renames, 0);
- atomic_set(&tcon->num_ffirst, 0);
- atomic_set(&tcon->num_fnext, 0);
- atomic_set(&tcon->num_fclose, 0);
- atomic_set(&tcon->num_hardlinks, 0);
- atomic_set(&tcon->num_symlinks, 0);
- atomic_set(&tcon->num_locks, 0);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3,
+ struct cifsTconInfo,
+ tcon_list);
+ atomic_set(&tcon->num_smbs_sent, 0);
+ atomic_set(&tcon->num_writes, 0);
+ atomic_set(&tcon->num_reads, 0);
+ atomic_set(&tcon->num_oplock_brks, 0);
+ atomic_set(&tcon->num_opens, 0);
+ atomic_set(&tcon->num_closes, 0);
+ atomic_set(&tcon->num_deletes, 0);
+ atomic_set(&tcon->num_mkdirs, 0);
+ atomic_set(&tcon->num_rmdirs, 0);
+ atomic_set(&tcon->num_renames, 0);
+ atomic_set(&tcon->num_t2renames, 0);
+ atomic_set(&tcon->num_ffirst, 0);
+ atomic_set(&tcon->num_fnext, 0);
+ atomic_set(&tcon->num_fclose, 0);
+ atomic_set(&tcon->num_hardlinks, 0);
+ atomic_set(&tcon->num_symlinks, 0);
+ atomic_set(&tcon->num_locks, 0);
+ }
+ }
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
}
return count;
static int cifs_stats_proc_show(struct seq_file *m, void *v)
{
int i;
- struct list_head *tmp;
+ struct list_head *tmp1, *tmp2, *tmp3;
+ struct TCP_Server_Info *server;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
seq_printf(m,
GlobalCurrentXid, GlobalMaxActiveXid);
i = 0;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- i++;
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- seq_printf(m, "\n%d) %s", i, tcon->treeName);
- if (tcon->tidStatus == CifsNeedReconnect)
- seq_puts(m, "\tDISCONNECTED ");
- seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
- atomic_read(&tcon->num_smbs_sent),
- atomic_read(&tcon->num_oplock_brks));
- seq_printf(m, "\nReads: %d Bytes: %lld",
- atomic_read(&tcon->num_reads),
- (long long)(tcon->bytes_read));
- seq_printf(m, "\nWrites: %d Bytes: %lld",
- atomic_read(&tcon->num_writes),
- (long long)(tcon->bytes_written));
- seq_printf(m,
- "\nLocks: %d HardLinks: %d Symlinks: %d",
- atomic_read(&tcon->num_locks),
- atomic_read(&tcon->num_hardlinks),
- atomic_read(&tcon->num_symlinks));
-
- seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
- atomic_read(&tcon->num_opens),
- atomic_read(&tcon->num_closes),
- atomic_read(&tcon->num_deletes));
- seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
- atomic_read(&tcon->num_mkdirs),
- atomic_read(&tcon->num_rmdirs));
- seq_printf(m, "\nRenames: %d T2 Renames %d",
- atomic_read(&tcon->num_renames),
- atomic_read(&tcon->num_t2renames));
- seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
- atomic_read(&tcon->num_ffirst),
- atomic_read(&tcon->num_fnext),
- atomic_read(&tcon->num_fclose));
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp1, &cifs_tcp_ses_list) {
+ server = list_entry(tmp1, struct TCP_Server_Info,
+ tcp_ses_list);
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifsSesInfo,
+ smb_ses_list);
+ list_for_each(tmp3, &ses->tcon_list) {
+ tcon = list_entry(tmp3,
+ struct cifsTconInfo,
+ tcon_list);
+ i++;
+ seq_printf(m, "\n%d) %s", i, tcon->treeName);
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
+ atomic_read(&tcon->num_smbs_sent),
+ atomic_read(&tcon->num_oplock_brks));
+ seq_printf(m, "\nReads: %d Bytes: %lld",
+ atomic_read(&tcon->num_reads),
+ (long long)(tcon->bytes_read));
+ seq_printf(m, "\nWrites: %d Bytes: %lld",
+ atomic_read(&tcon->num_writes),
+ (long long)(tcon->bytes_written));
+ seq_printf(m, "\nLocks: %d HardLinks: %d "
+ "Symlinks: %d",
+ atomic_read(&tcon->num_locks),
+ atomic_read(&tcon->num_hardlinks),
+ atomic_read(&tcon->num_symlinks));
+ seq_printf(m, "\nOpens: %d Closes: %d"
+ "Deletes: %d",
+ atomic_read(&tcon->num_opens),
+ atomic_read(&tcon->num_closes),
+ atomic_read(&tcon->num_deletes));
+ seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
+ atomic_read(&tcon->num_mkdirs),
+ atomic_read(&tcon->num_rmdirs));
+ seq_printf(m, "\nRenames: %d T2 Renames %d",
+ atomic_read(&tcon->num_renames),
+ atomic_read(&tcon->num_t2renames));
+ seq_printf(m, "\nFindFirst: %d FNext %d "
+ "FClose %d",
+ atomic_read(&tcon->num_ffirst),
+ atomic_read(&tcon->num_fnext),
+ atomic_read(&tcon->num_fclose));
+ }
+ }
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
seq_putc(m, '\n');
return 0;
/**
* compose_mount_options - creates mount options for refferral
* @sb_mountdata: parent/root DFS mount options (template)
- * @ref_unc: refferral server UNC
+ * @dentry: point where we are going to mount
+ * @ref: server's referral
* @devname: pointer for saving device name
*
* creates mount options for submount based on template options sb_mountdata
* Caller is responcible for freeing retunrned value if it is not error.
*/
static char *compose_mount_options(const char *sb_mountdata,
- const char *ref_unc,
+ struct dentry *dentry,
+ const struct dfs_info3_param *ref,
char **devname)
{
int rc;
char *srvIP = NULL;
char sep = ',';
int off, noff;
+ char *fullpath;
if (sb_mountdata == NULL)
return ERR_PTR(-EINVAL);
- *devname = cifs_get_share_name(ref_unc);
+ *devname = cifs_get_share_name(ref->node_name);
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) {
cERROR(1, ("%s: Failed to resolve server part of %s to IP",
mountdata = ERR_PTR(rc);
goto compose_mount_options_out;
}
- md_len = strlen(sb_mountdata) + strlen(srvIP) + strlen(ref_unc) + 3;
+ /* md_len = strlen(...) + 12 for 'sep+prefixpath='
+ * assuming that we have 'unc=' and 'ip=' in
+ * the original sb_mountdata
+ */
+ md_len = strlen(sb_mountdata) + strlen(srvIP) +
+ strlen(ref->node_name) + 12;
mountdata = kzalloc(md_len+1, GFP_KERNEL);
if (mountdata == NULL) {
mountdata = ERR_PTR(-ENOMEM);
strncpy(mountdata, sb_mountdata, 5);
off += 5;
}
- while ((tkn_e = strchr(sb_mountdata+off, sep))) {
- noff = (tkn_e - (sb_mountdata+off)) + 1;
- if (strnicmp(sb_mountdata+off, "unc=", 4) == 0) {
+
+ do {
+ tkn_e = strchr(sb_mountdata + off, sep);
+ if (tkn_e == NULL)
+ noff = strlen(sb_mountdata + off);
+ else
+ noff = tkn_e - (sb_mountdata + off) + 1;
+
+ if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata+off, "ip=", 3) == 0) {
+ if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) {
off += noff;
continue;
}
- if (strnicmp(sb_mountdata+off, "prefixpath=", 3) == 0) {
+ if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
off += noff;
continue;
}
- strncat(mountdata, sb_mountdata+off, noff);
+ strncat(mountdata, sb_mountdata + off, noff);
off += noff;
- }
- strcat(mountdata, sb_mountdata+off);
+ } while (tkn_e);
+ strcat(mountdata, sb_mountdata + off);
mountdata[md_len] = '\0';
/* copy new IP and ref share name */
- strcat(mountdata, ",ip=");
+ if (mountdata[strlen(mountdata) - 1] != sep)
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "ip=");
strcat(mountdata, srvIP);
- strcat(mountdata, ",unc=");
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "unc=");
strcat(mountdata, *devname);
/* find & copy prefixpath */
- tkn_e = strchr(ref_unc+2, '\\');
- if (tkn_e) {
- tkn_e = strchr(tkn_e+1, '\\');
- if (tkn_e) {
- strcat(mountdata, ",prefixpath=");
- strcat(mountdata, tkn_e+1);
- }
+ tkn_e = strchr(ref->node_name + 2, '\\');
+ if (tkn_e == NULL) /* invalid unc, missing share name*/
+ goto compose_mount_options_out;
+
+ fullpath = build_path_from_dentry(dentry);
+ tkn_e = strchr(tkn_e + 1, '\\');
+ if (tkn_e || strlen(fullpath) - (ref->path_consumed)) {
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "prefixpath=");
+ if (tkn_e)
+ strcat(mountdata, tkn_e + 1);
+ strcat(mountdata, fullpath + (ref->path_consumed));
}
+ kfree(fullpath);
/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
- struct dentry *dentry, char *ref_unc)
+ struct dentry *dentry, const struct dfs_info3_param *ref)
{
struct cifs_sb_info *cifs_sb;
struct vfsmount *mnt;
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
mountdata = compose_mount_options(cifs_sb->mountdata,
- ref_unc, &devname);
+ dentry, ref, &devname);
if (IS_ERR(mountdata))
return (struct vfsmount *)mountdata;
}
mnt = cifs_dfs_do_refmount(nd->path.mnt,
nd->path.dentry,
- referrals[i].node_name);
+ referrals + i);
cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
__func__,
referrals[i].node_name, mnt));
* strlen(";sec=ntlmsspi") */
#define MAX_MECH_STR_LEN 13
-/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
-#define MAX_IPV6_ADDR_LEN 42
+/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
+#define MAX_IPV6_ADDR_LEN 43
/* strlen of "host=" */
#define HOST_KEY_LEN 5
tcon = cifs_sb->tcon;
if (tcon == NULL)
return;
- down(&tcon->tconSem);
- if (atomic_read(&tcon->useCount) == 1)
+
+ read_lock(&cifs_tcp_ses_lock);
+ if (tcon->tc_count == 1)
tcon->tidStatus = CifsExiting;
- up(&tcon->tconSem);
+ read_unlock(&cifs_tcp_ses_lock);
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
not bother sending an oplock release if session
to server still is disconnected since oplock
already released by the server in that case */
- if (pTcon->tidStatus != CifsNeedReconnect) {
+ if (!pTcon->need_reconnect) {
rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
static int cifs_dnotify_thread(void *dummyarg)
{
struct list_head *tmp;
- struct cifsSesInfo *ses;
+ struct TCP_Server_Info *server;
do {
if (try_to_freeze())
continue;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(15*HZ);
- read_lock(&GlobalSMBSeslock);
/* check if any stuck requests that need
to be woken up and wakeq so the
thread can wake up and error out */
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server && atomic_read(&ses->server->inFlight))
- wake_up_all(&ses->server->response_q);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &cifs_tcp_ses_list) {
+ server = list_entry(tmp, struct TCP_Server_Info,
+ tcp_ses_list);
+ if (atomic_read(&server->inFlight))
+ wake_up_all(&server->response_q);
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
} while (!kthread_should_stop());
return 0;
{
int rc = 0;
cifs_proc_init();
-/* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */
- INIT_LIST_HEAD(&GlobalSMBSessionList);
- INIT_LIST_HEAD(&GlobalTreeConnectionList);
+ INIT_LIST_HEAD(&cifs_tcp_ses_list);
INIT_LIST_HEAD(&GlobalOplock_Q);
#ifdef CONFIG_CIFS_EXPERIMENTAL
INIT_LIST_HEAD(&GlobalDnotifyReqList);
GlobalMaxActiveXid = 0;
memset(Local_System_Name, 0, 15);
rwlock_init(&GlobalSMBSeslock);
+ rwlock_init(&cifs_tcp_ses_lock);
spin_lock_init(&GlobalMid_Lock);
if (cifs_max_pending < 2) {
};
enum protocolEnum {
- IPV4 = 0,
- IPV6,
+ TCP = 0,
SCTP
/* Netbios frames protocol not supported at this time */
};
*/
struct TCP_Server_Info {
+ struct list_head tcp_ses_list;
+ struct list_head smb_ses_list;
+ int srv_count; /* reference counter */
/* 15 character server name + 0x20 16th byte indicating type = srv */
char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
bool svlocal:1; /* local server or remote */
bool noblocksnd; /* use blocking sendmsg */
bool noautotune; /* do not autotune send buf sizes */
- atomic_t socketUseCount; /* number of open cifs sessions on socket */
atomic_t inFlight; /* number of requests on the wire to server */
#ifdef CONFIG_CIFS_STATS2
atomic_t inSend; /* requests trying to send */
* Session structure. One of these for each uid session with a particular host
*/
struct cifsSesInfo {
- struct list_head cifsSessionList;
+ struct list_head smb_ses_list;
+ struct list_head tcon_list;
struct semaphore sesSem;
#if 0
struct cifsUidInfo *uidInfo; /* pointer to user info */
#endif
struct TCP_Server_Info *server; /* pointer to server info */
- atomic_t inUse; /* # of mounts (tree connections) on this ses */
+ int ses_count; /* reference counter */
enum statusEnum status;
unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u16 ipc_tid; /* special tid for connection to IPC share */
char userName[MAX_USERNAME_SIZE + 1];
char *domainName;
char *password;
+ bool need_reconnect:1; /* connection reset, uid now invalid */
};
/* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1
* session
*/
struct cifsTconInfo {
- struct list_head cifsConnectionList;
+ struct list_head tcon_list;
+ int tc_count;
struct list_head openFileList;
- struct semaphore tconSem;
struct cifsSesInfo *ses; /* pointer to session associated with */
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
char *nativeFileSystem;
__u16 tid; /* The 2 byte tree id */
__u16 Flags; /* optional support bits */
enum statusEnum tidStatus;
- atomic_t useCount; /* how many explicit/implicit mounts to share */
#ifdef CONFIG_CIFS_STATS
atomic_t num_smbs_sent;
atomic_t num_writes;
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
for this mount even if server would support */
bool local_lease:1; /* check leases (only) on local system not remote */
+ bool need_reconnect:1; /* connection reset, tid now invalid */
/* BB add field for back pointer to sb struct(s)? */
};
#endif
/*
- * The list of servers that did not respond with NT LM 0.12.
- * This list helps improve performance and eliminate the messages indicating
- * that we had a communications error talking to the server in this list.
+ * the list of TCP_Server_Info structures, ie each of the sockets
+ * connecting our client to a distinct server (ip address), is
+ * chained together by cifs_tcp_ses_list. The list of all our SMB
+ * sessions (and from that the tree connections) can be found
+ * by iterating over cifs_tcp_ses_list
*/
-/* Feature not supported */
-/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
+GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
/*
- * The following is a hash table of all the users we know about.
+ * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
+ * tcp session, and the list of tcon's per smb session. It also protects
+ * the reference counters for the server, smb session, and tcon. Finally,
+ * changes to the tcon->tidStatus should be done while holding this lock.
*/
-GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
+GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
-/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
-GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
-GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
+/*
+ * This lock protects the cifs_file->llist and cifs_file->flist
+ * list operations, and updates to some flags (cifs_file->invalidHandle)
+ * It will be moved to either use the tcon->stat_lock or equivalent later.
+ * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
+ * the cifs_tcp_ses_lock must be grabbed first and released last.
+ */
+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
- if (tcon->ses->status == CifsNeedReconnect)
+ if (tcon->ses->need_reconnect)
rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
- if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ if (!rc && (tcon->need_reconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
- if (tcon->ses->status == CifsNeedReconnect)
+ if (tcon->ses->need_reconnect)
rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
- if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ if (!rc && (tcon->need_reconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
rc = -EIO;
goto neg_err_exit;
}
-
- if (server->socketUseCount.counter > 1) {
+ read_lock(&cifs_tcp_ses_lock);
+ if (server->srv_count > 1) {
+ read_unlock(&cifs_tcp_ses_lock);
if (memcmp(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
pSMBr->u.extended_response.GUID,
16);
}
- } else
+ } else {
+ read_unlock(&cifs_tcp_ses_lock);
memcpy(server->server_GUID,
pSMBr->u.extended_response.GUID, 16);
+ }
if (count == 16) {
server->secType = RawNTLMSSP;
int rc = 0;
cFYI(1, ("In tree disconnect"));
- /*
- * If last user of the connection and
- * connection alive - disconnect it
- * If this is the last connection on the server session disconnect it
- * (and inside session disconnect we should check if tcp socket needs
- * to be freed and kernel thread woken up).
- */
- if (tcon)
- down(&tcon->tconSem);
- else
- return -EIO;
- atomic_dec(&tcon->useCount);
- if (atomic_read(&tcon->useCount) > 0) {
- up(&tcon->tconSem);
- return -EBUSY;
- }
+ /* BB: do we need to check this? These should never be NULL. */
+ if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
+ return -EIO;
- /* No need to return error on this operation if tid invalidated and
- closed on server already e.g. due to tcp session crashing */
- if (tcon->tidStatus == CifsNeedReconnect) {
- up(&tcon->tconSem);
+ /*
+ * No need to return error on this operation if tid invalidated and
+ * closed on server already e.g. due to tcp session crashing. Also,
+ * the tcon is no longer on the list, so no need to take lock before
+ * checking this.
+ */
+ if (tcon->need_reconnect)
return 0;
- }
- if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
- up(&tcon->tconSem);
- return -EIO;
- }
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
(void **)&smb_buffer);
- if (rc) {
- up(&tcon->tconSem);
+ if (rc)
return rc;
- }
rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
if (rc)
cFYI(1, ("Tree disconnect failed %d", rc));
- up(&tcon->tconSem);
-
/* No need to return error on this operation if tid invalidated and
- closed on server already e.g. due to tcp session crashing */
+ closed on server already e.g. due to tcp session crashing */
if (rc == -EAGAIN)
rc = 0;
int rc = 0;
cFYI(1, ("In SMBLogoff for session disconnect"));
- if (ses)
- down(&ses->sesSem);
- else
+
+ /*
+ * BB: do we need to check validity of ses and server? They should
+ * always be valid since we have an active reference. If not, that
+ * should probably be a BUG()
+ */
+ if (!ses || !ses->server)
return -EIO;
- atomic_dec(&ses->inUse);
- if (atomic_read(&ses->inUse) > 0) {
- up(&ses->sesSem);
- return -EBUSY;
- }
+ down(&ses->sesSem);
+ if (ses->need_reconnect)
+ goto session_already_dead; /* no need to send SMBlogoff if uid
+ already closed due to reconnect */
rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
if (rc) {
up(&ses->sesSem);
return rc;
}
- if (ses->server) {
- pSMB->hdr.Mid = GetNextMid(ses->server);
+ pSMB->hdr.Mid = GetNextMid(ses->server);
- if (ses->server->secMode &
+ if (ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- }
pSMB->hdr.Uid = ses->Suid;
pSMB->AndXCommand = 0xFF;
rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
- if (ses->server) {
- atomic_dec(&ses->server->socketUseCount);
- if (atomic_read(&ses->server->socketUseCount) == 0) {
- spin_lock(&GlobalMid_Lock);
- ses->server->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- rc = -ESHUTDOWN;
- }
- }
+session_already_dead:
up(&ses->sesSem);
/* if session dead then we do not need to do ulogoff,
return rc;
}
+/* computes length of UCS string converted to host codepage
+ * @src: UCS string
+ * @maxlen: length of the input string in UCS characters
+ * (not in bytes)
+ *
+ * return: size of input string in host codepage
+ */
+static int hostlen_fromUCS(const __le16 *src, const int maxlen,
+ const struct nls_table *nls_codepage) {
+ int i;
+ int hostlen = 0;
+ char to[4];
+ int charlen;
+ for (i = 0; (i < maxlen) && src[i]; ++i) {
+ charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
+ to, NLS_MAX_CHARSET_SIZE);
+ hostlen += charlen > 0 ? charlen : 1;
+ }
+ return hostlen;
+}
+
/* parses DFS refferal V3 structure
* caller is responsible for freeing target_nodes
* returns:
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
unsigned int *num_of_nodes,
struct dfs_info3_param **target_nodes,
- const struct nls_table *nls_codepage)
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName)
{
int i, rc = 0;
char *data_end;
struct dfs_info3_param *node = (*target_nodes)+i;
node->flags = le16_to_cpu(pSMBr->DFSFlags);
- node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+ if (is_unicode) {
+ __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL);
+ cifsConvertToUCS((__le16 *) tmp, searchName,
+ PATH_MAX, nls_codepage, remap);
+ node->path_consumed = hostlen_fromUCS(tmp,
+ le16_to_cpu(pSMBr->PathConsumed)/2,
+ nls_codepage);
+ kfree(tmp);
+ } else
+ node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
+
node->server_type = le16_to_cpu(ref->ServerType);
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
/* parse returned result into more usable form */
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
- target_nodes, nls_codepage);
+ target_nodes, nls_codepage, remap,
+ searchName);
GetDFSRefExit:
cifs_buf_release(pSMB);
cifs_reconnect(struct TCP_Server_Info *server)
{
int rc = 0;
- struct list_head *tmp;
+ struct list_head *tmp, *tmp2;
struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
struct mid_q_entry *mid_entry;
/* before reconnecting the tcp session, mark the smb session (uid)
and the tid bad so they are not used until reconnected */
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if (ses->server) {
- if (ses->server == server) {
- ses->status = CifsNeedReconnect;
- ses->ipc_tid = 0;
- }
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ ses->need_reconnect = true;
+ ses->ipc_tid = 0;
+ list_for_each(tmp2, &ses->tcon_list) {
+ tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
+ tcon->need_reconnect = true;
}
- /* else tcp and smb sessions need reconnection */
- }
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if ((tcon->ses) && (tcon->ses->server == server))
- tcon->tidStatus = CifsNeedReconnect;
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
/* do not want to be sending data on a socket we are freeing */
down(&server->tcpSem);
if (server->ssocket) {
while ((server->tcpStatus != CifsExiting) &&
(server->tcpStatus != CifsGood)) {
try_to_freeze();
- if (server->protocolType == IPV6) {
+ if (server->addr.sockAddr6.sin6_family == AF_INET6) {
rc = ipv6_connect(&server->addr.sockAddr6,
&server->ssocket, server->noautotune);
} else {
msleep(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */
- if (pdu_length < 4)
+ if (pdu_length < 4) {
+ iov.iov_base = (4 - pdu_length) +
+ (char *)smb_buffer;
+ iov.iov_len = pdu_length;
+ smb_msg.msg_control = NULL;
+ smb_msg.msg_controllen = 0;
goto incomplete_rcv;
- else
+ } else
continue;
} else if (length <= 0) {
if (server->tcpStatus == CifsNew) {
}
} /* end while !EXITING */
+ /* take it off the list, if it's not already */
+ write_lock(&cifs_tcp_ses_lock);
+ list_del_init(&server->tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
if (smallbuf) /* no sense logging a debug message if NULL */
cifs_small_buf_release(smallbuf);
- read_lock(&GlobalSMBSeslock);
+ /*
+ * BB: we shouldn't have to do any of this. It shouldn't be
+ * possible to exit from the thread with active SMB sessions
+ */
+ read_lock(&cifs_tcp_ses_lock);
if (list_empty(&server->pending_mid_q)) {
/* loop through server session structures attached to this and
mark them dead */
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses =
- list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server) {
- ses->status = CifsExiting;
- ses->server = NULL;
- }
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo,
+ smb_ses_list);
+ ses->status = CifsExiting;
+ ses->server = NULL;
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
} else {
/* although we can not zero the server struct pointer yet,
since there are active requests which may depnd on them,
mark the corresponding SMB sessions as exiting too */
- list_for_each(tmp, &GlobalSMBSessionList) {
+ list_for_each(tmp, &server->smb_ses_list) {
ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server)
- ses->status = CifsExiting;
+ smb_ses_list);
+ ses->status = CifsExiting;
}
spin_lock(&GlobalMid_Lock);
}
}
spin_unlock(&GlobalMid_Lock);
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
/* 1/8th of sec is more than enough time for them to exit */
msleep(125);
}
if there are any pointing to this (e.g
if a crazy root user tried to kill cifsd
kernel thread explicitly this might happen) */
- write_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo,
- cifsSessionList);
- if (ses->server == server)
- ses->server = NULL;
+ /* BB: This shouldn't be necessary, see above */
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ ses->server = NULL;
}
- write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
kfree(server->hostname);
task_to_wake = xchg(&server->tsk, NULL);
return 0;
}
-static struct cifsSesInfo *
-cifs_find_tcp_session(struct in_addr *target_ip_addr,
- struct in6_addr *target_ip6_addr,
- char *userName, struct TCP_Server_Info **psrvTcp)
+static struct TCP_Server_Info *
+cifs_find_tcp_session(struct sockaddr *addr)
{
struct list_head *tmp;
- struct cifsSesInfo *ses;
-
- *psrvTcp = NULL;
+ struct TCP_Server_Info *server;
+ struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &cifs_tcp_ses_list) {
+ server = list_entry(tmp, struct TCP_Server_Info,
+ tcp_ses_list);
+ /*
+ * the demux thread can exit on its own while still in CifsNew
+ * so don't accept any sockets in that state. Since the
+ * tcpStatus never changes back to CifsNew it's safe to check
+ * for this without a lock.
+ */
+ if (server->tcpStatus == CifsNew)
+ continue;
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalSMBSessionList) {
- ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if (!ses->server)
+ if (addr->sa_family == AF_INET &&
+ (addr4->sin_addr.s_addr !=
+ server->addr.sockAddr.sin_addr.s_addr))
+ continue;
+ else if (addr->sa_family == AF_INET6 &&
+ memcmp(&server->addr.sockAddr6.sin6_addr,
+ &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
continue;
- if (target_ip_addr &&
- ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
- continue;
- else if (target_ip6_addr &&
- memcmp(&ses->server->addr.sockAddr6.sin6_addr,
- target_ip6_addr, sizeof(*target_ip6_addr)))
- continue;
- /* BB lock server and tcp session; increment use count here?? */
+ ++server->srv_count;
+ write_unlock(&cifs_tcp_ses_lock);
+ cFYI(1, ("Existing tcp session with server found"));
+ return server;
+ }
+ write_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
- /* found a match on the TCP session */
- *psrvTcp = ses->server;
+static void
+cifs_put_tcp_session(struct TCP_Server_Info *server)
+{
+ struct task_struct *task;
- /* BB check if reconnection needed */
- if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
- read_unlock(&GlobalSMBSeslock);
- /* Found exact match on both TCP and
- SMB sessions */
- return ses;
- }
- /* else tcp and smb sessions need reconnection */
+ write_lock(&cifs_tcp_ses_lock);
+ if (--server->srv_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
}
- read_unlock(&GlobalSMBSeslock);
- return NULL;
+ list_del_init(&server->tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ spin_lock(&GlobalMid_Lock);
+ server->tcpStatus = CifsExiting;
+ spin_unlock(&GlobalMid_Lock);
+
+ task = xchg(&server->tsk, NULL);
+ if (task)
+ force_sig(SIGKILL, task);
}
-static struct cifsTconInfo *
-find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
+static struct cifsSesInfo *
+cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
{
struct list_head *tmp;
- struct cifsTconInfo *tcon;
- __be32 old_ip;
-
- read_lock(&GlobalSMBSeslock);
+ struct cifsSesInfo *ses;
- list_for_each(tmp, &GlobalTreeConnectionList) {
- cFYI(1, ("Next tcon"));
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if (!tcon->ses || !tcon->ses->server)
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
continue;
- old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr;
- cFYI(1, ("old ip addr: %x == new ip %x ?",
- old_ip, new_target_ip_addr));
+ ++ses->ses_count;
+ write_unlock(&cifs_tcp_ses_lock);
+ return ses;
+ }
+ write_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
- if (old_ip != new_target_ip_addr)
- continue;
+static void
+cifs_put_smb_ses(struct cifsSesInfo *ses)
+{
+ int xid;
+ struct TCP_Server_Info *server = ses->server;
- /* BB lock tcon, server, tcp session and increment use count? */
- /* found a match on the TCP session */
- /* BB check if reconnection needed */
- cFYI(1, ("IP match, old UNC: %s new: %s",
- tcon->treeName, uncName));
+ write_lock(&cifs_tcp_ses_lock);
+ if (--ses->ses_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
- if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE))
- continue;
+ list_del_init(&ses->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
- cFYI(1, ("and old usr: %s new: %s",
- tcon->treeName, uncName));
+ if (ses->status == CifsGood) {
+ xid = GetXid();
+ CIFSSMBLogoff(xid, ses);
+ _FreeXid(xid);
+ }
+ sesInfoFree(ses);
+ cifs_put_tcp_session(server);
+}
- if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE))
+static struct cifsTconInfo *
+cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
+{
+ struct list_head *tmp;
+ struct cifsTconInfo *tcon;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &ses->tcon_list) {
+ tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
+ if (tcon->tidStatus == CifsExiting)
+ continue;
+ if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
continue;
- /* matched smb session (user name) */
- read_unlock(&GlobalSMBSeslock);
+ ++tcon->tc_count;
+ write_unlock(&cifs_tcp_ses_lock);
return tcon;
}
-
- read_unlock(&GlobalSMBSeslock);
+ write_unlock(&cifs_tcp_ses_lock);
return NULL;
}
+static void
+cifs_put_tcon(struct cifsTconInfo *tcon)
+{
+ int xid;
+ struct cifsSesInfo *ses = tcon->ses;
+
+ write_lock(&cifs_tcp_ses_lock);
+ if (--tcon->tc_count > 0) {
+ write_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+
+ list_del_init(&tcon->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ xid = GetXid();
+ CIFSSMBTDis(xid, tcon);
+ _FreeXid(xid);
+
+ DeleteTconOplockQEntries(tcon);
+ tconInfoFree(tcon);
+ cifs_put_smb_ses(ses);
+}
+
int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
}
}
-static void
-kill_cifsd(struct TCP_Server_Info *server)
+static void setup_cifs_sb(struct smb_vol *pvolume_info,
+ struct cifs_sb_info *cifs_sb)
{
- struct task_struct *task;
-
- task = xchg(&server->tsk, NULL);
- if (task)
- force_sig(SIGKILL, task);
+ if (pvolume_info->rsize > CIFSMaxBufSize) {
+ cERROR(1, ("rsize %d too large, using MaxBufSize",
+ pvolume_info->rsize));
+ cifs_sb->rsize = CIFSMaxBufSize;
+ } else if ((pvolume_info->rsize) &&
+ (pvolume_info->rsize <= CIFSMaxBufSize))
+ cifs_sb->rsize = pvolume_info->rsize;
+ else /* default */
+ cifs_sb->rsize = CIFSMaxBufSize;
+
+ if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+ cERROR(1, ("wsize %d too large, using 4096 instead",
+ pvolume_info->wsize));
+ cifs_sb->wsize = 4096;
+ } else if (pvolume_info->wsize)
+ cifs_sb->wsize = pvolume_info->wsize;
+ else
+ cifs_sb->wsize = min_t(const int,
+ PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+ 127*1024);
+ /* old default of CIFSMaxBufSize was too small now
+ that SMB Write2 can send multiple pages in kvec.
+ RFC1001 does not describe what happens when frame
+ bigger than 128K is sent so use that as max in
+ conjunction with 52K kvec constraint on arch with 4K
+ page size */
+
+ if (cifs_sb->rsize < 2048) {
+ cifs_sb->rsize = 2048;
+ /* Windows ME may prefer this */
+ cFYI(1, ("readsize set to minimum: 2048"));
+ }
+ /* calculate prepath */
+ cifs_sb->prepath = pvolume_info->prepath;
+ if (cifs_sb->prepath) {
+ cifs_sb->prepathlen = strlen(cifs_sb->prepath);
+ /* we can not convert the / to \ in the path
+ separators in the prefixpath yet because we do not
+ know (until reset_cifs_unix_caps is called later)
+ whether POSIX PATH CAP is available. We normalize
+ the / to \ after reset_cifs_unix_caps is called */
+ pvolume_info->prepath = NULL;
+ } else
+ cifs_sb->prepathlen = 0;
+ cifs_sb->mnt_uid = pvolume_info->linux_uid;
+ cifs_sb->mnt_gid = pvolume_info->linux_gid;
+ cifs_sb->mnt_file_mode = pvolume_info->file_mode;
+ cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
+ cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
+ cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
+
+ if (pvolume_info->noperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+ if (pvolume_info->setuids)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+ if (pvolume_info->server_ino)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+ if (pvolume_info->remap)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
+ if (pvolume_info->no_xattr)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
+ if (pvolume_info->sfu_emul)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
+ if (pvolume_info->nobrl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+ if (pvolume_info->cifs_acl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
+ if (pvolume_info->override_uid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
+ if (pvolume_info->override_gid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
+ if (pvolume_info->dynperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+ if (pvolume_info->direct_io) {
+ cFYI(1, ("mounting share using direct i/o"));
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+ }
+
+ if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
+ cERROR(1, ("mount option dynperm ignored if cifsacl "
+ "mount option supported"));
}
int
{
int rc = 0;
int xid;
- int address_type = AF_INET;
struct socket *csocket = NULL;
- struct sockaddr_in sin_server;
- struct sockaddr_in6 sin_server6;
+ struct sockaddr addr;
+ struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
+ struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
struct smb_vol volume_info;
struct cifsSesInfo *pSesInfo = NULL;
- struct cifsSesInfo *existingCifsSes = NULL;
struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL;
/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
+ memset(&addr, 0, sizeof(struct sockaddr));
memset(&volume_info, 0, sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
rc = -EINVAL;
if (volume_info.UNCip && volume_info.UNC) {
rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
- &sin_server.sin_addr.s_addr);
+ &sin_server->sin_addr.s_addr);
if (rc <= 0) {
/* not ipv4 address, try ipv6 */
rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
- &sin_server6.sin6_addr.in6_u);
+ &sin_server6->sin6_addr.in6_u);
if (rc > 0)
- address_type = AF_INET6;
+ addr.sa_family = AF_INET6;
} else {
- address_type = AF_INET;
+ addr.sa_family = AF_INET;
}
if (rc <= 0) {
}
}
- if (address_type == AF_INET)
- existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
- NULL /* no ipv6 addr */,
- volume_info.username, &srvTcp);
- else if (address_type == AF_INET6) {
- cFYI(1, ("looking for ipv6 address"));
- existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
- &sin_server6.sin6_addr,
- volume_info.username, &srvTcp);
- } else {
- rc = -EINVAL;
- goto out;
- }
-
- if (srvTcp) {
- cFYI(1, ("Existing tcp session with server found"));
- } else { /* create socket */
- if (volume_info.port)
- sin_server.sin_port = htons(volume_info.port);
- else
- sin_server.sin_port = 0;
- if (address_type == AF_INET6) {
+ srvTcp = cifs_find_tcp_session(&addr);
+ if (!srvTcp) { /* create socket */
+ if (addr.sa_family == AF_INET6) {
cFYI(1, ("attempting ipv6 connect"));
/* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */
- rc = ipv6_connect(&sin_server6, &csocket,
+ sin_server6->sin6_port = htons(volume_info.port);
+ rc = ipv6_connect(sin_server6, &csocket,
volume_info.noblocksnd);
- } else
- rc = ipv4_connect(&sin_server, &csocket,
+ } else {
+ sin_server->sin_port = htons(volume_info.port);
+ rc = ipv4_connect(sin_server, &csocket,
volume_info.source_rfc1001_name,
volume_info.target_rfc1001_name,
volume_info.noblocksnd,
volume_info.noautotune);
+ }
if (rc < 0) {
- cERROR(1, ("Error connecting to IPv4 socket. "
+ cERROR(1, ("Error connecting to socket. "
"Aborting operation"));
if (csocket != NULL)
sock_release(csocket);
} else {
srvTcp->noblocksnd = volume_info.noblocksnd;
srvTcp->noautotune = volume_info.noautotune;
- memcpy(&srvTcp->addr.sockAddr, &sin_server,
- sizeof(struct sockaddr_in));
+ if (addr.sa_family == AF_INET6)
+ memcpy(&srvTcp->addr.sockAddr6, sin_server6,
+ sizeof(struct sockaddr_in6));
+ else
+ memcpy(&srvTcp->addr.sockAddr, sin_server,
+ sizeof(struct sockaddr_in));
atomic_set(&srvTcp->inFlight, 0);
/* BB Add code for ipv6 case too */
srvTcp->ssocket = csocket;
- srvTcp->protocolType = IPV4;
srvTcp->hostname = extract_hostname(volume_info.UNC);
if (IS_ERR(srvTcp->hostname)) {
rc = PTR_ERR(srvTcp->hostname);
memcpy(srvTcp->server_RFC1001_name,
volume_info.target_rfc1001_name, 16);
srvTcp->sequence_number = 0;
+ INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
+ INIT_LIST_HEAD(&srvTcp->smb_ses_list);
+ ++srvTcp->srv_count;
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&srvTcp->tcp_ses_list,
+ &cifs_tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
}
}
- if (existingCifsSes) {
- pSesInfo = existingCifsSes;
+ pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
+ if (pSesInfo) {
cFYI(1, ("Existing smb sess found (status=%d)",
pSesInfo->status));
+ /*
+ * The existing SMB session already has a reference to srvTcp,
+ * so we can put back the extra one we got before
+ */
+ cifs_put_tcp_session(srvTcp);
+
down(&pSesInfo->sesSem);
- if (pSesInfo->status == CifsNeedReconnect) {
+ if (pSesInfo->need_reconnect) {
cFYI(1, ("Session needs reconnect"));
rc = cifs_setup_session(xid, pSesInfo,
cifs_sb->local_nls);
} else if (!rc) {
cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
- if (pSesInfo == NULL)
+ if (pSesInfo == NULL) {
rc = -ENOMEM;
- else {
- pSesInfo->server = srvTcp;
- sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
- NIPQUAD(sin_server.sin_addr.s_addr));
- }
+ goto mount_fail_check;
+ }
+
+ /* new SMB session uses our srvTcp ref */
+ pSesInfo->server = srvTcp;
+ sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
+ NIPQUAD(sin_server->sin_addr.s_addr));
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ /* volume_info.password freed at unmount */
+ if (volume_info.password) {
+ pSesInfo->password = volume_info.password;
+ /* set to NULL to prevent freeing on exit */
+ volume_info.password = NULL;
+ }
+ if (volume_info.username)
+ strncpy(pSesInfo->userName, volume_info.username,
+ MAX_USERNAME_SIZE);
+ if (volume_info.domainname) {
+ int len = strlen(volume_info.domainname);
+ pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
+ if (pSesInfo->domainName)
+ strcpy(pSesInfo->domainName,
+ volume_info.domainname);
+ }
+ pSesInfo->linux_uid = volume_info.linux_uid;
+ pSesInfo->overrideSecFlg = volume_info.secFlg;
+ down(&pSesInfo->sesSem);
- if (!rc) {
- /* volume_info.password freed at unmount */
- if (volume_info.password) {
- pSesInfo->password = volume_info.password;
- /* set to NULL to prevent freeing on exit */
- volume_info.password = NULL;
- }
- if (volume_info.username)
- strncpy(pSesInfo->userName,
- volume_info.username,
- MAX_USERNAME_SIZE);
- if (volume_info.domainname) {
- int len = strlen(volume_info.domainname);
- pSesInfo->domainName =
- kmalloc(len + 1, GFP_KERNEL);
- if (pSesInfo->domainName)
- strcpy(pSesInfo->domainName,
- volume_info.domainname);
- }
- pSesInfo->linux_uid = volume_info.linux_uid;
- pSesInfo->overrideSecFlg = volume_info.secFlg;
- down(&pSesInfo->sesSem);
- /* BB FIXME need to pass vol->secFlgs BB */
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- up(&pSesInfo->sesSem);
- if (!rc)
- atomic_inc(&srvTcp->socketUseCount);
- }
+ /* BB FIXME need to pass vol->secFlgs BB */
+ rc = cifs_setup_session(xid, pSesInfo,
+ cifs_sb->local_nls);
+ up(&pSesInfo->sesSem);
}
/* search for existing tcon to this server share */
if (!rc) {
- if (volume_info.rsize > CIFSMaxBufSize) {
- cERROR(1, ("rsize %d too large, using MaxBufSize",
- volume_info.rsize));
- cifs_sb->rsize = CIFSMaxBufSize;
- } else if ((volume_info.rsize) &&
- (volume_info.rsize <= CIFSMaxBufSize))
- cifs_sb->rsize = volume_info.rsize;
- else /* default */
- cifs_sb->rsize = CIFSMaxBufSize;
-
- if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
- cERROR(1, ("wsize %d too large, using 4096 instead",
- volume_info.wsize));
- cifs_sb->wsize = 4096;
- } else if (volume_info.wsize)
- cifs_sb->wsize = volume_info.wsize;
- else
- cifs_sb->wsize =
- min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
- 127*1024);
- /* old default of CIFSMaxBufSize was too small now
- that SMB Write2 can send multiple pages in kvec.
- RFC1001 does not describe what happens when frame
- bigger than 128K is sent so use that as max in
- conjunction with 52K kvec constraint on arch with 4K
- page size */
-
- if (cifs_sb->rsize < 2048) {
- cifs_sb->rsize = 2048;
- /* Windows ME may prefer this */
- cFYI(1, ("readsize set to minimum: 2048"));
- }
- /* calculate prepath */
- cifs_sb->prepath = volume_info.prepath;
- if (cifs_sb->prepath) {
- cifs_sb->prepathlen = strlen(cifs_sb->prepath);
- /* we can not convert the / to \ in the path
- separators in the prefixpath yet because we do not
- know (until reset_cifs_unix_caps is called later)
- whether POSIX PATH CAP is available. We normalize
- the / to \ after reset_cifs_unix_caps is called */
- volume_info.prepath = NULL;
- } else
- cifs_sb->prepathlen = 0;
- cifs_sb->mnt_uid = volume_info.linux_uid;
- cifs_sb->mnt_gid = volume_info.linux_gid;
- cifs_sb->mnt_file_mode = volume_info.file_mode;
- cifs_sb->mnt_dir_mode = volume_info.dir_mode;
- cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
- cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
-
- if (volume_info.noperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
- if (volume_info.setuids)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
- if (volume_info.server_ino)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
- if (volume_info.remap)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
- if (volume_info.no_xattr)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
- if (volume_info.sfu_emul)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
- if (volume_info.nobrl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
- if (volume_info.cifs_acl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
- if (volume_info.override_uid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
- if (volume_info.override_gid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
- if (volume_info.dynperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
- if (volume_info.direct_io) {
- cFYI(1, ("mounting share using direct i/o"));
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
- }
+ setup_cifs_sb(&volume_info, cifs_sb);
- if ((volume_info.cifs_acl) && (volume_info.dynperm))
- cERROR(1, ("mount option dynperm ignored if cifsacl "
- "mount option supported"));
-
- tcon =
- find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
- volume_info.username);
+ tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
if (tcon) {
cFYI(1, ("Found match on UNC path"));
- /* we can have only one retry value for a connection
- to a share so for resources mounted more than once
- to the same server share the last value passed in
- for the retry flag is used */
- tcon->retry = volume_info.retry;
- tcon->nocase = volume_info.nocase;
- tcon->local_lease = volume_info.local_lease;
+ /* existing tcon already has a reference */
+ cifs_put_smb_ses(pSesInfo);
if (tcon->seal != volume_info.seal)
cERROR(1, ("transport encryption setting "
"conflicts with existing tid"));
} else {
tcon = tconInfoAlloc();
- if (tcon == NULL)
+ if (tcon == NULL) {
rc = -ENOMEM;
- else {
- /* check for null share name ie connecting to
- * dfs root */
-
- /* BB check if this works for exactly length
- * three strings */
- if ((strchr(volume_info.UNC + 3, '\\') == NULL)
- && (strchr(volume_info.UNC + 3, '/') ==
- NULL)) {
-/* rc = connect_to_dfs_path(xid, pSesInfo,
- "", cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);*/
- cFYI(1, ("DFS root not supported"));
- rc = -ENODEV;
- goto out;
- } else {
- /* BB Do we need to wrap sesSem around
- * this TCon call and Unix SetFS as
- * we do on SessSetup and reconnect? */
- rc = CIFSTCon(xid, pSesInfo,
- volume_info.UNC,
- tcon, cifs_sb->local_nls);
- cFYI(1, ("CIFS Tcon rc = %d", rc));
- if (volume_info.nodfs) {
- tcon->Flags &=
- ~SMB_SHARE_IS_IN_DFS;
- cFYI(1, ("DFS disabled (%d)",
- tcon->Flags));
- }
- }
- if (!rc) {
- atomic_inc(&pSesInfo->inUse);
- tcon->retry = volume_info.retry;
- tcon->nocase = volume_info.nocase;
- tcon->seal = volume_info.seal;
+ goto mount_fail_check;
+ }
+ tcon->ses = pSesInfo;
+
+ /* check for null share name ie connect to dfs root */
+ if ((strchr(volume_info.UNC + 3, '\\') == NULL)
+ && (strchr(volume_info.UNC + 3, '/') == NULL)) {
+ /* rc = connect_to_dfs_path(...) */
+ cFYI(1, ("DFS root not supported"));
+ rc = -ENODEV;
+ goto mount_fail_check;
+ } else {
+ /* BB Do we need to wrap sesSem around
+ * this TCon call and Unix SetFS as
+ * we do on SessSetup and reconnect? */
+ rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
+ tcon, cifs_sb->local_nls);
+ cFYI(1, ("CIFS Tcon rc = %d", rc));
+ if (volume_info.nodfs) {
+ tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
+ cFYI(1, ("DFS disabled (%d)",
+ tcon->Flags));
}
}
- }
+ if (rc)
+ goto mount_fail_check;
+ tcon->seal = volume_info.seal;
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+ }
+
+ /* we can have only one retry value for a connection
+ to a share so for resources mounted more than once
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info.retry;
+ tcon->nocase = volume_info.nocase;
+ tcon->local_lease = volume_info.local_lease;
}
if (pSesInfo) {
if (pSesInfo->capabilities & CAP_LARGE_FILES) {
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100;
-/* on error free sesinfo and tcon struct if needed */
+mount_fail_check:
+ /* on error free sesinfo and tcon struct if needed */
if (rc) {
- /* if session setup failed, use count is zero but
- we still need to free cifsd thread */
- if (atomic_read(&srvTcp->socketUseCount) == 0) {
- spin_lock(&GlobalMid_Lock);
- srvTcp->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- kill_cifsd(srvTcp);
- }
- /* If find_unc succeeded then rc == 0 so we can not end */
- if (tcon) /* up accidently freeing someone elses tcon struct */
- tconInfoFree(tcon);
- if (existingCifsSes == NULL) {
- if (pSesInfo) {
- if ((pSesInfo->server) &&
- (pSesInfo->status == CifsGood)) {
- int temp_rc;
- temp_rc = CIFSSMBLogoff(xid, pSesInfo);
- /* if the socketUseCount is now zero */
- if ((temp_rc == -ESHUTDOWN) &&
- (pSesInfo->server))
- kill_cifsd(pSesInfo->server);
- } else {
- cFYI(1, ("No session or bad tcon"));
- if (pSesInfo->server) {
- spin_lock(&GlobalMid_Lock);
- srvTcp->tcpStatus = CifsExiting;
- spin_unlock(&GlobalMid_Lock);
- kill_cifsd(pSesInfo->server);
- }
- }
- sesInfoFree(pSesInfo);
- /* pSesInfo = NULL; */
- }
- }
- } else {
- atomic_inc(&tcon->useCount);
- cifs_sb->tcon = tcon;
- tcon->ses = pSesInfo;
-
- /* do not care if following two calls succeed - informational */
- if (!tcon->ipc) {
- CIFSSMBQFSDeviceInfo(xid, tcon);
- CIFSSMBQFSAttributeInfo(xid, tcon);
- }
-
- /* tell server which Unix caps we support */
- if (tcon->ses->capabilities & CAP_UNIX)
- /* reset of caps checks mount to see if unix extensions
- disabled for just this mount */
- reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+ /* If find_unc succeeded then rc == 0 so we can not end */
+ /* up accidently freeing someone elses tcon struct */
+ if (tcon)
+ cifs_put_tcon(tcon);
+ else if (pSesInfo)
+ cifs_put_smb_ses(pSesInfo);
else
- tcon->unix_ext = 0; /* server does not support them */
+ cifs_put_tcp_session(srvTcp);
+ goto out;
+ }
+ cifs_sb->tcon = tcon;
- /* convert forward to back slashes in prepath here if needed */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
- convert_delimiter(cifs_sb->prepath,
- CIFS_DIR_SEP(cifs_sb));
+ /* do not care if following two calls succeed - informational */
+ if (!tcon->ipc) {
+ CIFSSMBQFSDeviceInfo(xid, tcon);
+ CIFSSMBQFSAttributeInfo(xid, tcon);
+ }
- if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
- cifs_sb->rsize = 1024 * 127;
- cFYI(DBG2,
- ("no very large read support, rsize now 127K"));
- }
- if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
- cifs_sb->wsize = min(cifs_sb->wsize,
- (tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE));
- if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
- cifs_sb->rsize = min(cifs_sb->rsize,
- (tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE));
+ /* tell server which Unix caps we support */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ /* reset of caps checks mount to see if unix extensions
+ disabled for just this mount */
+ reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+ else
+ tcon->unix_ext = 0; /* server does not support them */
+
+ /* convert forward to back slashes in prepath here if needed */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
+ convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
+
+ if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
+ cifs_sb->rsize = 1024 * 127;
+ cFYI(DBG2, ("no very large read support, rsize now 127K"));
}
+ if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
+ cifs_sb->wsize = min(cifs_sb->wsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
+ cifs_sb->rsize = min(cifs_sb->rsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
/* volume_info.password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
tcon->tidStatus = CifsGood;
+ tcon->need_reconnect = false;
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
{
int rc = 0;
- int xid;
- struct cifsSesInfo *ses = NULL;
char *tmp;
- xid = GetXid();
-
- if (cifs_sb->tcon) {
- ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
- rc = CIFSSMBTDis(xid, cifs_sb->tcon);
- if (rc == -EBUSY) {
- FreeXid(xid);
- return 0;
- }
- DeleteTconOplockQEntries(cifs_sb->tcon);
- tconInfoFree(cifs_sb->tcon);
- if ((ses) && (ses->server)) {
- /* save off task so we do not refer to ses later */
- cFYI(1, ("About to do SMBLogoff "));
- rc = CIFSSMBLogoff(xid, ses);
- if (rc == -EBUSY) {
- FreeXid(xid);
- return 0;
- } else if (rc == -ESHUTDOWN) {
- cFYI(1, ("Waking up socket by sending signal"));
- if (ses->server)
- kill_cifsd(ses->server);
- rc = 0;
- } /* else - we have an smb session
- left on this socket do not kill cifsd */
- } else
- cFYI(1, ("No session or bad tcon"));
- }
+ if (cifs_sb->tcon)
+ cifs_put_tcon(cifs_sb->tcon);
cifs_sb->tcon = NULL;
tmp = cifs_sb->prepath;
cifs_sb->prepathlen = 0;
cifs_sb->prepath = NULL;
kfree(tmp);
- if (ses)
- sesInfoFree(ses);
- FreeXid(xid);
return rc;
}
cFYI(1, ("CIFS Session Established successfully"));
spin_lock(&GlobalMid_Lock);
pSesInfo->status = CifsGood;
+ pSesInfo->need_reconnect = false;
spin_unlock(&GlobalMid_Lock);
}
pTcon = cifs_sb->tcon;
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;
-
+ write_lock(&GlobalSMBSeslock);
pSMBFile->closePend = true;
if (pTcon) {
/* no sense reconnecting to close a file that is
already closed */
- if (pTcon->tidStatus != CifsNeedReconnect) {
+ if (!pTcon->need_reconnect) {
+ write_unlock(&GlobalSMBSeslock);
timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout <= 2048)) {
timeout *= 4;
}
if (atomic_read(&pSMBFile->wrtPending))
- cERROR(1,
- ("close with pending writes"));
- rc = CIFSSMBClose(xid, pTcon,
+ cERROR(1, ("close with pending write"));
+ if (!pTcon->need_reconnect &&
+ !pSMBFile->invalidHandle)
+ rc = CIFSSMBClose(xid, pTcon,
pSMBFile->netfid);
- }
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
+ } else
+ write_unlock(&GlobalSMBSeslock);
/* Delete any outstanding lock records.
We'll lose them when the file is closed anyway. */
pTcon = cifs_sb->tcon;
cFYI(1, ("Freeing private data in close dir"));
+ write_lock(&GlobalSMBSeslock);
if (!pCFileStruct->srch_inf.endOfSearch &&
!pCFileStruct->invalidHandle) {
pCFileStruct->invalidHandle = true;
+ write_unlock(&GlobalSMBSeslock);
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
cFYI(1, ("Closing uncompleted readdir with rc %d",
rc));
/* not much we can do if it fails anyway, ignore rc */
rc = 0;
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
if (ptmp) {
cFYI(1, ("closedir free smb buf in srch struct"));
if ((wbc->nr_to_write -= n_iov) <= 0)
done = 1;
index = next;
- }
+ } else
+ /* Need to re-find the pages we skipped */
+ index = pvec.pages[0]->index + 1;
+
pagevec_release(&pvec);
}
if (!scanned && !done) {
ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
if (ret_buf) {
- write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
ret_buf->status = CifsNew;
- list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
+ ++ret_buf->ses_count;
+ INIT_LIST_HEAD(&ret_buf->smb_ses_list);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
init_MUTEX(&ret_buf->sesSem);
- write_unlock(&GlobalSMBSeslock);
}
return ret_buf;
}
return;
}
- write_lock(&GlobalSMBSeslock);
atomic_dec(&sesInfoAllocCount);
- list_del(&buf_to_free->cifsSessionList);
- write_unlock(&GlobalSMBSeslock);
kfree(buf_to_free->serverOS);
kfree(buf_to_free->serverDomain);
kfree(buf_to_free->serverNOS);
struct cifsTconInfo *ret_buf;
ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
if (ret_buf) {
- write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
- list_add(&ret_buf->cifsConnectionList,
- &GlobalTreeConnectionList);
ret_buf->tidStatus = CifsNew;
+ ++ret_buf->tc_count;
INIT_LIST_HEAD(&ret_buf->openFileList);
- init_MUTEX(&ret_buf->tconSem);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
#ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock);
#endif
- write_unlock(&GlobalSMBSeslock);
}
return ret_buf;
}
cFYI(1, ("Null buffer passed to tconInfoFree"));
return;
}
- write_lock(&GlobalSMBSeslock);
atomic_dec(&tconInfoAllocCount);
- list_del(&buf_to_free->cifsConnectionList);
- write_unlock(&GlobalSMBSeslock);
kfree(buf_to_free->nativeFileSystem);
kfree(buf_to_free);
}
if (current->fsuid != treeCon->ses->linux_uid) {
cFYI(1, ("Multiuser mode and UID "
"did not match tcon uid"));
- read_lock(&GlobalSMBSeslock);
- list_for_each(temp_item, &GlobalSMBSessionList) {
- ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
+ ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
if (ses->linux_uid == current->fsuid) {
if (ses->server == treeCon->ses->server) {
cFYI(1, ("found matching uid substitute right smb_uid"));
}
}
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
}
}
}
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
{
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
- struct list_head *tmp;
- struct list_head *tmp1;
+ struct list_head *tmp, *tmp1, *tmp2;
+ struct cifsSesInfo *ses;
struct cifsTconInfo *tcon;
+ struct cifsInodeInfo *pCifsInode;
struct cifsFileInfo *netfile;
cFYI(1, ("Checking for oplock break or dnotify response"));
return false;
/* look up tcon based on tid & uid */
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &GlobalTreeConnectionList) {
- tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
+ read_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &srv->smb_ses_list) {
+ ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+ list_for_each(tmp1, &ses->tcon_list) {
+ tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list);
+ if (tcon->tid != buf->Tid)
+ continue;
+
cifs_stats_inc(&tcon->num_oplock_brks);
- list_for_each(tmp1, &tcon->openFileList) {
- netfile = list_entry(tmp1, struct cifsFileInfo,
+ write_lock(&GlobalSMBSeslock);
+ list_for_each(tmp2, &tcon->openFileList) {
+ netfile = list_entry(tmp2, struct cifsFileInfo,
tlist);
- if (pSMB->Fid == netfile->netfid) {
- struct cifsInodeInfo *pCifsInode;
- read_unlock(&GlobalSMBSeslock);
- cFYI(1,
- ("file id match, oplock break"));
- pCifsInode =
- CIFS_I(netfile->pInode);
- pCifsInode->clientCanCacheAll = false;
- if (pSMB->OplockLevel == 0)
- pCifsInode->clientCanCacheRead
- = false;
- pCifsInode->oplockPending = true;
- AllocOplockQEntry(netfile->pInode,
- netfile->netfid,
- tcon);
- cFYI(1,
- ("about to wake up oplock thread"));
- if (oplockThread)
- wake_up_process(oplockThread);
- return true;
- }
+ if (pSMB->Fid != netfile->netfid)
+ continue;
+
+ write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
+ cFYI(1, ("file id match, oplock break"));
+ pCifsInode = CIFS_I(netfile->pInode);
+ pCifsInode->clientCanCacheAll = false;
+ if (pSMB->OplockLevel == 0)
+ pCifsInode->clientCanCacheRead = false;
+ pCifsInode->oplockPending = true;
+ AllocOplockQEntry(netfile->pInode,
+ netfile->netfid, tcon);
+ cFYI(1, ("about to wake up oplock thread"));
+ if (oplockThread)
+ wake_up_process(oplockThread);
+
+ return true;
}
- read_unlock(&GlobalSMBSeslock);
+ write_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
cFYI(1, ("No matching file for oplock break"));
return true;
}
}
- read_unlock(&GlobalSMBSeslock);
+ read_unlock(&cifs_tcp_ses_lock);
cFYI(1, ("Can not process oplock break for non-existent connection"));
return true;
}
(index_to_find < first_entry_in_buffer)) {
/* close and restart search */
cFYI(1, ("search backing up - close and restart search"));
+ write_lock(&GlobalSMBSeslock);
if (!cifsFile->srch_inf.endOfSearch &&
!cifsFile->invalidHandle) {
cifsFile->invalidHandle = true;
+ write_unlock(&GlobalSMBSeslock);
CIFSFindClose(xid, pTcon, cifsFile->netfid);
- }
+ } else
+ write_unlock(&GlobalSMBSeslock);
if (cifsFile->srch_inf.ntwrk_buf_start) {
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
if (cifsFile->srch_inf.smallBuf)
error = release_lockspace(ls, force);
if (!error)
ls_count--;
- else if (!ls_count)
+ if (!ls_count)
threads_stop();
mutex_unlock(&ls_lock);
decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat)
{
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex;
struct blkcipher_desc desc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
};
int rc = 0;
- sg_init_table(&dst_sg, 1);
- sg_init_table(&src_sg, 1);
-
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(
KERN_DEBUG, "Session key encryption key (size [%d]):\n",
}
rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.encrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]. "
auth_tok->session_key.encrypted_key_size;
rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.decrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]\n", rc);
rc = -EINVAL;
goto out;
}
- rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg,
auth_tok->session_key.encrypted_key_size);
mutex_unlock(tfm_mutex);
if (unlikely(rc)) {
size_t i;
size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex = NULL;
u8 cipher_code;
size_t packet_size_length;
ecryptfs_dump_hex(session_key_encryption_key, 16);
}
rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat session key; expected rc = 1; "
"got rc = [%d]. key_rec->enc_key_size = [%d]\n",
goto out;
}
rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat encrypted session key; "
"expected rc = 1; got rc = [%d]. "
rc = 0;
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n",
crypt_stat->key_size);
- rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg,
(*key_rec).enc_key_size);
mutex_unlock(tfm_mutex);
if (rc) {
extern int do_mknod(const char *file, int mode, unsigned int major,
unsigned int minor);
extern int link_file(const char *from, const char *to);
-extern int do_readlink(char *file, char *buf, int size);
+extern int hostfs_do_readlink(char *file, char *buf, int size);
extern int rename_file(char *from, char *to);
extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
long long *bfree_out, long long *bavail_out,
if (name == NULL)
goto out;
- n = do_readlink(link, name, len);
+ n = hostfs_do_readlink(link, name, len);
if (n < len)
break;
len *= 2;
name = inode_name(page->mapping->host, 0);
if (name == NULL)
return -ENOMEM;
- err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
+ err = hostfs_do_readlink(name, buffer, PAGE_CACHE_SIZE);
kfree(name);
if (err == PAGE_CACHE_SIZE)
err = -E2BIG;
return 0;
}
-int do_readlink(char *file, char *buf, int size)
+int hostfs_do_readlink(char *file, char *buf, int size)
{
int n;
}
EXPORT_SYMBOL_GPL(get_inotify_watch);
+int pin_inotify_watch(struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ spin_lock(&sb_lock);
+ if (sb->s_count >= S_BIAS) {
+ atomic_inc(&sb->s_active);
+ spin_unlock(&sb_lock);
+ atomic_inc(&watch->count);
+ return 1;
+ }
+ spin_unlock(&sb_lock);
+ return 0;
+}
+
/**
* put_inotify_watch - decrements the ref count on a given watch. cleans up
* watch references if the count reaches zero. inotify_watch is freed by
}
EXPORT_SYMBOL_GPL(put_inotify_watch);
+void unpin_inotify_watch(struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ put_inotify_watch(watch);
+ deactivate_super(sb);
+}
+
/*
* inotify_handle_get_wd - returns the next WD for use by the given handle
*
}
EXPORT_SYMBOL_GPL(inotify_init_watch);
+/*
+ * Watch removals suck violently. To kick the watch out we need (in this
+ * order) inode->inotify_mutex and ih->mutex. That's fine if we have
+ * a hold on inode; however, for all other cases we need to make damn sure
+ * we don't race with umount. We can *NOT* just grab a reference to a
+ * watch - inotify_unmount_inodes() will happily sail past it and we'll end
+ * with reference to inode potentially outliving its superblock. Ideally
+ * we just want to grab an active reference to superblock if we can; that
+ * will make sure we won't go into inotify_umount_inodes() until we are
+ * done. Cleanup is just deactivate_super(). However, that leaves a messy
+ * case - what if we *are* racing with umount() and active references to
+ * superblock can't be acquired anymore? We can bump ->s_count, grab
+ * ->s_umount, which will almost certainly wait until the superblock is shut
+ * down and the watch in question is pining for fjords. That's fine, but
+ * there is a problem - we might have hit the window between ->s_active
+ * getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock
+ * is past the point of no return and is heading for shutdown) and the
+ * moment when deactivate_super() acquires ->s_umount. We could just do
+ * drop_super() yield() and retry, but that's rather antisocial and this
+ * stuff is luser-triggerable. OTOH, having grabbed ->s_umount and having
+ * found that we'd got there first (i.e. that ->s_root is non-NULL) we know
+ * that we won't race with inotify_umount_inodes(). So we could grab a
+ * reference to watch and do the rest as above, just with drop_super() instead
+ * of deactivate_super(), right? Wrong. We had to drop ih->mutex before we
+ * could grab ->s_umount. So the watch could've been gone already.
+ *
+ * That still can be dealt with - we need to save watch->wd, do idr_find()
+ * and compare its result with our pointer. If they match, we either have
+ * the damn thing still alive or we'd lost not one but two races at once,
+ * the watch had been killed and a new one got created with the same ->wd
+ * at the same address. That couldn't have happened in inotify_destroy(),
+ * but inotify_rm_wd() could run into that. Still, "new one got created"
+ * is not a problem - we have every right to kill it or leave it alone,
+ * whatever's more convenient.
+ *
+ * So we can use idr_find(...) == watch && watch->inode->i_sb == sb as
+ * "grab it and kill it" check. If it's been our original watch, we are
+ * fine, if it's a newcomer - nevermind, just pretend that we'd won the
+ * race and kill the fscker anyway; we are safe since we know that its
+ * superblock won't be going away.
+ *
+ * And yes, this is far beyond mere "not very pretty"; so's the entire
+ * concept of inotify to start with.
+ */
+
+/**
+ * pin_to_kill - pin the watch down for removal
+ * @ih: inotify handle
+ * @watch: watch to kill
+ *
+ * Called with ih->mutex held, drops it. Possible return values:
+ * 0 - nothing to do, it has died
+ * 1 - remove it, drop the reference and deactivate_super()
+ * 2 - remove it, drop the reference and drop_super(); we tried hard to avoid
+ * that variant, since it involved a lot of PITA, but that's the best that
+ * could've been done.
+ */
+static int pin_to_kill(struct inotify_handle *ih, struct inotify_watch *watch)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ s32 wd = watch->wd;
+
+ spin_lock(&sb_lock);
+ if (sb->s_count >= S_BIAS) {
+ atomic_inc(&sb->s_active);
+ spin_unlock(&sb_lock);
+ get_inotify_watch(watch);
+ mutex_unlock(&ih->mutex);
+ return 1; /* the best outcome */
+ }
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */
+ down_read(&sb->s_umount);
+ if (likely(!sb->s_root)) {
+ /* fs is already shut down; the watch is dead */
+ drop_super(sb);
+ return 0;
+ }
+ /* raced with the final deactivate_super() */
+ mutex_lock(&ih->mutex);
+ if (idr_find(&ih->idr, wd) != watch || watch->inode->i_sb != sb) {
+ /* the watch is dead */
+ mutex_unlock(&ih->mutex);
+ drop_super(sb);
+ return 0;
+ }
+ /* still alive or freed and reused with the same sb and wd; kill */
+ get_inotify_watch(watch);
+ mutex_unlock(&ih->mutex);
+ return 2;
+}
+
+static void unpin_and_kill(struct inotify_watch *watch, int how)
+{
+ struct super_block *sb = watch->inode->i_sb;
+ put_inotify_watch(watch);
+ switch (how) {
+ case 1:
+ deactivate_super(sb);
+ break;
+ case 2:
+ drop_super(sb);
+ }
+}
+
/**
* inotify_destroy - clean up and destroy an inotify instance
* @ih: inotify handle
* pretty. We cannot do a simple iteration over the list, because we
* do not know the inode until we iterate to the watch. But we need to
* hold inode->inotify_mutex before ih->mutex. The following works.
+ *
+ * AV: it had to become even uglier to start working ;-/
*/
while (1) {
struct inotify_watch *watch;
struct list_head *watches;
+ struct super_block *sb;
struct inode *inode;
+ int how;
mutex_lock(&ih->mutex);
watches = &ih->watches;
break;
}
watch = list_first_entry(watches, struct inotify_watch, h_list);
- get_inotify_watch(watch);
- mutex_unlock(&ih->mutex);
+ sb = watch->inode->i_sb;
+ how = pin_to_kill(ih, watch);
+ if (!how)
+ continue;
inode = watch->inode;
mutex_lock(&inode->inotify_mutex);
mutex_unlock(&ih->mutex);
mutex_unlock(&inode->inotify_mutex);
- put_inotify_watch(watch);
+ unpin_and_kill(watch, how);
}
/* free this handle: the put matching the get in inotify_init() */
int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
{
struct inotify_watch *watch;
+ struct super_block *sb;
struct inode *inode;
+ int how;
mutex_lock(&ih->mutex);
watch = idr_find(&ih->idr, wd);
mutex_unlock(&ih->mutex);
return -EINVAL;
}
- get_inotify_watch(watch);
+ sb = watch->inode->i_sb;
+ how = pin_to_kill(ih, watch);
+ if (!how)
+ return 0;
+
inode = watch->inode;
- mutex_unlock(&ih->mutex);
mutex_lock(&inode->inotify_mutex);
mutex_lock(&ih->mutex);
mutex_unlock(&ih->mutex);
mutex_unlock(&inode->inotify_mutex);
- put_inotify_watch(watch);
+ unpin_and_kill(watch, how);
return 0;
}
if (IS_APPEND(dir))
return -EPERM;
if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
- IS_IMMUTABLE(victim->d_inode))
+ IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
return -EPERM;
if (isdir) {
if (!S_ISDIR(victim->d_inode->i_mode))
static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
whole_disk_show, NULL);
-int add_partition(struct gendisk *disk, int partno,
- sector_t start, sector_t len, int flags)
+struct hd_struct *add_partition(struct gendisk *disk, int partno,
+ sector_t start, sector_t len, int flags)
{
struct hd_struct *p;
dev_t devt = MKDEV(0, 0);
err = disk_expand_part_tbl(disk, partno);
if (err)
- return err;
+ return ERR_PTR(err);
ptbl = disk->part_tbl;
if (ptbl->part[partno])
- return -EBUSY;
+ return ERR_PTR(-EBUSY);
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
- return -ENOMEM;
+ return ERR_PTR(-EBUSY);
if (!init_part_stats(p)) {
err = -ENOMEM;
err = blk_alloc_devt(p, &devt);
if (err)
- goto out_free;
+ goto out_free_stats;
pdev->devt = devt;
/* delay uevent until 'holders' subdir is created */
if (!ddev->uevent_suppress)
kobject_uevent(&pdev->kobj, KOBJ_ADD);
- return 0;
+ return p;
+out_free_stats:
+ free_part_stats(p);
out_free:
kfree(p);
- return err;
+ return ERR_PTR(err);
out_del:
kobject_put(p->holder_dir);
device_del(pdev);
out_put:
put_device(pdev);
blk_free_devt(devt);
- return err;
+ return ERR_PTR(err);
}
/* Not exported, helper to add_disk(). */
disk->disk_name, p, (unsigned long long) size);
size = get_capacity(disk) - from;
}
- res = add_partition(disk, p, from, size, state->parts[p].flags);
- if (res) {
- printk(KERN_ERR " %s: p%d could not be added: %d\n",
- disk->disk_name, p, -res);
+ part = add_partition(disk, p, from, size,
+ state->parts[p].flags);
+ if (IS_ERR(part)) {
+ printk(KERN_ERR " %s: p%d could not be added: %ld\n",
+ disk->disk_name, p, -PTR_ERR(part));
continue;
}
#ifdef CONFIG_BLK_DEV_MD
if (state->parts[p].flags & ADDPART_FLAG_RAID)
- md_autodetect_dev(bdev->bd_dev+p);
+ md_autodetect_dev(part_to_dev(part)->devt);
#endif
}
kfree(state);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
inode->i_mode = table->mode;
+ inode->i_uid = inode->i_gid = 0;
if (!table->child) {
inode->i_mode |= S_IFREG;
inode->i_op = &proc_sys_inode_operations;
+++ /dev/null
-/*
- * Copyright © 2008 Ingo Molnar
- *
- * This program 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.
- *
- * 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.
- *
- * 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.
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <asm/cacheflush.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-
-void *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
-
-void
-iounmap_atomic(void *kvaddr, enum km_type type);
return current->flags & PF_SPREAD_SLAB;
}
-extern void cpuset_track_online_nodes(void);
-
extern int current_cpuset_is_being_rebound(void);
extern void rebuild_sched_domains(void);
return 0;
}
-static inline void cpuset_track_online_nodes(void) {}
-
static inline int current_cpuset_is_being_rebound(void)
{
return 0;
({ \
int __ret = 0; \
\
- if (unlikely(c)) { \
+ if (!oops_in_progress && unlikely(c)) { \
if (debug_locks_off() && !debug_locks_silent) \
WARN_ON(1); \
__ret = 1; \
} both;
};
+#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
+
#ifdef CONFIG_FUTEX
extern void exit_robust_list(struct task_struct *curr);
extern void exit_pi_state_list(struct task_struct *curr);
extern int disk_expand_part_tbl(struct gendisk *disk, int target);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int);
+extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
+ int partno, sector_t start,
+ sector_t len, int flags);
extern void delete_partition(struct gendisk *, int);
extern void printk_all_partitions(void);
struct inotify_watch *);
extern void get_inotify_watch(struct inotify_watch *);
extern void put_inotify_watch(struct inotify_watch *);
+extern int pin_inotify_watch(struct inotify_watch *);
+extern void unpin_inotify_watch(struct inotify_watch *);
#else
{
}
+extern inline int pin_inotify_watch(struct inotify_watch *watch)
+{
+ return 0;
+}
+
+extern inline void unpin_inotify_watch(struct inotify_watch *watch)
+{
+}
+
#endif /* CONFIG_INOTIFY */
#endif /* __KERNEL __ */
#define KEY_KPEQUAL 117
#define KEY_KPPLUSMINUS 118
#define KEY_PAUSE 119
+#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */
#define KEY_KPCOMMA 121
#define KEY_HANGEUL 122
#define KEY_PAUSECD 201
#define KEY_PROG3 202
#define KEY_PROG4 203
+#define KEY_DASHBOARD 204 /* AL Dashboard */
#define KEY_SUSPEND 205
#define KEY_CLOSE 206 /* AC Close */
#define KEY_PLAY 207
(__x < 0) ? -__x : __x; \
})
+#ifdef CONFIG_PROVE_LOCKING
+void might_fault(void);
+#else
+static inline void might_fault(void)
+{
+ might_sleep();
+}
+#endif
+
extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
extern int core_kernel_text(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
+extern int func_ptr_is_kernel_text(void *ptr);
+
struct pid;
extern struct pid *session_of_pgrp(struct pid *pgrp);
return buf;
}
-#define pr_emerg(fmt, arg...) \
- printk(KERN_EMERG fmt, ##arg)
-#define pr_alert(fmt, arg...) \
- printk(KERN_ALERT fmt, ##arg)
-#define pr_crit(fmt, arg...) \
- printk(KERN_CRIT fmt, ##arg)
-#define pr_err(fmt, arg...) \
- printk(KERN_ERR fmt, ##arg)
-#define pr_warning(fmt, arg...) \
- printk(KERN_WARNING fmt, ##arg)
-#define pr_notice(fmt, arg...) \
- printk(KERN_NOTICE fmt, ##arg)
-#define pr_info(fmt, arg...) \
- printk(KERN_INFO fmt, ##arg)
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define pr_emerg(fmt, ...) \
+ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert(fmt, ...) \
+ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit(fmt, ...) \
+ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...) \
+ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning(fmt, ...) \
+ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_notice(fmt, ...) \
+ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) \
+ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
#define pr_debug(fmt, ...) do { \
- dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+ dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
-#define pr_debug(fmt, arg...) \
- printk(KERN_DEBUG fmt, ##arg)
+#define pr_debug(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
-#define pr_debug(fmt, arg...) \
- ({ if (0) printk(KERN_DEBUG fmt, ##arg); 0; })
+#define pr_debug(fmt, ...) \
+ ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
#endif
/*
struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
};
+#define LOCKSTAT_POINTS 4
+
/*
* The lock-class itself:
*/
int name_version;
#ifdef CONFIG_LOCK_STAT
- unsigned long contention_point[4];
+ unsigned long contention_point[LOCKSTAT_POINTS];
+ unsigned long contending_point[LOCKSTAT_POINTS];
#endif
};
struct lock_class_stats {
unsigned long contention_point[4];
+ unsigned long contending_point[4];
struct lock_time read_waittime;
struct lock_time write_waittime;
struct lock_time read_holdtime;
const char *name;
#ifdef CONFIG_LOCK_STAT
int cpu;
+ unsigned long ip;
#endif
};
# define lock_set_subclass(l, s, i) do { } while (0)
# define lockdep_init() do { } while (0)
# define lockdep_info() do { } while (0)
-# define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0)
+# define lockdep_init_map(lock, name, key, sub) \
+ do { (void)(name); (void)(key); } while (0)
# define lockdep_set_class(lock, key) do { (void)(key); } while (0)
# define lockdep_set_class_and_name(lock, key, name) \
- do { (void)(key); } while (0)
+ do { (void)(key); (void)(name); } while (0)
#define lockdep_set_class_and_subclass(lock, key, sub) \
do { (void)(key); } while (0)
#define lockdep_set_subclass(lock, sub) do { } while (0)
#ifdef CONFIG_LOCK_STAT
extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
-extern void lock_acquired(struct lockdep_map *lock);
+extern void lock_acquired(struct lockdep_map *lock, unsigned long ip);
#define LOCK_CONTENDED(_lock, try, lock) \
do { \
lock_contended(&(_lock)->dep_map, _RET_IP_); \
lock(_lock); \
} \
- lock_acquired(&(_lock)->dep_map); \
+ lock_acquired(&(_lock)->dep_map, _RET_IP_); \
} while (0)
#else /* CONFIG_LOCK_STAT */
#define lock_contended(lockdep_map, ip) do {} while (0)
-#define lock_acquired(lockdep_map) do {} while (0)
+#define lock_acquired(lockdep_map, ip) do {} while (0)
#define LOCK_CONTENDED(_lock, try, lock) \
lock(_lock)
# define lock_map_release(l) do { } while (0)
#endif
+#ifdef CONFIG_PROVE_LOCKING
+# define might_lock(lock) \
+do { \
+ typecheck(struct lockdep_map *, &(lock)->dep_map); \
+ lock_acquire(&(lock)->dep_map, 0, 0, 0, 2, NULL, _THIS_IP_); \
+ lock_release(&(lock)->dep_map, 0, _THIS_IP_); \
+} while (0)
+# define might_lock_read(lock) \
+do { \
+ typecheck(struct lockdep_map *, &(lock)->dep_map); \
+ lock_acquire(&(lock)->dep_map, 0, 0, 1, 2, NULL, _THIS_IP_); \
+ lock_release(&(lock)->dep_map, 0, _THIS_IP_); \
+} while (0)
+#else
+# define might_lock(lock) do { } while (0)
+# define might_lock_read(lock) do { } while (0)
+#endif
+
#endif /* __LINUX_LOCKDEP_H */
/*
* NOTE: mutex_trylock() follows the spin_trylock() convention,
* not the down_trylock() convention!
+ *
+ * Returns 1 if the mutex has been acquired successfully, and 0 on contention.
*/
extern int mutex_trylock(struct mutex *lock);
extern void mutex_unlock(struct mutex *lock);
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
-#define SYS_PACCEPT 18 /* sys_paccept(2) */
+#define SYS_ACCEPT4 18 /* sys_accept4(2) */
typedef enum {
SS_FREE = 0, /* not allocated */
* remaining bits are used as flags. */
#define SOCK_TYPE_MASK 0xf
-/* Flags for socket, socketpair, paccept */
+/* Flags for socket, socketpair, accept4 */
#define SOCK_CLOEXEC O_CLOEXEC
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK O_NONBLOCK
extern struct socket *sockfd_lookup(int fd, int *err);
#define sockfd_put(sock) fput(sock->file)
extern int net_ratelimit(void);
-extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen, int flags);
#define net_random() random32()
#define net_srandom(seed) srandom32((__force u32)seed)
#include <linux/seqlock.h>
#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-#define RCU_SECONDS_TILL_STALL_CHECK ( 3 * HZ) /* for rcp->jiffies_stall */
+#define RCU_SECONDS_TILL_STALL_CHECK (10 * HZ) /* for rcp->jiffies_stall */
#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ) /* for rcp->jiffies_stall */
#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
u64 ring_buffer_time_stamp(int cpu);
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
+void tracing_on(void);
+void tracing_off(void);
+
enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0,
};
#define PORT_SC26XX 82
+/* SH-SCI */
+#define PORT_SCIFA 83
+
#ifdef __KERNEL__
#include <linux/compiler.h>
#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */
+/*
+ * SLAB_DESTROY_BY_RCU - **WARNING** READ THIS!
+ *
+ * This delays freeing the SLAB page by a grace period, it does _NOT_
+ * delay object freeing. This means that if you do kmem_cache_free()
+ * that memory location is free to be reused at any time. Thus it may
+ * be possible to see another object there in the same RCU grace period.
+ *
+ * This feature only ensures the memory location backing the object
+ * stays valid, the trick to using this is relying on an independent
+ * object validation pass. Something like:
+ *
+ * rcu_read_lock()
+ * again:
+ * obj = lockless_lookup(key);
+ * if (obj) {
+ * if (!try_get_ref(obj)) // might fail for free objects
+ * goto again;
+ *
+ * if (obj->key != key) { // not the object we expected
+ * put_ref(obj);
+ * goto again;
+ * }
+ * }
+ * rcu_read_unlock();
+ *
+ * See also the comment on struct slab_rcu in mm/slab.c.
+ */
#define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
asmlinkage long sys_bind(int, struct sockaddr __user *, int);
asmlinkage long sys_connect(int, struct sockaddr __user *, int);
asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);
-asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *,
- const __user sigset_t *, size_t, int);
+asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int);
asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_send(int, void __user *, size_t, unsigned);
\
set_fs(KERNEL_DS); \
pagefault_disable(); \
- ret = __get_user(retval, (__force typeof(retval) __user *)(addr)); \
+ ret = __copy_from_user_inatomic(&(retval), (__force typeof(retval) __user *)(addr), sizeof(retval)); \
pagefault_enable(); \
set_fs(old_fs); \
ret; \
* (in probe()), bound to a driver, or unbinding (in disconnect())
* @is_active: flag set when the interface is bound and not suspended.
* @sysfs_files_created: sysfs attributes exist
+ * @unregistering: flag set when the interface is being unregistered
* @needs_remote_wakeup: flag set when the driver requires remote-wakeup
* capability during autosuspend.
* @needs_altsetting0: flag set when a set-interface request for altsetting 0
enum usb_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
+ unsigned unregistering:1; /* unregistration is in progress */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
* not do so then mac80211 may add this under certain circumstances.
*/
-/**
- * enum ieee80211_notification_type - Low level driver notification
- * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence
- */
-enum ieee80211_notification_types {
- IEEE80211_NOTIFY_RE_ASSOC,
-};
-
/**
* struct ieee80211_ht_bss_info - describing BSS's HT characteristics
*
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
u16 tid);
-/**
- * ieee80211_notify_mac - low level driver notification
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @notif_type: enum ieee80211_notification_types
- *
- * This function must be called by low level driver to inform mac80211 of
- * low level driver status change or force mac80211 to re-assoc for low
- * level driver internal error that require re-assoc.
- */
-void ieee80211_notify_mac(struct ieee80211_hw *hw,
- enum ieee80211_notification_types notif_type);
-
/**
* ieee80211_find_sta - find a station
*
*/
#define sock_lock_init_class_and_name(sk, sname, skey, name, key) \
do { \
- sk->sk_lock.owned = 0; \
+ sk->sk_lock.owned = 0; \
init_waitqueue_head(&sk->sk_lock.wq); \
spin_lock_init(&(sk)->sk_lock.slock); \
debug_check_no_locks_freed((void *)&(sk)->sk_lock, \
help
The regular slab allocator that is established and known to work
well in all environments. It organizes cache hot objects in
- per cpu and per node queues. SLAB is the default choice for
- a slab allocator.
+ per cpu and per node queues.
config SLUB
bool "SLUB (Unqueued Allocator)"
instead of managing queues of cached objects (SLAB approach).
Per cpu caching is realized using slabs of objects instead
of queues of objects. SLUB can use memory efficiently
- and has enhanced diagnostics.
+ and has enhanced diagnostics. SLUB is the default choice for
+ a slab allocator.
config SLOB
depends on EMBEDDED
if (ids->in_use >= size)
return -ENOSPC;
+ spin_lock_init(&new->lock);
+ new->deleted = 0;
+ rcu_read_lock();
+ spin_lock(&new->lock);
+
err = idr_get_new(&ids->ipcs_idr, new, &id);
- if (err)
+ if (err) {
+ spin_unlock(&new->lock);
+ rcu_read_unlock();
return err;
+ }
ids->in_use++;
ids->seq = 0;
new->id = ipc_buildid(id, new->seq);
- spin_lock_init(&new->lock);
- new->deleted = 0;
- rcu_read_lock();
- spin_lock(&new->lock);
return id;
}
hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
notifier.o ksysfs.o pm_qos_params.o sched_clock.o
-CFLAGS_REMOVE_sched.o = -mno-spe
-
ifdef CONFIG_FUNCTION_TRACER
# Do not trace debug files and internal ftrace files
CFLAGS_REMOVE_lockdep.o = -pg
CFLAGS_REMOVE_rtmutex-debug.o = -pg
CFLAGS_REMOVE_cgroup-debug.o = -pg
CFLAGS_REMOVE_sched_clock.o = -pg
-CFLAGS_REMOVE_sched.o = -mno-spe -pg
+CFLAGS_REMOVE_sched.o = -pg
endif
obj-$(CONFIG_FREEZER) += freezer.o
struct list_head trees; /* with root here */
int dead;
int count;
+ atomic_long_t refs;
struct rcu_head head;
struct node {
struct list_head list;
* tree is refcounted; one reference for "some rules on rules_list refer to
* it", one for each chunk with pointer to it.
*
- * chunk is refcounted by embedded inotify_watch.
+ * chunk is refcounted by embedded inotify_watch + .refs (non-zero refcount
+ * of watch contributes 1 to .refs).
*
* node.index allows to get from node.list to containing chunk.
* MSB of that sucker is stolen to mark taggings that we might have to
INIT_LIST_HEAD(&chunk->hash);
INIT_LIST_HEAD(&chunk->trees);
chunk->count = count;
+ atomic_long_set(&chunk->refs, 1);
for (i = 0; i < count; i++) {
INIT_LIST_HEAD(&chunk->owners[i].list);
chunk->owners[i].index = i;
return chunk;
}
-static void __free_chunk(struct rcu_head *rcu)
+static void free_chunk(struct audit_chunk *chunk)
{
- struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
int i;
for (i = 0; i < chunk->count; i++) {
kfree(chunk);
}
-static inline void free_chunk(struct audit_chunk *chunk)
+void audit_put_chunk(struct audit_chunk *chunk)
{
- call_rcu(&chunk->head, __free_chunk);
+ if (atomic_long_dec_and_test(&chunk->refs))
+ free_chunk(chunk);
}
-void audit_put_chunk(struct audit_chunk *chunk)
+static void __put_chunk(struct rcu_head *rcu)
{
- put_inotify_watch(&chunk->watch);
+ struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
+ audit_put_chunk(chunk);
}
enum {HASH_SIZE = 128};
list_for_each_entry_rcu(p, list, hash) {
if (p->watch.inode == inode) {
- get_inotify_watch(&p->watch);
+ atomic_long_inc(&p->refs);
return p;
}
}
/* tagging and untagging inodes with trees */
-static void untag_chunk(struct audit_chunk *chunk, struct node *p)
+static struct audit_chunk *find_chunk(struct node *p)
+{
+ int index = p->index & ~(1U<<31);
+ p -= index;
+ return container_of(p, struct audit_chunk, owners[0]);
+}
+
+static void untag_chunk(struct node *p)
{
+ struct audit_chunk *chunk = find_chunk(p);
struct audit_chunk *new;
struct audit_tree *owner;
int size = chunk->count - 1;
int i, j;
+ if (!pin_inotify_watch(&chunk->watch)) {
+ /*
+ * Filesystem is shutting down; all watches are getting
+ * evicted, just take it off the node list for this
+ * tree and let the eviction logics take care of the
+ * rest.
+ */
+ owner = p->owner;
+ if (owner->root == chunk) {
+ list_del_init(&owner->same_root);
+ owner->root = NULL;
+ }
+ list_del_init(&p->list);
+ p->owner = NULL;
+ put_tree(owner);
+ return;
+ }
+
+ spin_unlock(&hash_lock);
+
+ /*
+ * pin_inotify_watch() succeeded, so the watch won't go away
+ * from under us.
+ */
mutex_lock(&chunk->watch.inode->inotify_mutex);
if (chunk->dead) {
mutex_unlock(&chunk->watch.inode->inotify_mutex);
- return;
+ goto out;
}
owner = p->owner;
inotify_evict_watch(&chunk->watch);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
put_inotify_watch(&chunk->watch);
- return;
+ goto out;
}
new = alloc_chunk(size);
inotify_evict_watch(&chunk->watch);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
put_inotify_watch(&chunk->watch);
- return;
+ goto out;
Fallback:
// do the best we can
put_tree(owner);
spin_unlock(&hash_lock);
mutex_unlock(&chunk->watch.inode->inotify_mutex);
+out:
+ unpin_inotify_watch(&chunk->watch);
+ spin_lock(&hash_lock);
}
static int create_chunk(struct inode *inode, struct audit_tree *tree)
return 0;
}
-static struct audit_chunk *find_chunk(struct node *p)
-{
- int index = p->index & ~(1U<<31);
- p -= index;
- return container_of(p, struct audit_chunk, owners[0]);
-}
-
static void kill_rules(struct audit_tree *tree)
{
struct audit_krule *rule, *next;
spin_lock(&hash_lock);
while (!list_empty(&victim->chunks)) {
struct node *p;
- struct audit_chunk *chunk;
p = list_entry(victim->chunks.next, struct node, list);
- chunk = find_chunk(p);
- get_inotify_watch(&chunk->watch);
- spin_unlock(&hash_lock);
-
- untag_chunk(chunk, p);
- put_inotify_watch(&chunk->watch);
- spin_lock(&hash_lock);
+ untag_chunk(p);
}
spin_unlock(&hash_lock);
put_tree(victim);
while (!list_empty(&tree->chunks)) {
struct node *node;
- struct audit_chunk *chunk;
node = list_entry(tree->chunks.next, struct node, list);
if (!(node->index & (1U<<31)))
break;
- chunk = find_chunk(node);
- get_inotify_watch(&chunk->watch);
- spin_unlock(&hash_lock);
-
- untag_chunk(chunk, node);
-
- put_inotify_watch(&chunk->watch);
- spin_lock(&hash_lock);
+ untag_chunk(node);
}
if (!tree->root && !tree->goner) {
tree->goner = 1;
static void destroy_watch(struct inotify_watch *watch)
{
struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
- free_chunk(chunk);
+ call_rcu(&chunk->head, __put_chunk);
}
static const struct inotify_operations rtree_inotify_ops = {
list_for_each_entry_safe(p, n, in_list, ilist) {
list_del(&p->ilist);
inotify_rm_watch(audit_ih, &p->wdata);
- /* the put matching the get in audit_do_del_rule() */
- put_inotify_watch(&p->wdata);
+ /* the unpin matching the pin in audit_do_del_rule() */
+ unpin_inotify_watch(&p->wdata);
}
}
/* Put parent on the inotify un-registration
* list. Grab a reference before releasing
* audit_filter_mutex, to be released in
- * audit_inotify_unregister(). */
- list_add(&parent->ilist, &inotify_list);
- get_inotify_watch(&parent->wdata);
+ * audit_inotify_unregister().
+ * If filesystem is going away, just leave
+ * the sucker alone, eviction will take
+ * care of it.
+ */
+ if (pin_inotify_watch(&parent->wdata))
+ list_add(&parent->ilist, &inotify_list);
}
}
}
struct cgroup *cgrp;
struct cgroup_iter it;
struct task_struct *tsk;
+
/*
- * Validate dentry by checking the superblock operations
+ * Validate dentry by checking the superblock operations,
+ * and make sure it's a directory.
*/
- if (dentry->d_sb->s_op != &cgroup_ops)
+ if (dentry->d_sb->s_op != &cgroup_ops ||
+ !S_ISDIR(dentry->d_inode->i_mode))
goto err;
ret = 0;
mutex_unlock(&cgroup_mutex);
return -EBUSY;
}
-
- parent = cgrp->parent;
- root = cgrp->root;
- sb = root->sb;
+ mutex_unlock(&cgroup_mutex);
/*
* Call pre_destroy handlers of subsys. Notify subsystems
*/
cgroup_call_pre_destroy(cgrp);
- if (cgroup_has_css_refs(cgrp)) {
+ mutex_lock(&cgroup_mutex);
+ parent = cgrp->parent;
+ root = cgrp->root;
+ sb = root->sb;
+
+ if (atomic_read(&cgrp->count)
+ || !list_empty(&cgrp->children)
+ || cgroup_has_css_refs(cgrp)) {
mutex_unlock(&cgroup_mutex);
return -EBUSY;
}
#include <linux/list.h>
#include <linux/mempolicy.h>
#include <linux/mm.h>
+#include <linux/memory.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/namei.h>
int ndoms; /* number of sched domains in result */
int nslot; /* next empty doms[] cpumask_t slot */
- ndoms = 0;
doms = NULL;
dattr = NULL;
csa = NULL;
* Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
*/
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
- if (!doms) {
- ndoms = 0;
+ if (!doms)
goto done;
- }
/*
* The rest of the code, including the scheduler, can deal with
done:
kfree(csa);
+ /*
+ * Fallback to the default domain if kmalloc() failed.
+ * See comments in partition_sched_domains().
+ */
+ if (doms == NULL)
+ ndoms = 1;
+
*domains = doms;
*attributes = dattr;
return ndoms;
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
* See also the previous routine cpuset_track_online_cpus().
*/
-void cpuset_track_online_nodes(void)
+static int cpuset_track_online_nodes(struct notifier_block *self,
+ unsigned long action, void *arg)
{
cgroup_lock();
- top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
- scan_for_empty_cpusets(&top_cpuset);
+ switch (action) {
+ case MEM_ONLINE:
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+ break;
+ case MEM_OFFLINE:
+ top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+ scan_for_empty_cpusets(&top_cpuset);
+ break;
+ default:
+ break;
+ }
cgroup_unlock();
+ return NOTIFY_OK;
}
#endif
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
hotcpu_notifier(cpuset_track_online_cpus, 0);
+ hotplug_memory_notifier(cpuset_track_online_nodes, 10);
}
/**
#include <linux/cn_proc.h>
#include <linux/mutex.h>
#include <linux/futex.h>
-#include <linux/compat.h>
#include <linux/pipe_fs_i.h>
#include <linux/audit.h> /* for audit_free() */
#include <linux/resource.h>
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
-#ifdef CONFIG_FUTEX
- if (unlikely(tsk->robust_list))
- exit_robust_list(tsk);
-#ifdef CONFIG_COMPAT
- if (unlikely(tsk->compat_robust_list))
- compat_exit_robust_list(tsk);
-#endif
-#endif
if (group_dead)
tty_audit_exit();
if (unlikely(tsk->audit_context))
return 1;
return module_text_address(addr) != NULL;
}
+
+/*
+ * On some architectures (PPC64, IA64) function pointers
+ * are actually only tokens to some data that then holds the
+ * real function address. As a result, to find if a function
+ * pointer is part of the kernel text, we need to do some
+ * special dereferencing first.
+ */
+int func_ptr_is_kernel_text(void *ptr)
+{
+ unsigned long addr;
+ addr = (unsigned long) dereference_function_descriptor(ptr);
+ if (core_kernel_text(addr))
+ return 1;
+ return module_text_address(addr) != NULL;
+}
#include <linux/jiffies.h>
#include <linux/tracehook.h>
#include <linux/futex.h>
+#include <linux/compat.h>
#include <linux/task_io_accounting_ops.h>
#include <linux/rcupdate.h>
#include <linux/ptrace.h>
{
struct completion *vfork_done = tsk->vfork_done;
+ /* Get rid of any futexes when releasing the mm */
+#ifdef CONFIG_FUTEX
+ if (unlikely(tsk->robust_list))
+ exit_robust_list(tsk);
+#ifdef CONFIG_COMPAT
+ if (unlikely(tsk->compat_robust_list))
+ compat_exit_robust_list(tsk);
+#endif
+#endif
+
/* Get rid of any cached register state */
deactivate_mm(tsk, mm);
static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
-/*
- * Take mm->mmap_sem, when futex is shared
- */
-static inline void futex_lock_mm(struct rw_semaphore *fshared)
-{
- if (fshared)
- down_read(fshared);
-}
-
-/*
- * Release mm->mmap_sem, when the futex is shared
- */
-static inline void futex_unlock_mm(struct rw_semaphore *fshared)
-{
- if (fshared)
- up_read(fshared);
-}
-
/*
* We hash on the keys returned from get_futex_key (see below).
*/
&& key1->both.offset == key2->both.offset);
}
+/*
+ * Take a reference to the resource addressed by a key.
+ * Can be called while holding spinlocks.
+ *
+ */
+static void get_futex_key_refs(union futex_key *key)
+{
+ if (!key->both.ptr)
+ return;
+
+ switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+ case FUT_OFF_INODE:
+ atomic_inc(&key->shared.inode->i_count);
+ break;
+ case FUT_OFF_MMSHARED:
+ atomic_inc(&key->private.mm->mm_count);
+ break;
+ }
+}
+
+/*
+ * Drop a reference to the resource addressed by a key.
+ * The hash bucket spinlock must not be held.
+ */
+static void drop_futex_key_refs(union futex_key *key)
+{
+ if (!key->both.ptr)
+ return;
+
+ switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+ case FUT_OFF_INODE:
+ iput(key->shared.inode);
+ break;
+ case FUT_OFF_MMSHARED:
+ mmdrop(key->private.mm);
+ break;
+ }
+}
+
/**
* get_futex_key - Get parameters which are the keys for a futex.
* @uaddr: virtual address of the futex
* For other futexes, it points to ¤t->mm->mmap_sem and
* caller must have taken the reader lock. but NOT any spinlocks.
*/
-static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
- union futex_key *key)
+static int get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
{
unsigned long address = (unsigned long)uaddr;
struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
struct page *page;
int err;
return -EFAULT;
key->private.mm = mm;
key->private.address = address;
+ get_futex_key_refs(key);
return 0;
}
- /*
- * The futex is hashed differently depending on whether
- * it's in a shared or private mapping. So check vma first.
- */
- vma = find_extend_vma(mm, address);
- if (unlikely(!vma))
- return -EFAULT;
- /*
- * Permissions.
- */
- if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ))
- return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES;
+again:
+ err = get_user_pages_fast(address, 1, 0, &page);
+ if (err < 0)
+ return err;
+
+ lock_page(page);
+ if (!page->mapping) {
+ unlock_page(page);
+ put_page(page);
+ goto again;
+ }
/*
* Private mappings are handled in a simple way.
*
* NOTE: When userspace waits on a MAP_SHARED mapping, even if
* it's a read-only handle, it's expected that futexes attach to
- * the object not the particular process. Therefore we use
- * VM_MAYSHARE here, not VM_SHARED which is restricted to shared
- * mappings of _writable_ handles.
+ * the object not the particular process.
*/
- if (likely(!(vma->vm_flags & VM_MAYSHARE))) {
- key->both.offset |= FUT_OFF_MMSHARED; /* reference taken on mm */
+ if (PageAnon(page)) {
+ key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
key->private.mm = mm;
key->private.address = address;
- return 0;
+ } else {
+ key->both.offset |= FUT_OFF_INODE; /* inode-based key */
+ key->shared.inode = page->mapping->host;
+ key->shared.pgoff = page->index;
}
- /*
- * Linear file mappings are also simple.
- */
- key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
- key->both.offset |= FUT_OFF_INODE; /* inode-based key. */
- if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
- key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
- + vma->vm_pgoff);
- return 0;
- }
+ get_futex_key_refs(key);
- /*
- * We could walk the page table to read the non-linear
- * pte, and get the page index without fetching the page
- * from swap. But that's a lot of code to duplicate here
- * for a rare case, so we simply fetch the page.
- */
- err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL);
- if (err >= 0) {
- key->shared.pgoff =
- page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
- put_page(page);
- return 0;
- }
- return err;
-}
-
-/*
- * Take a reference to the resource addressed by a key.
- * Can be called while holding spinlocks.
- *
- */
-static void get_futex_key_refs(union futex_key *key)
-{
- if (key->both.ptr == NULL)
- return;
- switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
- case FUT_OFF_INODE:
- atomic_inc(&key->shared.inode->i_count);
- break;
- case FUT_OFF_MMSHARED:
- atomic_inc(&key->private.mm->mm_count);
- break;
- }
+ unlock_page(page);
+ put_page(page);
+ return 0;
}
-/*
- * Drop a reference to the resource addressed by a key.
- * The hash bucket spinlock must not be held.
- */
-static void drop_futex_key_refs(union futex_key *key)
+static inline
+void put_futex_key(int fshared, union futex_key *key)
{
- if (!key->both.ptr)
- return;
- switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
- case FUT_OFF_INODE:
- iput(key->shared.inode);
- break;
- case FUT_OFF_MMSHARED:
- mmdrop(key->private.mm);
- break;
- }
+ drop_futex_key_refs(key);
}
static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
/*
* Fault handling.
- * if fshared is non NULL, current->mm->mmap_sem is already held
*/
-static int futex_handle_fault(unsigned long address,
- struct rw_semaphore *fshared, int attempt)
+static int futex_handle_fault(unsigned long address, int attempt)
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
if (attempt > 2)
return ret;
- if (!fshared)
- down_read(&mm->mmap_sem);
+ down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
if (vma && address >= vma->vm_start &&
(vma->vm_flags & VM_WRITE)) {
current->min_flt++;
}
}
- if (!fshared)
- up_read(&mm->mmap_sem);
+ up_read(&mm->mmap_sem);
return ret;
}
/* pi_mutex gets initialized later */
pi_state->owner = NULL;
atomic_set(&pi_state->refcount, 1);
+ pi_state->key = FUTEX_KEY_INIT;
current->pi_state_cache = pi_state;
struct list_head *next, *head = &curr->pi_state_list;
struct futex_pi_state *pi_state;
struct futex_hash_bucket *hb;
- union futex_key key;
+ union futex_key key = FUTEX_KEY_INIT;
if (!futex_cmpxchg_enabled)
return;
* Wake up all waiters hashed on the physical page that is mapped
* to this virtual address:
*/
-static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
- int nr_wake, u32 bitset)
+static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
{
struct futex_hash_bucket *hb;
struct futex_q *this, *next;
struct plist_head *head;
- union futex_key key;
+ union futex_key key = FUTEX_KEY_INIT;
int ret;
if (!bitset)
return -EINVAL;
- futex_lock_mm(fshared);
-
ret = get_futex_key(uaddr, fshared, &key);
if (unlikely(ret != 0))
goto out;
spin_unlock(&hb->lock);
out:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &key);
return ret;
}
* to this virtual address:
*/
static int
-futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared,
- u32 __user *uaddr2,
+futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
int nr_wake, int nr_wake2, int op)
{
- union futex_key key1, key2;
+ union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
struct futex_hash_bucket *hb1, *hb2;
struct plist_head *head;
struct futex_q *this, *next;
int ret, op_ret, attempt = 0;
retryfull:
- futex_lock_mm(fshared);
-
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
goto out;
*/
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr2,
- fshared, attempt);
+ attempt);
if (ret)
goto out;
goto retry;
}
- /*
- * If we would have faulted, release mmap_sem,
- * fault it in and start all over again.
- */
- futex_unlock_mm(fshared);
-
ret = get_user(dummy, uaddr2);
if (ret)
return ret;
if (hb1 != hb2)
spin_unlock(&hb2->lock);
out:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &key2);
+ put_futex_key(fshared, &key1);
return ret;
}
* Requeue all waiters hashed on one physical page to another
* physical page.
*/
-static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
- u32 __user *uaddr2,
+static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
int nr_wake, int nr_requeue, u32 *cmpval)
{
- union futex_key key1, key2;
+ union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
struct futex_hash_bucket *hb1, *hb2;
struct plist_head *head1;
struct futex_q *this, *next;
int ret, drop_count = 0;
retry:
- futex_lock_mm(fshared);
-
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
goto out;
if (hb1 != hb2)
spin_unlock(&hb2->lock);
- /*
- * If we would have faulted, release mmap_sem, fault
- * it in and start all over again.
- */
- futex_unlock_mm(fshared);
-
ret = get_user(curval, uaddr1);
if (!ret)
drop_futex_key_refs(&key1);
out:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &key2);
+ put_futex_key(fshared, &key1);
return ret;
}
* private futexes.
*/
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
- struct task_struct *newowner,
- struct rw_semaphore *fshared)
+ struct task_struct *newowner, int fshared)
{
u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
struct futex_pi_state *pi_state = q->pi_state;
handle_fault:
spin_unlock(q->lock_ptr);
- ret = futex_handle_fault((unsigned long)uaddr, fshared, attempt++);
+ ret = futex_handle_fault((unsigned long)uaddr, attempt++);
spin_lock(q->lock_ptr);
static long futex_wait_restart(struct restart_block *restart);
-static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
+static int futex_wait(u32 __user *uaddr, int fshared,
u32 val, ktime_t *abs_time, u32 bitset)
{
struct task_struct *curr = current;
q.pi_state = NULL;
q.bitset = bitset;
retry:
- futex_lock_mm(fshared);
-
+ q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
goto out_release_sem;
if (unlikely(ret)) {
queue_unlock(&q, hb);
- /*
- * If we would have faulted, release mmap_sem, fault it in and
- * start all over again.
- */
- futex_unlock_mm(fshared);
-
ret = get_user(uval, uaddr);
if (!ret)
/* Only actually queue if *uaddr contained val. */
queue_me(&q, hb);
- /*
- * Now the futex is queued and we have checked the data, we
- * don't want to hold mmap_sem while we sleep.
- */
- futex_unlock_mm(fshared);
-
/*
* There might have been scheduling since the queue_me(), as we
* cannot hold a spinlock across the get_user() in case it
queue_unlock(&q, hb);
out_release_sem:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &q.key);
return ret;
}
static long futex_wait_restart(struct restart_block *restart)
{
u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
- struct rw_semaphore *fshared = NULL;
+ int fshared = 0;
ktime_t t;
t.tv64 = restart->futex.time;
restart->fn = do_no_restart_syscall;
if (restart->futex.flags & FLAGS_SHARED)
- fshared = ¤t->mm->mmap_sem;
+ fshared = 1;
return (long)futex_wait(uaddr, fshared, restart->futex.val, &t,
restart->futex.bitset);
}
* if there are waiters then it will block, it does PI, etc. (Due to
* races the kernel might see a 0 value of the futex too.)
*/
-static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+static int futex_lock_pi(u32 __user *uaddr, int fshared,
int detect, ktime_t *time, int trylock)
{
struct hrtimer_sleeper timeout, *to = NULL;
q.pi_state = NULL;
retry:
- futex_lock_mm(fshared);
-
+ q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
goto out_release_sem;
* exit to complete.
*/
queue_unlock(&q, hb);
- futex_unlock_mm(fshared);
cond_resched();
goto retry;
*/
queue_me(&q, hb);
- /*
- * Now the futex is queued and we have checked the data, we
- * don't want to hold mmap_sem while we sleep.
- */
- futex_unlock_mm(fshared);
-
WARN_ON(!q.pi_state);
/*
* Block on the PI mutex:
ret = ret ? 0 : -EWOULDBLOCK;
}
- futex_lock_mm(fshared);
spin_lock(q.lock_ptr);
if (!ret) {
/* Unqueue and drop the lock */
unqueue_me_pi(&q);
- futex_unlock_mm(fshared);
if (to)
destroy_hrtimer_on_stack(&to->timer);
queue_unlock(&q, hb);
out_release_sem:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &q.key);
if (to)
destroy_hrtimer_on_stack(&to->timer);
return ret;
queue_unlock(&q, hb);
if (attempt++) {
- ret = futex_handle_fault((unsigned long)uaddr, fshared,
- attempt);
+ ret = futex_handle_fault((unsigned long)uaddr, attempt);
if (ret)
goto out_release_sem;
goto retry_unlocked;
}
- futex_unlock_mm(fshared);
-
ret = get_user(uval, uaddr);
if (!ret && (uval != -EFAULT))
goto retry;
* This is the in-kernel slowpath: we look up the PI state (if any),
* and do the rt-mutex unlock.
*/
-static int futex_unlock_pi(u32 __user *uaddr, struct rw_semaphore *fshared)
+static int futex_unlock_pi(u32 __user *uaddr, int fshared)
{
struct futex_hash_bucket *hb;
struct futex_q *this, *next;
u32 uval;
struct plist_head *head;
- union futex_key key;
+ union futex_key key = FUTEX_KEY_INIT;
int ret, attempt = 0;
retry:
*/
if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
return -EPERM;
- /*
- * First take all the futex related locks:
- */
- futex_lock_mm(fshared);
ret = get_futex_key(uaddr, fshared, &key);
if (unlikely(ret != 0))
out_unlock:
spin_unlock(&hb->lock);
out:
- futex_unlock_mm(fshared);
+ put_futex_key(fshared, &key);
return ret;
spin_unlock(&hb->lock);
if (attempt++) {
- ret = futex_handle_fault((unsigned long)uaddr, fshared,
- attempt);
+ ret = futex_handle_fault((unsigned long)uaddr, attempt);
if (ret)
goto out;
uval = 0;
goto retry_unlocked;
}
- futex_unlock_mm(fshared);
-
ret = get_user(uval, uaddr);
if (!ret && (uval != -EFAULT))
goto retry;
* PI futexes happens in exit_pi_state():
*/
if (!pi && (uval & FUTEX_WAITERS))
- futex_wake(uaddr, &curr->mm->mmap_sem, 1,
- FUTEX_BITSET_MATCH_ANY);
+ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
}
return 0;
}
{
int ret = -ENOSYS;
int cmd = op & FUTEX_CMD_MASK;
- struct rw_semaphore *fshared = NULL;
+ int fshared = 0;
if (!(op & FUTEX_PRIVATE_FLAG))
- fshared = ¤t->mm->mmap_sem;
+ fshared = 1;
switch (cmd) {
case FUTEX_WAIT:
char *modname;
const char *name;
unsigned long offset, size;
- char namebuf[KSYM_NAME_LEN];
+ int len;
- name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
+ name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
if (!name)
return sprintf(buffer, "0x%lx", address);
+ if (name != buffer)
+ strcpy(buffer, name);
+ len = strlen(buffer);
+ buffer += len;
+
if (modname)
- return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
- size, modname);
+ len += sprintf(buffer, "+%#lx/%#lx [%s]",
+ offset, size, modname);
else
- return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
+ len += sprintf(buffer, "+%#lx/%#lx", offset, size);
+
+ return len;
}
/* Look up a kernel symbol and print it to the kernel messages. */
#ifdef CONFIG_LOCK_STAT
static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats);
-static int lock_contention_point(struct lock_class *class, unsigned long ip)
+static int lock_point(unsigned long points[], unsigned long ip)
{
int i;
- for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) {
- if (class->contention_point[i] == 0) {
- class->contention_point[i] = ip;
+ for (i = 0; i < LOCKSTAT_POINTS; i++) {
+ if (points[i] == 0) {
+ points[i] = ip;
break;
}
- if (class->contention_point[i] == ip)
+ if (points[i] == ip)
break;
}
for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++)
stats.contention_point[i] += pcs->contention_point[i];
+ for (i = 0; i < ARRAY_SIZE(stats.contending_point); i++)
+ stats.contending_point[i] += pcs->contending_point[i];
+
lock_time_add(&pcs->read_waittime, &stats.read_waittime);
lock_time_add(&pcs->write_waittime, &stats.write_waittime);
memset(cpu_stats, 0, sizeof(struct lock_class_stats));
}
memset(class->contention_point, 0, sizeof(class->contention_point));
+ memset(class->contending_point, 0, sizeof(class->contending_point));
}
static struct lock_class_stats *get_lock_stats(struct lock_class *class)
struct held_lock *hlock, *prev_hlock;
struct lock_class_stats *stats;
unsigned int depth;
- int i, point;
+ int i, contention_point, contending_point;
depth = curr->lockdep_depth;
if (DEBUG_LOCKS_WARN_ON(!depth))
found_it:
hlock->waittime_stamp = sched_clock();
- point = lock_contention_point(hlock_class(hlock), ip);
+ contention_point = lock_point(hlock_class(hlock)->contention_point, ip);
+ contending_point = lock_point(hlock_class(hlock)->contending_point,
+ lock->ip);
stats = get_lock_stats(hlock_class(hlock));
- if (point < ARRAY_SIZE(stats->contention_point))
- stats->contention_point[point]++;
+ if (contention_point < LOCKSTAT_POINTS)
+ stats->contention_point[contention_point]++;
+ if (contending_point < LOCKSTAT_POINTS)
+ stats->contending_point[contending_point]++;
if (lock->cpu != smp_processor_id())
stats->bounces[bounce_contended + !!hlock->read]++;
put_lock_stats(stats);
}
static void
-__lock_acquired(struct lockdep_map *lock)
+__lock_acquired(struct lockdep_map *lock, unsigned long ip)
{
struct task_struct *curr = current;
struct held_lock *hlock, *prev_hlock;
put_lock_stats(stats);
lock->cpu = cpu;
+ lock->ip = ip;
}
void lock_contended(struct lockdep_map *lock, unsigned long ip)
}
EXPORT_SYMBOL_GPL(lock_contended);
-void lock_acquired(struct lockdep_map *lock)
+void lock_acquired(struct lockdep_map *lock, unsigned long ip)
{
unsigned long flags;
raw_local_irq_save(flags);
check_flags(flags);
current->lockdep_recursion = 1;
- __lock_acquired(lock);
+ __lock_acquired(lock, ip);
current->lockdep_recursion = 0;
raw_local_irq_restore(flags);
}
{
printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
- printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
+ printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
printk("... MAX_LOCK_DEPTH: %lu\n", MAX_LOCK_DEPTH);
printk("... MAX_LOCKDEP_KEYS: %lu\n", MAX_LOCKDEP_KEYS);
- printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
+ printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
printk("... MAX_LOCKDEP_ENTRIES: %lu\n", MAX_LOCKDEP_ENTRIES);
printk("... MAX_LOCKDEP_CHAINS: %lu\n", MAX_LOCKDEP_CHAINS);
printk("... CHAINHASH_SIZE: %lu\n", CHAINHASH_SIZE);
static void snprint_time(char *buf, size_t bufsiz, s64 nr)
{
- unsigned long rem;
+ s64 div;
+ s32 rem;
nr += 5; /* for display rounding */
- rem = do_div(nr, 1000); /* XXX: do_div_signed */
- snprintf(buf, bufsiz, "%lld.%02d", (long long)nr, (int)rem/10);
+ div = div_s64_rem(nr, 1000, &rem);
+ snprintf(buf, bufsiz, "%lld.%02d", (long long)div, (int)rem/10);
}
static void seq_time(struct seq_file *m, s64 time)
if (stats->read_holdtime.nr)
namelen += 2;
- for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) {
+ for (i = 0; i < LOCKSTAT_POINTS; i++) {
char sym[KSYM_SYMBOL_LEN];
char ip[32];
stats->contention_point[i],
ip, sym);
}
+ for (i = 0; i < LOCKSTAT_POINTS; i++) {
+ char sym[KSYM_SYMBOL_LEN];
+ char ip[32];
+
+ if (class->contending_point[i] == 0)
+ break;
+
+ if (!i)
+ seq_line(m, '-', 40-namelen, namelen);
+
+ sprint_symbol(sym, class->contending_point[i]);
+ snprintf(ip, sizeof(ip), "[<%p>]",
+ (void *)class->contending_point[i]);
+ seq_printf(m, "%40s %14lu %29s %s\n", name,
+ stats->contending_point[i],
+ ip, sym);
+ }
if (i) {
seq_puts(m, "\n");
seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1));
static void seq_header(struct seq_file *m)
{
- seq_printf(m, "lock_stat version 0.2\n");
+ seq_printf(m, "lock_stat version 0.3\n");
seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1));
seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s "
"%14s %14s\n",
* We also put the fastpath first in the kernel image, to make sure the
* branch is predicted by the CPU as default-untaken.
*/
-static void noinline __sched
+static __used noinline void __sched
__mutex_lock_slowpath(atomic_t *lock_count);
/***
EXPORT_SYMBOL(mutex_lock);
#endif
-static noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
+static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
/***
* mutex_unlock - release the mutex
}
done:
- lock_acquired(&lock->dep_map);
+ lock_acquired(&lock->dep_map, ip);
/* got the lock - rejoice! */
mutex_remove_waiter(lock, &waiter, task_thread_info(task));
debug_mutex_set_owner(lock, task_thread_info(task));
/*
* Release the lock, slowpath:
*/
-static noinline void
+static __used noinline void
__mutex_unlock_slowpath(atomic_t *lock_count)
{
__mutex_unlock_common_slowpath(lock_count, 1);
}
EXPORT_SYMBOL(mutex_lock_killable);
-static noinline void __sched
+static __used noinline void __sched
__mutex_lock_slowpath(atomic_t *lock_count)
{
struct mutex *lock = container_of(lock_count, struct mutex, count);
while (nb && nr_to_call) {
next_nb = rcu_dereference(nb->next);
+
+#ifdef CONFIG_DEBUG_NOTIFIERS
+ if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
+ WARN(1, "Invalid notifier called!");
+ nb = next_nb;
+ continue;
+ }
+#endif
ret = nb->notifier_call(nb, val, v);
if (nr_calls)
* has some performance issues. The stack dump of a WARN_ON
* is more likely to get the right attention than a printk...
*/
- WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000));
+ WARN(msec > (TEST_SUSPEND_SECONDS * 1000), "Component: %s\n", label);
}
#else
};
#ifdef CONFIG_SMP
-static void __init profile_nop(void *unused)
+static inline void profile_nop(void *unused)
{
}
/* OK, time to rat on our buddy... */
- printk(KERN_ERR "RCU detected CPU stalls:");
+ printk(KERN_ERR "INFO: RCU detected CPU stalls:");
for_each_possible_cpu(cpu) {
if (cpu_isset(cpu, rcp->cpumask))
printk(" %d", cpu);
{
unsigned long flags;
- printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu jiffies)\n",
+ printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu/%lu jiffies)\n",
smp_processor_id(), jiffies,
jiffies - rcp->gp_start);
dump_stack();
}
mutex_lock(&relay_channels_mutex);
- for_each_online_cpu(i)
+ for_each_possible_cpu(i)
if (chan->buf[i])
__relay_reset(chan->buf[i], 0);
mutex_unlock(&relay_channels_mutex);
return chan;
free_bufs:
- for_each_online_cpu(i) {
- if (!chan->buf[i])
- break;
- relay_close_buf(chan->buf[i]);
+ for_each_possible_cpu(i) {
+ if (chan->buf[i])
+ relay_close_buf(chan->buf[i]);
}
kref_put(&chan->kref, relay_destroy_channel);
/*
* Underflow?
*/
- if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
+ if (DEBUG_LOCKS_WARN_ON(val > preempt_count() - (!!kernel_locked())))
return;
/*
* Is the spinlock portion underflowing?
*
* The passed in 'doms_new' should be kmalloc'd. This routine takes
* ownership of it and will kfree it when done with it. If the caller
- * failed the kmalloc call, then it can pass in doms_new == NULL,
- * and partition_sched_domains() will fallback to the single partition
- * 'fallback_doms', it also forces the domains to be rebuilt.
+ * failed the kmalloc call, then it can pass in doms_new == NULL &&
+ * ndoms_new == 1, and partition_sched_domains() will fallback to
+ * the single partition 'fallback_doms', it also forces the domains
+ * to be rebuilt.
*
- * If doms_new==NULL it will be replaced with cpu_online_map.
- * ndoms_new==0 is a special case for destroying existing domains.
- * It will not create the default domain.
+ * If doms_new == NULL it will be replaced with cpu_online_map.
+ * ndoms_new == 0 is a special case for destroying existing domains,
+ * and it will not create the default domain.
*
* Call with hotplug lock held
*/
/*
* Zero means infinite timeout - no checking done:
*/
-unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120;
+unsigned long __read_mostly sysctl_hung_task_timeout_secs = 480;
unsigned long __read_mostly sysctl_hung_task_warnings = 10;
int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
{
struct work_struct *sm_work;
- int i;
+ int i, ret;
/* Set up initial state. */
mutex_lock(&lock);
/* This will release the thread on our CPU. */
put_cpu();
flush_workqueue(stop_machine_wq);
+ ret = active.fnret;
mutex_unlock(&lock);
- return active.fnret;
+ return ret;
}
int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
cond_syscall(sys_bind);
cond_syscall(sys_listen);
cond_syscall(sys_accept);
-cond_syscall(sys_paccept);
+cond_syscall(sys_accept4);
cond_syscall(sys_connect);
cond_syscall(sys_getsockname);
cond_syscall(sys_getpeername);
};
static int ftrace_filtered;
-static int tracing_on;
static LIST_HEAD(ftrace_new_addrs);
static int
__ftrace_replace_code(struct dyn_ftrace *rec,
- unsigned char *old, unsigned char *new, int enable)
+ unsigned char *nop, int enable)
{
unsigned long ip, fl;
+ unsigned char *call, *old, *new;
ip = rec->ip;
- if (ftrace_filtered && enable) {
+ /*
+ * If this record is not to be traced and
+ * it is not enabled then do nothing.
+ *
+ * If this record is not to be traced and
+ * it is enabled then disabled it.
+ *
+ */
+ if (rec->flags & FTRACE_FL_NOTRACE) {
+ if (rec->flags & FTRACE_FL_ENABLED)
+ rec->flags &= ~FTRACE_FL_ENABLED;
+ else
+ return 0;
+
+ } else if (ftrace_filtered && enable) {
/*
- * If filtering is on:
- *
- * If this record is set to be filtered and
- * is enabled then do nothing.
- *
- * If this record is set to be filtered and
- * it is not enabled, enable it.
- *
- * If this record is not set to be filtered
- * and it is not enabled do nothing.
- *
- * If this record is set not to trace then
- * do nothing.
- *
- * If this record is set not to trace and
- * it is enabled then disable it.
- *
- * If this record is not set to be filtered and
- * it is enabled, disable it.
+ * Filtering is on:
*/
- fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE |
- FTRACE_FL_ENABLED);
+ fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
- if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) ||
- (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) ||
- !fl || (fl == FTRACE_FL_NOTRACE))
+ /* Record is filtered and enabled, do nothing */
+ if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
return 0;
- /*
- * If it is enabled disable it,
- * otherwise enable it!
- */
- if (fl & FTRACE_FL_ENABLED) {
- /* swap new and old */
- new = old;
- old = ftrace_call_replace(ip, FTRACE_ADDR);
+ /* Record is not filtered and is not enabled do nothing */
+ if (!fl)
+ return 0;
+
+ /* Record is not filtered but enabled, disable it */
+ if (fl == FTRACE_FL_ENABLED)
rec->flags &= ~FTRACE_FL_ENABLED;
- } else {
- new = ftrace_call_replace(ip, FTRACE_ADDR);
+ else
+ /* Otherwise record is filtered but not enabled, enable it */
rec->flags |= FTRACE_FL_ENABLED;
- }
} else {
+ /* Disable or not filtered */
if (enable) {
- /*
- * If this record is set not to trace and is
- * not enabled, do nothing.
- */
- fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
- if (fl == FTRACE_FL_NOTRACE)
- return 0;
-
- new = ftrace_call_replace(ip, FTRACE_ADDR);
- } else
- old = ftrace_call_replace(ip, FTRACE_ADDR);
-
- if (enable) {
+ /* if record is enabled, do nothing */
if (rec->flags & FTRACE_FL_ENABLED)
return 0;
+
rec->flags |= FTRACE_FL_ENABLED;
+
} else {
+
+ /* if record is not enabled do nothing */
if (!(rec->flags & FTRACE_FL_ENABLED))
return 0;
+
rec->flags &= ~FTRACE_FL_ENABLED;
}
}
+ call = ftrace_call_replace(ip, FTRACE_ADDR);
+
+ if (rec->flags & FTRACE_FL_ENABLED) {
+ old = nop;
+ new = call;
+ } else {
+ old = call;
+ new = nop;
+ }
+
return ftrace_modify_code(ip, old, new);
}
static void ftrace_replace_code(int enable)
{
int i, failed;
- unsigned char *new = NULL, *old = NULL;
+ unsigned char *nop = NULL;
struct dyn_ftrace *rec;
struct ftrace_page *pg;
- if (enable)
- old = ftrace_nop_replace();
- else
- new = ftrace_nop_replace();
+ nop = ftrace_nop_replace();
for (pg = ftrace_pages_start; pg; pg = pg->next) {
for (i = 0; i < pg->index; i++) {
unfreeze_record(rec);
}
- failed = __ftrace_replace_code(rec, old, new, enable);
+ failed = __ftrace_replace_code(rec, nop, enable);
if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
rec->flags |= FTRACE_FL_FAILED;
if ((system_state == SYSTEM_BOOTING) ||
{
int *command = data;
- if (*command & FTRACE_ENABLE_CALLS) {
+ if (*command & FTRACE_ENABLE_CALLS)
ftrace_replace_code(1);
- tracing_on = 1;
- } else if (*command & FTRACE_DISABLE_CALLS) {
+ else if (*command & FTRACE_DISABLE_CALLS)
ftrace_replace_code(0);
- tracing_on = 0;
- }
if (*command & FTRACE_UPDATE_TRACE_FUNC)
ftrace_update_ftrace_func(ftrace_trace_function);
mutex_lock(&ftrace_start_lock);
ftrace_start++;
- if (ftrace_start == 1)
- command |= FTRACE_ENABLE_CALLS;
+ command |= FTRACE_ENABLE_CALLS;
if (saved_ftrace_func != ftrace_trace_function) {
saved_ftrace_func = ftrace_trace_function;
cnt = num_to_init / ENTRIES_PER_PAGE;
pr_info("ftrace: allocating %ld entries in %d pages\n",
- num_to_init, cnt);
+ num_to_init, cnt + 1);
for (i = 0; i < cnt; i++) {
pg->next = (void *)get_zeroed_page(GFP_KERNEL);
((iter->flags & FTRACE_ITER_FAILURES) &&
!(rec->flags & FTRACE_FL_FAILED)) ||
+ ((iter->flags & FTRACE_ITER_FILTER) &&
+ !(rec->flags & FTRACE_FL_FILTER)) ||
+
((iter->flags & FTRACE_ITER_NOTRACE) &&
!(rec->flags & FTRACE_FL_NOTRACE))) {
rec = NULL;
void *p = NULL;
loff_t l = -1;
- if (*pos != iter->pos) {
- for (p = t_next(m, p, &l); p && l < *pos; p = t_next(m, p, &l))
- ;
- } else {
- l = *pos;
- p = t_next(m, p, &l);
- }
+ if (*pos > iter->pos)
+ *pos = iter->pos;
+
+ l = *pos;
+ p = t_next(m, p, &l);
return p;
}
static int t_show(struct seq_file *m, void *v)
{
+ struct ftrace_iterator *iter = m->private;
struct dyn_ftrace *rec = v;
char str[KSYM_SYMBOL_LEN];
+ int ret = 0;
if (!rec)
return 0;
kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
- seq_printf(m, "%s\n", str);
+ ret = seq_printf(m, "%s\n", str);
+ if (ret < 0) {
+ iter->pos--;
+ iter->idx--;
+ }
return 0;
}
return -ENOMEM;
iter->pg = ftrace_pages_start;
- iter->pos = -1;
+ iter->pos = 0;
ret = seq_open(file, &show_ftrace_seq_ops);
if (!ret) {
if (file->f_mode & FMODE_READ) {
iter->pg = ftrace_pages_start;
- iter->pos = -1;
+ iter->pos = 0;
iter->flags = enable ? FTRACE_ITER_FILTER :
FTRACE_ITER_NOTRACE;
mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftrace_start_lock);
- if (iter->filtered && ftrace_start && ftrace_enabled)
+ if (ftrace_start && ftrace_enabled)
ftrace_run_update_code(FTRACE_ENABLE_CALLS);
mutex_unlock(&ftrace_start_lock);
mutex_unlock(&ftrace_sysctl_lock);
#include <linux/list.h>
#include <linux/fs.h>
+#include "trace.h"
+
+/* Global flag to disable all recording to ring buffers */
+static int ring_buffers_off __read_mostly;
+
+/**
+ * tracing_on - enable all tracing buffers
+ *
+ * This function enables all tracing buffers that may have been
+ * disabled with tracing_off.
+ */
+void tracing_on(void)
+{
+ ring_buffers_off = 0;
+}
+
+/**
+ * tracing_off - turn off all tracing buffers
+ *
+ * This function stops all tracing buffers from recording data.
+ * It does not disable any overhead the tracers themselves may
+ * be causing. This function simply causes all recording to
+ * the ring buffers to fail.
+ */
+void tracing_off(void)
+{
+ ring_buffers_off = 1;
+}
+
/* Up this if you want to test the TIME_EXTENTS and normalization */
#define DEBUG_SHIFT 0
/* FIXME!!! */
u64 ring_buffer_time_stamp(int cpu)
{
+ u64 time;
+
+ preempt_disable_notrace();
/* shift to debug/test normalization and TIME_EXTENTS */
- return sched_clock() << DEBUG_SHIFT;
+ time = sched_clock() << DEBUG_SHIFT;
+ preempt_enable_notrace();
+
+ return time;
}
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts)
LIST_HEAD(pages);
int i, cpu;
+ /*
+ * Always succeed at resizing a non-existent buffer:
+ */
+ if (!buffer)
+ return size;
+
size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
size *= BUF_PAGE_SIZE;
buffer_size = buffer->pages * BUF_PAGE_SIZE;
list_del_init(&page->list);
free_buffer_page(page);
}
+ mutex_unlock(&buffer->mutex);
return -ENOMEM;
}
struct ring_buffer_event *event;
int cpu, resched;
+ if (ring_buffers_off)
+ return NULL;
+
if (atomic_read(&buffer->record_disabled))
return NULL;
int ret = -EBUSY;
int cpu, resched;
+ if (ring_buffers_off)
+ return -EBUSY;
+
if (atomic_read(&buffer->record_disabled))
return -EBUSY;
return 0;
}
+static ssize_t
+rb_simple_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ int *p = filp->private_data;
+ char buf[64];
+ int r;
+
+ /* !ring_buffers_off == tracing_on */
+ r = sprintf(buf, "%d\n", !*p);
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t
+rb_simple_write(struct file *filp, const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ int *p = filp->private_data;
+ char buf[64];
+ long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+
+ buf[cnt] = 0;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ /* !ring_buffers_off == tracing_on */
+ *p = !val;
+
+ (*ppos)++;
+
+ return cnt;
+}
+
+static struct file_operations rb_simple_fops = {
+ .open = tracing_open_generic,
+ .read = rb_simple_read,
+ .write = rb_simple_write,
+};
+
+
+static __init int rb_init_debugfs(void)
+{
+ struct dentry *d_tracer;
+ struct dentry *entry;
+
+ d_tracer = tracing_init_dentry();
+
+ entry = debugfs_create_file("tracing_on", 0644, d_tracer,
+ &ring_buffers_off, &rb_simple_fops);
+ if (!entry)
+ pr_warning("Could not create debugfs 'tracing_on' entry\n");
+
+ return 0;
+}
+
+fs_initcall(rb_init_debugfs);
ring_buffer_read_finish(iter->buffer_iter[cpu]);
}
mutex_unlock(&trace_types_lock);
+ kfree(iter);
return ERR_PTR(-ENOMEM);
}
If unsure, say N.
+config DEBUG_NOTIFIERS
+ bool "Debug notifier call chains"
+ depends on DEBUG_KERNEL
+ help
+ Enable this to turn on sanity checking for notifier call chains.
+ This is most useful for kernel developers to make sure that
+ modules properly unregister themselves from notifier chains.
+ This is a relatively cheap check but if you care about maximum
+ performance, say N.
+
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL && \
WARN_ON(!irqs_disabled());
kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
} else
- kunmap(miter->addr);
+ kunmap(miter->page);
miter->page = NULL;
miter->addr = NULL;
dma_addr_t dev_addr;
void *ret;
int order = get_order(size);
+ u64 dma_mask = DMA_32BIT_MASK;
+
+ if (hwdev && hwdev->coherent_dma_mask)
+ dma_mask = hwdev->coherent_dma_mask;
ret = (void *)__get_free_pages(flags, order);
- if (ret && address_needs_mapping(hwdev, virt_to_bus(ret), size)) {
+ if (ret && !is_buffer_dma_capable(dma_mask, virt_to_bus(ret), size)) {
/*
* The allocated memory isn't reachable by the device.
* Fall back on swiotlb_map_single().
dev_addr = virt_to_bus(ret);
/* Confirm address can be DMA'd by device */
- if (address_needs_mapping(hwdev, dev_addr, size)) {
+ if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
- (unsigned long long)*hwdev->dma_mask,
+ (unsigned long long)dma_mask,
(unsigned long long)dev_addr);
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
}
up_read(¤t->mm->mmap_sem);
}
+
+#ifdef CONFIG_PROVE_LOCKING
+void might_fault(void)
+{
+ might_sleep();
+ /*
+ * it would be nicer only to annotate paths which are not under
+ * pagefault_disable, however that requires a larger audit and
+ * providing helpers like get_user_atomic.
+ */
+ if (!in_atomic() && current->mm)
+ might_lock_read(¤t->mm->mmap_sem);
+}
+EXPORT_SYMBOL(might_fault);
+#endif
#include <linux/highmem.h>
#include <linux/vmalloc.h>
#include <linux/ioport.h>
-#include <linux/cpuset.h>
#include <linux/delay.h>
#include <linux/migrate.h>
#include <linux/page-isolation.h>
/* we online node here. we can't roll back from here. */
node_set_online(nid);
- cpuset_track_online_nodes();
-
if (new_pgdat) {
ret = register_one_node(nid);
/*
remove_migration_ptes(page, page);
rc = mapping->a_ops->writepage(page, &wbc);
- if (rc < 0)
- /* I/O Error writing */
- return -EIO;
if (rc != AOP_WRITEPAGE_ACTIVATE)
/* unlocked. Relock */
lock_page(page);
- return -EAGAIN;
+ return (rc < 0) ? -EIO : -EAGAIN;
}
/*
unsigned long addr = start;
struct page *pages[16]; /* 16 gives a reasonable batch */
int nr_pages = (end - start) / PAGE_SIZE;
- int ret;
+ int ret = 0;
int gup_flags = 0;
VM_BUG_ON(start & ~PAGE_MASK);
BUG_ON(size & ~PAGE_MASK);
- addr = ALIGN(vstart, align);
-
va = kmalloc_node(sizeof(struct vmap_area),
gfp_mask & GFP_RECLAIM_MASK, node);
if (unlikely(!va))
return ERR_PTR(-ENOMEM);
retry:
+ addr = ALIGN(vstart, align);
+
spin_lock(&vmap_area_lock);
/* XXX: could have a last_hole cache */
n = vmap_area_root.rb_node;
goto found;
}
- while (addr + size >= first->va_start && addr + size <= vend) {
+ while (addr + size > first->va_start && addr + size <= vend) {
addr = ALIGN(first->va_end + PAGE_SIZE, align);
n = rb_next(&first->rb_node);
spin_unlock(&purge_lock);
}
+/*
+ * Kick off a purge of the outstanding lazy areas. Don't bother if somebody
+ * is already purging.
+ */
+static void try_purge_vmap_area_lazy(void)
+{
+ unsigned long start = ULONG_MAX, end = 0;
+
+ __purge_vmap_area_lazy(&start, &end, 0, 0);
+}
+
/*
* Kick off a purge of the outstanding lazy areas.
*/
{
unsigned long start = ULONG_MAX, end = 0;
- __purge_vmap_area_lazy(&start, &end, 0, 0);
+ __purge_vmap_area_lazy(&start, &end, 1, 0);
}
/*
va->flags |= VM_LAZY_FREE;
atomic_add((va->va_end - va->va_start) >> PAGE_SHIFT, &vmap_lazy_nr);
if (unlikely(atomic_read(&vmap_lazy_nr) > lazy_max_pages()))
- purge_vmap_area_lazy();
+ try_purge_vmap_area_lazy();
}
static struct vmap_area *find_vmap_area(unsigned long addr)
* Try to allocate it some swap space here.
*/
if (PageAnon(page) && !PageSwapCache(page)) {
+ if (!(sc->gfp_mask & __GFP_IO))
+ goto keep_locked;
switch (try_to_munlock(page)) {
case SWAP_FAIL: /* shouldn't happen */
case SWAP_AGAIN:
}
if (!add_to_swap(page, GFP_ATOMIC))
goto activate_locked;
+ may_enter_fs = 1;
}
#endif /* CONFIG_SWAP */
file_prio = 200 - sc->swappiness;
/*
- * anon recent_rotated[0]
- * %anon = 100 * ----------- / ----------------- * IO cost
- * anon + file rotate_sum
+ * The amount of pressure on anon vs file pages is inversely
+ * proportional to the fraction of recently scanned pages on
+ * each list that were recently referenced and in active use.
*/
ap = (anon_prio + 1) * (zone->recent_scanned[0] + 1);
ap /= zone->recent_rotated[0] + 1;
return 1;
}
-static void show_page_path(struct page *page)
-{
- char buf[256];
- if (page_is_file_cache(page)) {
- struct address_space *mapping = page->mapping;
- struct dentry *dentry;
- pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-
- spin_lock(&mapping->i_mmap_lock);
- dentry = d_find_alias(mapping->host);
- printk(KERN_INFO "rescued: %s %lu\n",
- dentry_path(dentry, buf, 256), pgoff);
- spin_unlock(&mapping->i_mmap_lock);
- } else {
-#if defined(CONFIG_MM_OWNER) && defined(CONFIG_MMU)
- struct anon_vma *anon_vma;
- struct vm_area_struct *vma;
-
- anon_vma = page_lock_anon_vma(page);
- if (!anon_vma)
- return;
-
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
- printk(KERN_INFO "rescued: anon %s\n",
- vma->vm_mm->owner->comm);
- break;
- }
- page_unlock_anon_vma(anon_vma);
-#endif
- }
-}
-
-
/**
* check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
* @page: page to check evictability and move to appropriate lru list
if (page_evictable(page, NULL)) {
enum lru_list l = LRU_INACTIVE_ANON + page_is_file_cache(page);
- show_page_path(page);
-
__dec_zone_state(zone, NR_UNEVICTABLE);
list_move(&page->lru, &zone->lru[l].list);
__inc_zone_state(zone, NR_INACTIVE_ANON + l);
If unsure, say N.
+if NET_9P
+
config NET_9P_VIRTIO
- depends on NET_9P && EXPERIMENTAL && VIRTIO
+ depends on EXPERIMENTAL && VIRTIO
tristate "9P Virtio Transport (Experimental)"
help
This builds support for a transports between
guest partitions and a host partition.
config NET_9P_RDMA
- depends on NET_9P && INFINIBAND && EXPERIMENTAL
+ depends on INET && INFINIBAND && EXPERIMENTAL
tristate "9P RDMA Transport (Experimental)"
help
- This builds support for a RDMA transport.
+ This builds support for an RDMA transport.
config NET_9P_DEBUG
bool "Debug information"
- depends on NET_9P
help
Say Y if you want the 9P subsystem to log debug information.
+endif
static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
- AL(6)};
+ AL(4)};
#undef AL
asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
}
-asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const compat_sigset_t __user *sigmask,
- compat_size_t sigsetsize, int flags)
-{
- compat_sigset_t ss32;
- sigset_t ksigmask, sigsaved;
- int ret;
-
- if (sigmask) {
- if (sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
- return -EFAULT;
- sigset_from_compat(&ksigmask, &ss32);
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
-
- ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-
- if (ret == -ERESTARTNOHAND) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-
- return ret;
-}
-
asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
int ret;
u32 a[6];
u32 a0, a1;
- if (call < SYS_SOCKET || call > SYS_PACCEPT)
+ if (call < SYS_SOCKET || call > SYS_ACCEPT4)
return -EINVAL;
if (copy_from_user(a, args, nas[call]))
return -EFAULT;
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
+ ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
break;
case SYS_GETSOCKNAME:
ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
case SYS_RECVMSG:
ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
break;
- case SYS_PACCEPT:
- ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
- compat_ptr(a[3]), a[4], a[5]);
+ case SYS_ACCEPT4:
+ ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);
break;
default:
ret = -EINVAL;
/* make sure that we don't pick a non-existing transmit queue */
ntxq = pkt_dev->odev->real_num_tx_queues;
- if (ntxq > num_online_cpus() && (pkt_dev->flags & F_QUEUE_MAP_CPU)) {
- printk(KERN_WARNING "pktgen: WARNING: QUEUE_MAP_CPU "
- "disabled because CPU count (%d) exceeds number "
- "of tx queues (%d) on %s\n", num_online_cpus(), ntxq,
- pkt_dev->odev->name);
- pkt_dev->flags &= ~F_QUEUE_MAP_CPU;
- }
+
if (ntxq <= pkt_dev->queue_map_min) {
printk(KERN_WARNING "pktgen: WARNING: Requested "
"queue_map_min (zero-based) (%d) exceeds valid range "
}
pkt_dev->cur_queue_map = t;
}
+ pkt_dev->cur_queue_map = pkt_dev->cur_queue_map % pkt_dev->odev->real_num_tx_queues;
}
/* Increment/randomize headers according to flags and current values
if (ifm->ifi_change)
flags = (flags & ifm->ifi_change) |
(dev->flags & ~ifm->ifi_change);
- dev_change_flags(dev, flags);
+ err = dev_change_flags(dev, flags);
+ if (err < 0)
+ goto errout;
}
if (tb[IFLA_TXQLEN])
if (!fpl)
return -ENOMEM;
*fplp = fpl;
- INIT_LIST_HEAD(&fpl->list);
fpl->count = 0;
}
fpp = &fpl->fp[fpl->count];
new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
if (new_fpl) {
- INIT_LIST_HEAD(&new_fpl->list);
for (i=fpl->count-1; i>=0; i--)
get_file(fpl->fp[i]);
memcpy(new_fpl, fpl, sizeof(*fpl));
static struct lock_class_key af_family_keys[AF_MAX];
static struct lock_class_key af_family_slock_keys[AF_MAX];
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make lock validator output more readable. (we pre-construct these
* strings build-time, so that runtime initialization of socket
"clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" ,
"clock-AF_MAX"
};
-#endif
/*
* sk_callback_lock locking rules are per-address-family,
},
},
.proto = sk->sk_protocol,
+ .flags = inet_sk_flowi_flags(sk),
.uli_u = {
.ports = {
.sport = inet->sport,
hash = protocol & (MAX_INET_PROTOS - 1);
ipprot = rcu_dereference(inet_protos[hash]);
- if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) {
+ if (ipprot != NULL) {
int ret;
+ if (!net_eq(net, &init_net) && !ipprot->netns_ok) {
+ if (net_ratelimit())
+ printk("%s: proto %d isn't netns-ready\n",
+ __func__, protocol);
+ kfree_skb(skb);
+ goto out;
+ }
+
if (!ipprot->no_policy) {
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
kfree_skb(skb);
goto proc_cache_fail;
#endif
return 0;
-reg_notif_fail:
- kmem_cache_destroy(mrt_cachep);
#ifdef CONFIG_PROC_FS
-proc_vif_fail:
- unregister_netdevice_notifier(&ip_mr_notifier);
proc_cache_fail:
proc_net_remove(&init_net, "ip_mr_vif");
+proc_vif_fail:
+ unregister_netdevice_notifier(&ip_mr_notifier);
#endif
+reg_notif_fail:
+ del_timer(&ipmr_expire_timer);
+ kmem_cache_destroy(mrt_cachep);
return err;
}
.saddr = saddr,
.tos = tos } },
.proto = sk->sk_protocol,
+ .flags = inet_sk_flowi_flags(sk),
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = dport } } };
switch (rthdr->type) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
+ if (rthdr->hdrlen != 2 ||
+ rthdr->segments_left != 1) {
+ err = -EINVAL;
+ goto exit_f;
+ }
break;
#endif
default:
.open = ip6mr_vif_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
.open = ipmr_mfc_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
#endif
}
/* routing header option needs extra check */
+ retv = -EINVAL;
if (optname == IPV6_RTHDR && opt && opt->srcrt) {
struct ipv6_rt_hdr *rthdr = opt->srcrt;
switch (rthdr->type) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
+ if (rthdr->hdrlen != 2 ||
+ rthdr->segments_left != 1)
+ goto sticky_done;
+
break;
#endif
default:
static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
{
- static char name[32];
+ char name[32];
int i;
/* print by name -- deprecated items */
p = icmp6type2name[icmptype];
if (!p) /* don't print un-named types here */
continue;
- (void) snprintf(name, sizeof(name)-1, "Icmp6%s%s",
+ snprintf(name, sizeof(name), "Icmp6%s%s",
i & 0x100 ? "Out" : "In", p);
seq_printf(seq, "%-32s\t%lu\n", name,
snmp_fold_field(mib, i));
val = snmp_fold_field(mib, i);
if (!val)
continue;
- (void) snprintf(name, sizeof(name)-1, "Icmp6%sType%u",
+ snprintf(name, sizeof(name), "Icmp6%sType%u",
i & 0x100 ? "Out" : "In", i & 0xff);
seq_printf(seq, "%-32s\t%lu\n", name, val);
}
ieee80211_restart_sta_timer(sdata);
rcu_read_unlock();
}
-
-/* driver notification call */
-void ieee80211_notify_mac(struct ieee80211_hw *hw,
- enum ieee80211_notification_types notif_type)
-{
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata;
-
- switch (notif_type) {
- case IEEE80211_NOTIFY_RE_ASSOC:
- rtnl_lock();
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- continue;
-
- ieee80211_sta_req_auth(sdata, &sdata->u.sta);
- }
- rtnl_unlock();
- break;
- }
-}
-EXPORT_SYMBOL(ieee80211_notify_mac);
#include <net/phonet/phonet.h>
#include <net/phonet/pn_dev.h>
-static struct net_proto_family phonet_proto_family;
-static struct phonet_protocol *phonet_proto_get(int protocol);
-static inline void phonet_proto_put(struct phonet_protocol *pp);
+/* Transport protocol registration */
+static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
+static DEFINE_SPINLOCK(proto_tab_lock);
+
+static struct phonet_protocol *phonet_proto_get(int protocol)
+{
+ struct phonet_protocol *pp;
+
+ if (protocol >= PHONET_NPROTO)
+ return NULL;
+
+ spin_lock(&proto_tab_lock);
+ pp = proto_tab[protocol];
+ if (pp && !try_module_get(pp->prot->owner))
+ pp = NULL;
+ spin_unlock(&proto_tab_lock);
+
+ return pp;
+}
+
+static inline void phonet_proto_put(struct phonet_protocol *pp)
+{
+ module_put(pp->prot->owner);
+}
/* protocol family functions */
struct phonethdr *ph;
int err;
- if (skb->len + 2 > 0xffff) {
- /* Phonet length field would overflow */
+ if (skb->len + 2 > 0xffff /* Phonet length field limit */ ||
+ skb->len + sizeof(struct phonethdr) > dev->mtu) {
err = -EMSGSIZE;
goto drop;
}
.func = phonet_rcv,
};
-/* Transport protocol registration */
-static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
-static DEFINE_SPINLOCK(proto_tab_lock);
-
int __init_or_module phonet_proto_register(int protocol,
struct phonet_protocol *pp)
{
}
EXPORT_SYMBOL(phonet_proto_unregister);
-static struct phonet_protocol *phonet_proto_get(int protocol)
-{
- struct phonet_protocol *pp;
-
- if (protocol >= PHONET_NPROTO)
- return NULL;
-
- spin_lock(&proto_tab_lock);
- pp = proto_tab[protocol];
- if (pp && !try_module_get(pp->prot->owner))
- pp = NULL;
- spin_unlock(&proto_tab_lock);
-
- return pp;
-}
-
-static inline void phonet_proto_put(struct phonet_protocol *pp)
-{
- module_put(pp->prot->owner);
-}
-
/* Module registration */
static int __init phonet_init(void)
{
struct nlattr *nest;
nest = nla_nest_start(skb, TCA_STAB);
+ if (nest == NULL)
+ goto nla_put_failure;
NLA_PUT(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts);
nla_nest_end(skb, nest);
void netif_carrier_on(struct net_device *dev)
{
if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
+ if (dev->reg_state == NETREG_UNINITIALIZED)
+ return;
linkwatch_fire_event(dev);
if (netif_running(dev))
__netdev_watchdog_up(dev);
*/
void netif_carrier_off(struct net_device *dev)
{
- if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
+ if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
+ if (dev->reg_state == NETREG_UNINITIALIZED)
+ return;
linkwatch_fire_event(dev);
+ }
}
EXPORT_SYMBOL(netif_carrier_off);
* clean when we restucture accept also.
*/
-long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen, int flags)
+asmlinkage long sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen, int flags)
{
struct socket *sock, *newsock;
struct file *newfile;
goto out_put;
}
-#if 0
-#ifdef HAVE_SET_RESTORE_SIGMASK
-asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const sigset_t __user *sigmask,
- size_t sigsetsize, int flags)
-{
- sigset_t ksigmask, sigsaved;
- int ret;
-
- if (sigmask) {
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
-
- ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-
- if (ret < 0 && signal_pending(current)) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-
- return ret;
-}
-#else
-asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen,
- const sigset_t __user *sigmask,
- size_t sigsetsize, int flags)
-{
- /* The platform does not support restoring the signal mask in the
- * return path. So we do not allow using paccept() with a signal
- * mask. */
- if (sigmask)
- return -EINVAL;
-
- return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
-}
-#endif
-#endif
-
asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
{
- return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0);
+ return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
}
/*
AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
- AL(6)
+ AL(4)
};
#undef AL
unsigned long a0, a1;
int err;
- if (call < 1 || call > SYS_PACCEPT)
+ if (call < 1 || call > SYS_ACCEPT4)
return -EINVAL;
/* copy_from_user should be SMP safe. */
err = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- err =
- do_accept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2], 0);
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], 0);
break;
case SYS_GETSOCKNAME:
err =
case SYS_RECVMSG:
err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
break;
- case SYS_PACCEPT:
- err =
- sys_paccept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2],
- (const sigset_t __user *) a[3],
- a[4], a[5]);
+ case SYS_ACCEPT4:
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], a[3]);
break;
default:
err = -EINVAL;
generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
{
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
+ int i;
if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
- gcred->acred.group_info != acred->group_info ||
gcred->acred.machine_cred != acred->machine_cred)
- return 0;
+ goto out_nomatch;
+
+ /* Optimisation in the case where pointers are identical... */
+ if (gcred->acred.group_info == acred->group_info)
+ goto out_match;
+
+ /* Slow path... */
+ if (gcred->acred.group_info->ngroups != acred->group_info->ngroups)
+ goto out_nomatch;
+ for (i = 0; i < gcred->acred.group_info->ngroups; i++) {
+ if (GROUP_AT(gcred->acred.group_info, i) !=
+ GROUP_AT(acred->group_info, i))
+ goto out_nomatch;
+ }
+out_match:
return 1;
+out_nomatch:
+ return 0;
}
void __init rpc_init_generic_auth(void)
container_of(work, struct hda_beep, beep_work);
struct hda_codec *codec = beep->codec;
+ if (!beep->enabled)
+ return;
+
/* generate tone */
snd_hda_codec_write_cache(codec, beep->nid, 0,
AC_VERB_SET_BEEP_CONTROL, beep->tone);
snprintf(beep->phys, sizeof(beep->phys),
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(beep);
+ return -ENOMEM;
+ }
/* setup digital beep device */
input_dev->name = "HDA Digital PCBeep";
beep->nid = nid;
beep->dev = input_dev;
beep->codec = codec;
+ beep->enabled = 1;
codec->beep = beep;
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
char phys[32];
int tone;
int nid;
+ int enabled;
struct work_struct beep_work; /* scheduled task for beep event */
};
#include "hda_beep.h"
#define NUM_CONTROL_ALLOC 32
+
+#define STAC_VREF_EVENT 0x00
+#define STAC_INSERT_EVENT 0x10
#define STAC_PWR_EVENT 0x20
#define STAC_HP_EVENT 0x30
-#define STAC_VREF_EVENT 0x40
enum {
STAC_REF,
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2,
+ "HP dv5", STAC_HP_M4),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4,
+ "HP dv7", STAC_HP_M4),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
"unknown HP", STAC_HP_M4),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
};
/* add dynamic controls */
-static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type,
- int idx, const char *name, unsigned long val)
+static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
+ struct snd_kcontrol_new *ktemp,
+ int idx, const char *name,
+ unsigned long val)
{
struct snd_kcontrol_new *knew;
}
knew = &spec->kctl_alloc[spec->num_kctl_used];
- *knew = stac92xx_control_templates[type];
+ *knew = *ktemp;
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
- if (! knew->name)
+ if (!knew->name)
return -ENOMEM;
knew->private_value = val;
spec->num_kctl_used++;
return 0;
}
+static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec,
+ int type, int idx, const char *name,
+ unsigned long val)
+{
+ return stac92xx_add_control_temp(spec,
+ &stac92xx_control_templates[type],
+ idx, name, val);
+}
+
/* add dynamic controls */
-static int stac92xx_add_control(struct sigmatel_spec *spec, int type,
- const char *name, unsigned long val)
+static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
+ const char *name, unsigned long val)
{
return stac92xx_add_control_idx(spec, type, 0, name, val);
}
return 0;
}
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info
+
+static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = codec->beep->enabled;
+ return 0;
+}
+
+static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ int enabled = !!ucontrol->value.integer.value[0];
+ if (codec->beep->enabled != enabled) {
+ codec->beep->enabled = enabled;
+ return 1;
+ }
+ return 0;
+}
+
+static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = stac92xx_dig_beep_switch_info,
+ .get = stac92xx_dig_beep_switch_get,
+ .put = stac92xx_dig_beep_switch_put,
+};
+
+static int stac92xx_beep_switch_ctl(struct hda_codec *codec)
+{
+ return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl,
+ 0, "PC Beep Playback Switch", 0);
+}
+#endif
+
static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (spec->digbeep_nid > 0) {
hda_nid_t nid = spec->digbeep_nid;
+ unsigned int caps;
err = stac92xx_auto_create_beep_ctls(codec, nid);
if (err < 0)
err = snd_hda_attach_beep_device(codec, nid);
if (err < 0)
return err;
+ /* if no beep switch is available, make its own one */
+ caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+ if (codec->beep &&
+ !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
+ err = stac92xx_beep_switch_ctl(codec);
+ if (err < 0)
+ return err;
+ }
}
#endif
stac92xx_set_config_regs(codec);
}
+ if (spec->board_config > STAC_92HD71BXX_REF) {
+ /* GPIO0 = EAPD */
+ spec->gpio_mask = 0x01;
+ spec->gpio_dir = 0x01;
+ spec->gpio_data = 0x01;
+ }
+
switch (codec->vendor_id) {
case 0x111d76b6: /* 4 Port without Analog Mixer */
case 0x111d76b7:
codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
break;
case 0x111d7608: /* 5 Port with Analog Mixer */
- switch (codec->subsystem_id) {
- case 0x103c361a:
+ switch (spec->board_config) {
+ case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
- snd_hda_codec_write(codec, codec->afg, 0,
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
- if (spec->board_config > STAC_92HD71BXX_REF) {
- /* GPIO0 = EAPD */
- spec->gpio_mask = 0x01;
- spec->gpio_dir = 0x01;
- spec->gpio_data = 0x01;
- }
-
spec->powerdown_adcs = 1;
spec->digbeep_nid = 0x26;
spec->mux_nids = stac92hd71bxx_mux_nids;
stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
- snd_hda_codec_write(codec, codec->afg, 0,
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
return -ENOMEM;
}
- if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST))
+ if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) {
+ kfree(mgr);
+ pci_disable_device(pci);
return -ENODEV;
+ }
card_name = pcxhr_board_params[pci_id->driver_data].board_name;
mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;
mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips;