mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
Merge branch 'master'
This commit is contained in:
commit
4741c336d2
@ -33,7 +33,9 @@ pci_alloc_consistent(struct pci_dev *dev, size_t size,
|
||||
|
||||
Consistent memory is memory for which a write by either the device or
|
||||
the processor can immediately be read by the processor or device
|
||||
without having to worry about caching effects.
|
||||
without having to worry about caching effects. (You may however need
|
||||
to make sure to flush the processor's write buffers before telling
|
||||
devices to read that memory.)
|
||||
|
||||
This routine allocates a region of <size> bytes of consistent memory.
|
||||
it also returns a <dma_handle> which may be cast to an unsigned
|
||||
@ -304,12 +306,12 @@ dma address with dma_mapping_error(). A non zero return value means the mapping
|
||||
could not be created and the driver should take appropriate action (eg
|
||||
reduce current DMA mapping usage or delay and try again later).
|
||||
|
||||
int
|
||||
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction direction)
|
||||
int
|
||||
pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
int
|
||||
dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
int
|
||||
pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
|
||||
Maps a scatter gather list from the block layer.
|
||||
|
||||
@ -327,12 +329,33 @@ critical that the driver do something, in the case of a block driver
|
||||
aborting the request or even oopsing is better than doing nothing and
|
||||
corrupting the filesystem.
|
||||
|
||||
void
|
||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
|
||||
enum dma_data_direction direction)
|
||||
void
|
||||
pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
With scatterlists, you use the resulting mapping like this:
|
||||
|
||||
int i, count = dma_map_sg(dev, sglist, nents, direction);
|
||||
struct scatterlist *sg;
|
||||
|
||||
for (i = 0, sg = sglist; i < count; i++, sg++) {
|
||||
hw_address[i] = sg_dma_address(sg);
|
||||
hw_len[i] = sg_dma_len(sg);
|
||||
}
|
||||
|
||||
where nents is the number of entries in the sglist.
|
||||
|
||||
The implementation is free to merge several consecutive sglist entries
|
||||
into one (e.g. with an IOMMU, or if several pages just happen to be
|
||||
physically contiguous) and returns the actual number of sg entries it
|
||||
mapped them to. On failure 0, is returned.
|
||||
|
||||
Then you should loop count times (note: this can be less than nents times)
|
||||
and use sg_dma_address() and sg_dma_len() macros where you previously
|
||||
accessed sg->address and sg->length as shown above.
|
||||
|
||||
void
|
||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||
int nhwentries, enum dma_data_direction direction)
|
||||
void
|
||||
pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
|
||||
unmap the previously mapped scatter/gather list. All the parameters
|
||||
must be the same as those and passed in to the scatter/gather mapping
|
||||
|
@ -58,11 +58,15 @@ translating each of those pages back to a kernel address using
|
||||
something like __va(). [ EDIT: Update this when we integrate
|
||||
Gerd Knorr's generic code which does this. ]
|
||||
|
||||
This rule also means that you may not use kernel image addresses
|
||||
(ie. items in the kernel's data/text/bss segment, or your driver's)
|
||||
nor may you use kernel stack addresses for DMA. Both of these items
|
||||
might be mapped somewhere entirely different than the rest of physical
|
||||
memory.
|
||||
This rule also means that you may use neither kernel image addresses
|
||||
(items in data/text/bss segments), nor module image addresses, nor
|
||||
stack addresses for DMA. These could all be mapped somewhere entirely
|
||||
different than the rest of physical memory. Even if those classes of
|
||||
memory could physically work with DMA, you'd need to ensure the I/O
|
||||
buffers were cacheline-aligned. Without that, you'd see cacheline
|
||||
sharing problems (data corruption) on CPUs with DMA-incoherent caches.
|
||||
(The CPU could write to one word, DMA would write to a different one
|
||||
in the same cache line, and one of them could be overwritten.)
|
||||
|
||||
Also, this means that you cannot take the return of a kmap()
|
||||
call and DMA to/from that. This is similar to vmalloc().
|
||||
@ -284,6 +288,11 @@ There are two types of DMA mappings:
|
||||
|
||||
in order to get correct behavior on all platforms.
|
||||
|
||||
Also, on some platforms your driver may need to flush CPU write
|
||||
buffers in much the same way as it needs to flush write buffers
|
||||
found in PCI bridges (such as by reading a register's value
|
||||
after writing it).
|
||||
|
||||
- Streaming DMA mappings which are usually mapped for one DMA transfer,
|
||||
unmapped right after it (unless you use pci_dma_sync_* below) and for which
|
||||
hardware can optimize for sequential accesses.
|
||||
@ -303,6 +312,9 @@ There are two types of DMA mappings:
|
||||
|
||||
Neither type of DMA mapping has alignment restrictions that come
|
||||
from PCI, although some devices may have such restrictions.
|
||||
Also, systems with caches that aren't DMA-coherent will work better
|
||||
when the underlying buffers don't share cache lines with other data.
|
||||
|
||||
|
||||
Using Consistent DMA mappings.
|
||||
|
||||
|
@ -12,18 +12,22 @@ meant as a replacement for the older, individual drivers:
|
||||
teletext adapters)
|
||||
|
||||
It currently supports the following devices:
|
||||
* Philips adapter
|
||||
* home brew teletext adapter
|
||||
* Velleman K8000 adapter
|
||||
* ELV adapter
|
||||
* Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
|
||||
* Barco LPT->DVI (K5800236) adapter
|
||||
* (type=0) Philips adapter
|
||||
* (type=1) home brew teletext adapter
|
||||
* (type=2) Velleman K8000 adapter
|
||||
* (type=3) ELV adapter
|
||||
* (type=4) Analog Devices ADM1032 evaluation board
|
||||
* (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
|
||||
* (type=6) Barco LPT->DVI (K5800236) adapter
|
||||
|
||||
These devices use different pinout configurations, so you have to tell
|
||||
the driver what you have, using the type module parameter. There is no
|
||||
way to autodetect the devices. Support for different pinout configurations
|
||||
can be easily added when needed.
|
||||
|
||||
Earlier kernels defaulted to type=0 (Philips). But now, if the type
|
||||
parameter is missing, the driver will simply fail to initialize.
|
||||
|
||||
|
||||
Building your own adapter
|
||||
-------------------------
|
||||
|
166
Documentation/networking/xfrm_sync.txt
Normal file
166
Documentation/networking/xfrm_sync.txt
Normal file
@ -0,0 +1,166 @@
|
||||
|
||||
The sync patches work is based on initial patches from
|
||||
Krisztian <hidden@balabit.hu> and others and additional patches
|
||||
from Jamal <hadi@cyberus.ca>.
|
||||
|
||||
The end goal for syncing is to be able to insert attributes + generate
|
||||
events so that the an SA can be safely moved from one machine to another
|
||||
for HA purposes.
|
||||
The idea is to synchronize the SA so that the takeover machine can do
|
||||
the processing of the SA as accurate as possible if it has access to it.
|
||||
|
||||
We already have the ability to generate SA add/del/upd events.
|
||||
These patches add ability to sync and have accurate lifetime byte (to
|
||||
ensure proper decay of SAs) and replay counters to avoid replay attacks
|
||||
with as minimal loss at failover time.
|
||||
This way a backup stays as closely uptodate as an active member.
|
||||
|
||||
Because the above items change for every packet the SA receives,
|
||||
it is possible for a lot of the events to be generated.
|
||||
For this reason, we also add a nagle-like algorithm to restrict
|
||||
the events. i.e we are going to set thresholds to say "let me
|
||||
know if the replay sequence threshold is reached or 10 secs have passed"
|
||||
These thresholds are set system-wide via sysctls or can be updated
|
||||
per SA.
|
||||
|
||||
The identified items that need to be synchronized are:
|
||||
- the lifetime byte counter
|
||||
note that: lifetime time limit is not important if you assume the failover
|
||||
machine is known ahead of time since the decay of the time countdown
|
||||
is not driven by packet arrival.
|
||||
- the replay sequence for both inbound and outbound
|
||||
|
||||
1) Message Structure
|
||||
----------------------
|
||||
|
||||
nlmsghdr:aevent_id:optional-TLVs.
|
||||
|
||||
The netlink message types are:
|
||||
|
||||
XFRM_MSG_NEWAE and XFRM_MSG_GETAE.
|
||||
|
||||
A XFRM_MSG_GETAE does not have TLVs.
|
||||
A XFRM_MSG_NEWAE will have at least two TLVs (as is
|
||||
discussed further below).
|
||||
|
||||
aevent_id structure looks like:
|
||||
|
||||
struct xfrm_aevent_id {
|
||||
struct xfrm_usersa_id sa_id;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
xfrm_usersa_id in this message layout identifies the SA.
|
||||
|
||||
flags are used to indicate different things. The possible
|
||||
flags are:
|
||||
XFRM_AE_RTHR=1, /* replay threshold*/
|
||||
XFRM_AE_RVAL=2, /* replay value */
|
||||
XFRM_AE_LVAL=4, /* lifetime value */
|
||||
XFRM_AE_ETHR=8, /* expiry timer threshold */
|
||||
XFRM_AE_CR=16, /* Event cause is replay update */
|
||||
XFRM_AE_CE=32, /* Event cause is timer expiry */
|
||||
XFRM_AE_CU=64, /* Event cause is policy update */
|
||||
|
||||
How these flags are used is dependent on the direction of the
|
||||
message (kernel<->user) as well the cause (config, query or event).
|
||||
This is described below in the different messages.
|
||||
|
||||
The pid will be set appropriately in netlink to recognize direction
|
||||
(0 to the kernel and pid = processid that created the event
|
||||
when going from kernel to user space)
|
||||
|
||||
A program needs to subscribe to multicast group XFRMNLGRP_AEVENTS
|
||||
to get notified of these events.
|
||||
|
||||
2) TLVS reflect the different parameters:
|
||||
-----------------------------------------
|
||||
|
||||
a) byte value (XFRMA_LTIME_VAL)
|
||||
This TLV carries the running/current counter for byte lifetime since
|
||||
last event.
|
||||
|
||||
b)replay value (XFRMA_REPLAY_VAL)
|
||||
This TLV carries the running/current counter for replay sequence since
|
||||
last event.
|
||||
|
||||
c)replay threshold (XFRMA_REPLAY_THRESH)
|
||||
This TLV carries the threshold being used by the kernel to trigger events
|
||||
when the replay sequence is exceeded.
|
||||
|
||||
d) expiry timer (XFRMA_ETIMER_THRESH)
|
||||
This is a timer value in milliseconds which is used as the nagle
|
||||
value to rate limit the events.
|
||||
|
||||
3) Default configurations for the parameters:
|
||||
----------------------------------------------
|
||||
|
||||
By default these events should be turned off unless there is
|
||||
at least one listener registered to listen to the multicast
|
||||
group XFRMNLGRP_AEVENTS.
|
||||
|
||||
Programs installing SAs will need to specify the two thresholds, however,
|
||||
in order to not change existing applications such as racoon
|
||||
we also provide default threshold values for these different parameters
|
||||
in case they are not specified.
|
||||
|
||||
the two sysctls/proc entries are:
|
||||
a) /proc/sys/net/core/sysctl_xfrm_aevent_etime
|
||||
used to provide default values for the XFRMA_ETIMER_THRESH in incremental
|
||||
units of time of 100ms. The default is 10 (1 second)
|
||||
|
||||
b) /proc/sys/net/core/sysctl_xfrm_aevent_rseqth
|
||||
used to provide default values for XFRMA_REPLAY_THRESH parameter
|
||||
in incremental packet count. The default is two packets.
|
||||
|
||||
4) Message types
|
||||
----------------
|
||||
|
||||
a) XFRM_MSG_GETAE issued by user-->kernel.
|
||||
XFRM_MSG_GETAE does not carry any TLVs.
|
||||
The response is a XFRM_MSG_NEWAE which is formatted based on what
|
||||
XFRM_MSG_GETAE queried for.
|
||||
The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
|
||||
*if XFRM_AE_RTHR flag is set, then XFRMA_REPLAY_THRESH is also retrieved
|
||||
*if XFRM_AE_ETHR flag is set, then XFRMA_ETIMER_THRESH is also retrieved
|
||||
|
||||
b) XFRM_MSG_NEWAE is issued by either user space to configure
|
||||
or kernel to announce events or respond to a XFRM_MSG_GETAE.
|
||||
|
||||
i) user --> kernel to configure a specific SA.
|
||||
any of the values or threshold parameters can be updated by passing the
|
||||
appropriate TLV.
|
||||
A response is issued back to the sender in user space to indicate success
|
||||
or failure.
|
||||
In the case of success, additionally an event with
|
||||
XFRM_MSG_NEWAE is also issued to any listeners as described in iii).
|
||||
|
||||
ii) kernel->user direction as a response to XFRM_MSG_GETAE
|
||||
The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
|
||||
The threshold TLVs will be included if explicitly requested in
|
||||
the XFRM_MSG_GETAE message.
|
||||
|
||||
iii) kernel->user to report as event if someone sets any values or
|
||||
thresholds for an SA using XFRM_MSG_NEWAE (as described in #i above).
|
||||
In such a case XFRM_AE_CU flag is set to inform the user that
|
||||
the change happened as a result of an update.
|
||||
The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
|
||||
|
||||
iv) kernel->user to report event when replay threshold or a timeout
|
||||
is exceeded.
|
||||
In such a case either XFRM_AE_CR (replay exceeded) or XFRM_AE_CE (timeout
|
||||
happened) is set to inform the user what happened.
|
||||
Note the two flags are mutually exclusive.
|
||||
The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
|
||||
|
||||
Exceptions to threshold settings
|
||||
--------------------------------
|
||||
|
||||
If you have an SA that is getting hit by traffic in bursts such that
|
||||
there is a period where the timer threshold expires with no packets
|
||||
seen, then an odd behavior is seen as follows:
|
||||
The first packet arrival after a timer expiry will trigger a timeout
|
||||
aevent; i.e we dont wait for a timeout period or a packet threshold
|
||||
to be reached. This is done for simplicity and efficiency reasons.
|
||||
|
||||
-JHS
|
@ -3,14 +3,11 @@
|
||||
--------------------
|
||||
|
||||
|
||||
$Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
|
||||
|
||||
|
||||
This document is meant as a brief overview of some aspects of the new serial
|
||||
driver. It is not complete, any questions you have should be directed to
|
||||
<rmk@arm.linux.org.uk>
|
||||
|
||||
The reference implementation is contained within serial_amba.c.
|
||||
The reference implementation is contained within amba_pl011.c.
|
||||
|
||||
|
||||
|
||||
@ -31,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing
|
||||
the correct port structure (via uart_get_console) and decoding command line
|
||||
arguments (uart_parse_options).
|
||||
|
||||
There is also a helper function (uart_write_console) which performs a
|
||||
character by character write, translating newlines to CRLF sequences.
|
||||
Driver writers are recommended to use this function rather than implementing
|
||||
their own version.
|
||||
|
||||
|
||||
Locking
|
||||
-------
|
||||
@ -86,6 +88,7 @@ hardware.
|
||||
- TIOCM_DTR DTR signal.
|
||||
- TIOCM_OUT1 OUT1 signal.
|
||||
- TIOCM_OUT2 OUT2 signal.
|
||||
- TIOCM_LOOP Set the port into loopback mode.
|
||||
If the appropriate bit is set, the signal should be driven
|
||||
active. If the bit is clear, the signal should be driven
|
||||
inactive.
|
||||
@ -141,6 +144,10 @@ hardware.
|
||||
enable_ms(port)
|
||||
Enable the modem status interrupts.
|
||||
|
||||
This method may be called multiple times. Modem status
|
||||
interrupts should be disabled when the shutdown method is
|
||||
called.
|
||||
|
||||
Locking: port->lock taken.
|
||||
Interrupts: locally disabled.
|
||||
This call must not sleep
|
||||
@ -160,6 +167,8 @@ hardware.
|
||||
state. Enable the port for reception. It should not activate
|
||||
RTS nor DTR; this will be done via a separate call to set_mctrl.
|
||||
|
||||
This method will only be called when the port is initially opened.
|
||||
|
||||
Locking: port_sem taken.
|
||||
Interrupts: globally disabled.
|
||||
|
||||
@ -169,6 +178,11 @@ hardware.
|
||||
RTS nor DTR; this will have already been done via a separate
|
||||
call to set_mctrl.
|
||||
|
||||
Drivers must not access port->info once this call has completed.
|
||||
|
||||
This method will only be called when there are no more users of
|
||||
this port.
|
||||
|
||||
Locking: port_sem taken.
|
||||
Interrupts: caller dependent.
|
||||
|
||||
|
@ -3058,13 +3058,6 @@ M: khali@linux-fr.org
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Odd Fixes
|
||||
|
||||
WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
|
||||
P: Nenad Corbic
|
||||
M: ncorbic@sangoma.com
|
||||
M: dm@sangoma.com
|
||||
W: http://www.sangoma.com
|
||||
S: Supported
|
||||
|
||||
WATCHDOG DEVICE DRIVERS
|
||||
P: Wim Van Sebroeck
|
||||
M: wim@iguana.be
|
||||
|
@ -194,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
|
||||
#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
|
||||
static struct at91_cf_data cf_data;
|
||||
|
||||
static struct resource at91_cf_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91_CF_BASE,
|
||||
/* ties up CS4, CS5, and CS6 */
|
||||
.end = AT91_CF_BASE + (0x30000000 - 1),
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at91rm9200_cf_device = {
|
||||
.name = "at91_cf",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &cf_data,
|
||||
},
|
||||
.num_resources = 0,
|
||||
.resource = at91_cf_resources,
|
||||
.num_resources = ARRAY_SIZE(at91_cf_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_cf(struct at91_cf_data *data)
|
||||
|
@ -50,7 +50,7 @@ static struct mtd_partition smdk_default_nand_part[] = {
|
||||
.offset = 0,
|
||||
},
|
||||
[1] = {
|
||||
.name = "S3C2410 flash parition 1",
|
||||
.name = "S3C2410 flash partition 1",
|
||||
.offset = 0,
|
||||
.size = SZ_2M,
|
||||
},
|
||||
|
@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
|
||||
clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
clkdivn |= S3C2440_CLKDIVN_UCLK;
|
||||
__raw_writel(camdivn, S3C2410_CLKDIVN);
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
|
||||
|
||||
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
|
||||
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
|
||||
pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
|
||||
pci-dma.o i386_ksyms.o i387.o bootflag.o \
|
||||
quirks.o i8237.o topology.o alternative.o
|
||||
|
||||
obj-y += cpu/
|
||||
|
@ -314,3 +314,4 @@ ENTRY(sys_call_table)
|
||||
.long sys_get_robust_list
|
||||
.long sys_splice
|
||||
.long sys_sync_file_range
|
||||
.long sys_tee /* 315 */
|
||||
|
@ -588,7 +588,10 @@ static __init int via_router_probe(struct irq_router *r,
|
||||
case PCI_DEVICE_ID_VIA_82C596:
|
||||
case PCI_DEVICE_ID_VIA_82C686:
|
||||
case PCI_DEVICE_ID_VIA_8231:
|
||||
case PCI_DEVICE_ID_VIA_8233A:
|
||||
case PCI_DEVICE_ID_VIA_8235:
|
||||
case PCI_DEVICE_ID_VIA_8237:
|
||||
case PCI_DEVICE_ID_VIA_8237_SATA:
|
||||
/* FIXME: add new ones for 8233/5 */
|
||||
r->name = "VIA";
|
||||
r->get = pirq_via_get;
|
||||
|
@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
|
||||
obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
|
||||
irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
|
||||
salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
|
||||
unwind.o mca.o mca_asm.o topology.o dmi_scan.o
|
||||
unwind.o mca.o mca_asm.o topology.o
|
||||
|
||||
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
|
||||
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
|
||||
@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
||||
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
|
||||
mca_recovery-y += mca_drv.o mca_drv_asm.o
|
||||
dmi_scan-y += ../../i386/kernel/dmi_scan.o
|
||||
|
||||
# The gate DSO image is built using a special linker script.
|
||||
targets += gate.so gate-syms.o
|
||||
|
@ -1609,5 +1609,6 @@ sys_call_table:
|
||||
data8 sys_set_robust_list
|
||||
data8 sys_get_robust_list
|
||||
data8 sys_sync_file_range // 1300
|
||||
data8 sys_tee
|
||||
|
||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||
|
@ -963,7 +963,7 @@ no_mod:
|
||||
*/
|
||||
|
||||
static void
|
||||
ia64_wait_for_slaves(int monarch)
|
||||
ia64_wait_for_slaves(int monarch, const char *type)
|
||||
{
|
||||
int c, wait = 0, missing = 0;
|
||||
for_each_online_cpu(c) {
|
||||
@ -989,7 +989,7 @@ ia64_wait_for_slaves(int monarch)
|
||||
}
|
||||
if (!missing)
|
||||
goto all_in;
|
||||
printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
|
||||
printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
|
||||
for_each_online_cpu(c) {
|
||||
if (c == monarch)
|
||||
continue;
|
||||
@ -1000,7 +1000,7 @@ ia64_wait_for_slaves(int monarch)
|
||||
return;
|
||||
|
||||
all_in:
|
||||
printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
|
||||
printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1038,7 +1038,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
|
||||
if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
ia64_wait_for_slaves(cpu);
|
||||
ia64_wait_for_slaves(cpu, "MCA");
|
||||
|
||||
/* Wakeup all the processors which are spinning in the rendezvous loop.
|
||||
* They will leave SAL, then spin in the OS with interrupts disabled
|
||||
@ -1429,7 +1429,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
|
||||
*/
|
||||
printk("Delaying for 5 seconds...\n");
|
||||
udelay(5*1000000);
|
||||
ia64_wait_for_slaves(cpu);
|
||||
ia64_wait_for_slaves(cpu, "INIT");
|
||||
/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
|
||||
* to default_monarch_init_process() above and just print all the
|
||||
* tasks.
|
||||
|
@ -519,6 +519,68 @@ void __cpuinit *per_cpu_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
||||
static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
|
||||
{
|
||||
unsigned long end_address, hole_next_pfn;
|
||||
unsigned long stop_address;
|
||||
|
||||
end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
|
||||
end_address = PAGE_ALIGN(end_address);
|
||||
|
||||
stop_address = (unsigned long) &vmem_map[
|
||||
pgdat->node_start_pfn + pgdat->node_spanned_pages];
|
||||
|
||||
do {
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
pgd = pgd_offset_k(end_address);
|
||||
if (pgd_none(*pgd)) {
|
||||
end_address += PGDIR_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
pud = pud_offset(pgd, end_address);
|
||||
if (pud_none(*pud)) {
|
||||
end_address += PUD_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, end_address);
|
||||
if (pmd_none(*pmd)) {
|
||||
end_address += PMD_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
pte = pte_offset_kernel(pmd, end_address);
|
||||
retry_pte:
|
||||
if (pte_none(*pte)) {
|
||||
end_address += PAGE_SIZE;
|
||||
pte++;
|
||||
if ((end_address < stop_address) &&
|
||||
(end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
|
||||
goto retry_pte;
|
||||
continue;
|
||||
}
|
||||
/* Found next valid vmem_map page */
|
||||
break;
|
||||
} while (end_address < stop_address);
|
||||
|
||||
end_address = min(end_address, stop_address);
|
||||
end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
|
||||
hole_next_pfn = end_address / sizeof(struct page);
|
||||
return hole_next_pfn - pgdat->node_start_pfn;
|
||||
}
|
||||
#else
|
||||
static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
|
||||
{
|
||||
return i + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* show_mem - give short summary of memory stats
|
||||
*
|
||||
@ -547,8 +609,10 @@ void show_mem(void)
|
||||
struct page *page;
|
||||
if (pfn_valid(pgdat->node_start_pfn + i))
|
||||
page = pfn_to_page(pgdat->node_start_pfn + i);
|
||||
else
|
||||
else {
|
||||
i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
|
||||
continue;
|
||||
}
|
||||
if (PageReserved(page))
|
||||
reserved++;
|
||||
else if (PageSwapCache(page))
|
||||
|
@ -323,3 +323,4 @@ COMPAT_SYS(pselect6)
|
||||
COMPAT_SYS(ppoll)
|
||||
SYSCALL(unshare)
|
||||
SYSCALL(splice)
|
||||
SYSCALL(tee)
|
||||
|
@ -75,7 +75,7 @@ sys_call_table:
|
||||
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
|
||||
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
|
||||
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
|
||||
/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
/*280*/ .long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
|
||||
/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
|
||||
|
@ -419,6 +419,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
|
||||
region->start = res->start - zero_res.start;
|
||||
region->end = res->end - zero_res.start;
|
||||
}
|
||||
EXPORT_SYMBOL(pcibios_resource_to_bus);
|
||||
|
||||
void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
|
||||
struct pci_bus_region *region)
|
||||
|
@ -138,6 +138,7 @@ SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
|
||||
SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
|
||||
SIGN2(sys32_splice, sys_splice, %o0, %o1)
|
||||
SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
|
||||
SIGN2(sys32_tee, sys_tee, %o0, %o1)
|
||||
|
||||
.globl sys32_mmap2
|
||||
sys32_mmap2:
|
||||
|
@ -76,7 +76,7 @@ sys_call_table32:
|
||||
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
|
||||
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
|
||||
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
|
||||
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
|
||||
/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
|
||||
@ -145,7 +145,7 @@ sys_call_table:
|
||||
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
|
||||
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
|
||||
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
|
||||
/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
/*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
|
||||
|
@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
|
||||
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
|
||||
x8664_ksyms.o i387.o syscall.o vsyscall.o \
|
||||
setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
|
||||
dmi_scan.o pci-dma.o pci-nommu.o
|
||||
pci-dma.o pci-nommu.o
|
||||
|
||||
obj-$(CONFIG_X86_MCE) += mce.o
|
||||
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
|
||||
@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
|
||||
quirks-y += ../../i386/kernel/quirks.o
|
||||
i8237-y += ../../i386/kernel/i8237.o
|
||||
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
|
||||
dmi_scan-y += ../../i386/kernel/dmi_scan.o
|
||||
|
||||
|
@ -350,16 +350,51 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
|
||||
* @file: file this ioctl operates on (optional)
|
||||
* @q: request queue to send scsi commands down
|
||||
* @disk: gendisk to operate on (option)
|
||||
* @sic: userspace structure describing the command to perform
|
||||
*
|
||||
* Send down the scsi command described by @sic to the device below
|
||||
* the request queue @q. If @file is non-NULL it's used to perform
|
||||
* fine-grained permission checks that allow users to send down
|
||||
* non-destructive SCSI commands. If the caller has a struct gendisk
|
||||
* available it should be passed in as @disk to allow the low level
|
||||
* driver to use the information contained in it. A non-NULL @disk
|
||||
* is only allowed if the caller knows that the low level driver doesn't
|
||||
* need it (e.g. in the scsi subsystem).
|
||||
*
|
||||
* Notes:
|
||||
* - This interface is deprecated - users should use the SG_IO
|
||||
* interface instead, as this is a more flexible approach to
|
||||
* performing SCSI commands on a device.
|
||||
* - The SCSI command length is determined by examining the 1st byte
|
||||
* of the given command. There is no way to override this.
|
||||
* - Data transfers are limited to PAGE_SIZE
|
||||
* - The length (x + y) must be at least OMAX_SB_LEN bytes long to
|
||||
* accommodate the sense buffer when an error occurs.
|
||||
* The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
|
||||
* old code will not be surprised.
|
||||
* - If a Unix error occurs (e.g. ENOMEM) then the user will receive
|
||||
* a negative return and the Unix error code in 'errno'.
|
||||
* If the SCSI command succeeds then 0 is returned.
|
||||
* Positive numbers returned are the compacted SCSI error codes (4
|
||||
* bytes in one int) where the lowest byte is the SCSI status.
|
||||
*/
|
||||
#define OMAX_SB_LEN 16 /* For backward compatibility */
|
||||
|
||||
static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
|
||||
struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
|
||||
int sg_scsi_ioctl(struct file *file, struct request_queue *q,
|
||||
struct gendisk *disk, struct scsi_ioctl_command __user *sic)
|
||||
{
|
||||
struct request *rq;
|
||||
int err;
|
||||
unsigned int in_len, out_len, bytes, opcode, cmdlen;
|
||||
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
|
||||
|
||||
if (!sic)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* get in an out lengths, verify they don't exceed a page worth of data
|
||||
*/
|
||||
@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
|
||||
if (copy_from_user(rq->cmd, sic->data, cmdlen))
|
||||
goto error;
|
||||
|
||||
if (copy_from_user(buffer, sic->data + cmdlen, in_len))
|
||||
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
|
||||
goto error;
|
||||
|
||||
err = verify_command(file, rq->cmd);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* default. possible overriden later */
|
||||
rq->retries = 5;
|
||||
|
||||
switch (opcode) {
|
||||
case SEND_DIAGNOSTIC:
|
||||
case FORMAT_UNIT:
|
||||
rq->timeout = FORMAT_UNIT_TIMEOUT;
|
||||
break;
|
||||
case START_STOP:
|
||||
rq->timeout = START_STOP_TIMEOUT;
|
||||
break;
|
||||
case MOVE_MEDIUM:
|
||||
rq->timeout = MOVE_MEDIUM_TIMEOUT;
|
||||
break;
|
||||
case READ_ELEMENT_STATUS:
|
||||
rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
|
||||
break;
|
||||
case READ_DEFECT_DATA:
|
||||
rq->timeout = READ_DEFECT_DATA_TIMEOUT;
|
||||
break;
|
||||
default:
|
||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
||||
break;
|
||||
case SEND_DIAGNOSTIC:
|
||||
case FORMAT_UNIT:
|
||||
rq->timeout = FORMAT_UNIT_TIMEOUT;
|
||||
rq->retries = 1;
|
||||
break;
|
||||
case START_STOP:
|
||||
rq->timeout = START_STOP_TIMEOUT;
|
||||
break;
|
||||
case MOVE_MEDIUM:
|
||||
rq->timeout = MOVE_MEDIUM_TIMEOUT;
|
||||
break;
|
||||
case READ_ELEMENT_STATUS:
|
||||
rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
|
||||
break;
|
||||
case READ_DEFECT_DATA:
|
||||
rq->timeout = READ_DEFECT_DATA_TIMEOUT;
|
||||
rq->retries = 1;
|
||||
break;
|
||||
default:
|
||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
|
||||
err = DRIVER_ERROR << 24;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
|
||||
rq->data = buffer;
|
||||
rq->data_len = bytes;
|
||||
rq->flags |= REQ_BLOCK_PC;
|
||||
rq->retries = 0;
|
||||
|
||||
blk_execute_rq(q, bd_disk, rq, 0);
|
||||
blk_execute_rq(q, disk, rq, 0);
|
||||
|
||||
out:
|
||||
err = rq->errors & 0xff; /* only 8 bit SCSI status */
|
||||
if (err) {
|
||||
if (rq->sense_len && rq->sense) {
|
||||
@ -450,7 +493,7 @@ error:
|
||||
blk_put_request(rq);
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
|
||||
|
||||
/* Send basic block requests */
|
||||
static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
|
||||
|
@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv,
|
||||
up(&dev->sem);
|
||||
if (dev->parent)
|
||||
up(&dev->parent->sem);
|
||||
|
||||
if (err > 0) /* success */
|
||||
err = count;
|
||||
else if (err == 0) /* driver didn't accept device */
|
||||
err = -ENODEV;
|
||||
}
|
||||
put_device(dev);
|
||||
put_bus(bus);
|
||||
|
@ -562,14 +562,13 @@ int class_device_add(struct class_device *class_dev)
|
||||
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
|
||||
|
||||
/* notify any interfaces this device is now here */
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
list_add_tail(&class_dev->node, &parent_class->children);
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node)
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev, class_intf);
|
||||
up(&parent_class->sem);
|
||||
down(&parent_class->sem);
|
||||
list_add_tail(&class_dev->node, &parent_class->children);
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node) {
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev, class_intf);
|
||||
}
|
||||
up(&parent_class->sem);
|
||||
|
||||
register_done:
|
||||
if (error) {
|
||||
|
@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
|
||||
sysfs_remove_link(&dev->kobj, "driver");
|
||||
klist_remove(&dev->knode_driver);
|
||||
|
||||
if (dev->bus->remove)
|
||||
if (dev->bus && dev->bus->remove)
|
||||
dev->bus->remove(dev);
|
||||
else if (drv->remove)
|
||||
drv->remove(dev);
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/pm.h>
|
||||
#include "../base.h"
|
||||
#include "power.h"
|
||||
|
||||
@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state)
|
||||
if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
|
||||
dev_dbg(dev, "suspending\n");
|
||||
error = dev->bus->suspend(dev, state);
|
||||
suspend_report_result(dev->bus->suspend, error);
|
||||
}
|
||||
up(&dev->sem);
|
||||
return error;
|
||||
@ -169,3 +172,12 @@ int device_power_down(pm_message_t state)
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_power_down);
|
||||
|
||||
void __suspend_report_result(const char *function, void *fn, int ret)
|
||||
{
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s(): ", function);
|
||||
print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
|
||||
printk("%d\n", ret);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__suspend_report_result);
|
||||
|
@ -1180,6 +1180,53 @@ static int revalidate_allvol(ctlr_info_t *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void complete_buffers(struct bio *bio, int status)
|
||||
{
|
||||
while (bio) {
|
||||
struct bio *xbh = bio->bi_next;
|
||||
int nr_sectors = bio_sectors(bio);
|
||||
|
||||
bio->bi_next = NULL;
|
||||
blk_finished_io(len);
|
||||
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
|
||||
bio = xbh;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void cciss_softirq_done(struct request *rq)
|
||||
{
|
||||
CommandList_struct *cmd = rq->completion_data;
|
||||
ctlr_info_t *h = hba[cmd->ctlr];
|
||||
unsigned long flags;
|
||||
u64bit temp64;
|
||||
int i, ddir;
|
||||
|
||||
if (cmd->Request.Type.Direction == XFER_READ)
|
||||
ddir = PCI_DMA_FROMDEVICE;
|
||||
else
|
||||
ddir = PCI_DMA_TODEVICE;
|
||||
|
||||
/* command did not need to be retried */
|
||||
/* unmap the DMA mapping for all the scatter gather elements */
|
||||
for(i=0; i<cmd->Header.SGList; i++) {
|
||||
temp64.val32.lower = cmd->SG[i].Addr.lower;
|
||||
temp64.val32.upper = cmd->SG[i].Addr.upper;
|
||||
pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
|
||||
}
|
||||
|
||||
complete_buffers(rq->bio, rq->errors);
|
||||
|
||||
#ifdef CCISS_DEBUG
|
||||
printk("Done with %p\n", rq);
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
spin_lock_irqsave(&h->lock, flags);
|
||||
end_that_request_last(rq, rq->errors);
|
||||
cmd_free(h, cmd,1);
|
||||
spin_unlock_irqrestore(&h->lock, flags);
|
||||
}
|
||||
|
||||
/* This function will check the usage_count of the drive to be updated/added.
|
||||
* If the usage_count is zero then the drive information will be updated and
|
||||
* the disk will be re-registered with the kernel. If not then it will be
|
||||
@ -1248,6 +1295,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
|
||||
|
||||
blk_queue_max_sectors(disk->queue, 512);
|
||||
|
||||
blk_queue_softirq_done(disk->queue, cciss_softirq_done);
|
||||
|
||||
disk->queue->queuedata = hba[ctlr];
|
||||
|
||||
blk_queue_hardsect_size(disk->queue,
|
||||
@ -2147,20 +2196,6 @@ static void start_io( ctlr_info_t *h)
|
||||
addQ (&(h->cmpQ), c);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void complete_buffers(struct bio *bio, int status)
|
||||
{
|
||||
while (bio) {
|
||||
struct bio *xbh = bio->bi_next;
|
||||
int nr_sectors = bio_sectors(bio);
|
||||
|
||||
bio->bi_next = NULL;
|
||||
blk_finished_io(len);
|
||||
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
|
||||
bio = xbh;
|
||||
}
|
||||
|
||||
}
|
||||
/* Assumes that CCISS_LOCK(h->ctlr) is held. */
|
||||
/* Zeros out the error record and then resends the command back */
|
||||
/* to the controller */
|
||||
@ -2178,39 +2213,6 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
|
||||
start_io(h);
|
||||
}
|
||||
|
||||
static void cciss_softirq_done(struct request *rq)
|
||||
{
|
||||
CommandList_struct *cmd = rq->completion_data;
|
||||
ctlr_info_t *h = hba[cmd->ctlr];
|
||||
unsigned long flags;
|
||||
u64bit temp64;
|
||||
int i, ddir;
|
||||
|
||||
if (cmd->Request.Type.Direction == XFER_READ)
|
||||
ddir = PCI_DMA_FROMDEVICE;
|
||||
else
|
||||
ddir = PCI_DMA_TODEVICE;
|
||||
|
||||
/* command did not need to be retried */
|
||||
/* unmap the DMA mapping for all the scatter gather elements */
|
||||
for(i=0; i<cmd->Header.SGList; i++) {
|
||||
temp64.val32.lower = cmd->SG[i].Addr.lower;
|
||||
temp64.val32.upper = cmd->SG[i].Addr.upper;
|
||||
pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
|
||||
}
|
||||
|
||||
complete_buffers(rq->bio, rq->errors);
|
||||
|
||||
#ifdef CCISS_DEBUG
|
||||
printk("Done with %p\n", rq);
|
||||
#endif /* CCISS_DEBUG */
|
||||
|
||||
spin_lock_irqsave(&h->lock, flags);
|
||||
end_that_request_last(rq, rq->errors);
|
||||
cmd_free(h, cmd,1);
|
||||
spin_unlock_irqrestore(&h->lock, flags);
|
||||
}
|
||||
|
||||
/* checks the status of the job and calls complete buffers to mark all
|
||||
* buffers for the completed job. Note that this function does not need
|
||||
* to hold the hba/queue lock.
|
||||
|
@ -64,6 +64,12 @@ static struct gatt_mask efficeon_generic_masks[] =
|
||||
{.mask = 0x00000001, .type = 0}
|
||||
};
|
||||
|
||||
/* This function does the same thing as mask_memory() for this chipset... */
|
||||
static inline unsigned long efficeon_mask_memory(unsigned long addr)
|
||||
{
|
||||
return addr | 0x00000001;
|
||||
}
|
||||
|
||||
static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
|
||||
{
|
||||
{256, 65536, 0},
|
||||
@ -251,7 +257,7 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
|
||||
last_page = NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
int index = pg_start + i;
|
||||
unsigned long insert = mem->memory[i];
|
||||
unsigned long insert = efficeon_mask_memory(mem->memory[i]);
|
||||
|
||||
page = (unsigned int *) efficeon_private.l1_table[index >> 10];
|
||||
|
||||
|
@ -2734,7 +2734,7 @@ static void __do_SAK(void *arg)
|
||||
printk(KERN_NOTICE "SAK: killed process %d"
|
||||
" (%s): fd#%d opened to the tty\n",
|
||||
p->pid, p->comm, i);
|
||||
send_sig(SIGKILL, p, 1);
|
||||
force_sig(SIGKILL, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
obj-$(CONFIG_EDD) += edd.o
|
||||
obj-$(CONFIG_DMI) += dmi_scan.o
|
||||
obj-$(CONFIG_EDD) += edd.o
|
||||
obj-$(CONFIG_EFI_VARS) += efivars.o
|
||||
obj-$(CONFIG_EFI_PCDP) += pcdp.o
|
||||
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
|
||||
|
@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
|
||||
else
|
||||
printk(KERN_ERR "dmi_string: out of memory.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num,
|
||||
{
|
||||
u8 *buf, *data;
|
||||
int i = 0;
|
||||
|
||||
|
||||
buf = dmi_ioremap(base, len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num,
|
||||
data = buf;
|
||||
|
||||
/*
|
||||
* Stop when we see all the items the table claimed to have
|
||||
* OR we run off the end of the table (also happens)
|
||||
*/
|
||||
* Stop when we see all the items the table claimed to have
|
||||
* OR we run off the end of the table (also happens)
|
||||
*/
|
||||
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
|
||||
struct dmi_header *dm = (struct dmi_header *)data;
|
||||
/*
|
||||
@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf)
|
||||
{
|
||||
u8 sum = 0;
|
||||
int a;
|
||||
|
||||
|
||||
for (a = 0; a < 15; a++)
|
||||
sum += buf[a];
|
||||
|
@ -1161,7 +1161,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
bank. */
|
||||
if (kind < 0) {
|
||||
if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
|
||||
dev_warn(dev, "Detection failed at step 3\n");
|
||||
dev_dbg(dev, "Detection failed at step 1\n");
|
||||
goto ERROR1;
|
||||
}
|
||||
val1 = w83792d_read_value(client, W83792D_REG_BANK);
|
||||
@ -1170,6 +1170,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
if (!(val1 & 0x07)) { /* is Bank0 */
|
||||
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
|
||||
((val1 & 0x80) && (val2 != 0x5c))) {
|
||||
dev_dbg(dev, "Detection failed at step 2\n");
|
||||
goto ERROR1;
|
||||
}
|
||||
}
|
||||
@ -1177,7 +1178,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
should match */
|
||||
if (w83792d_read_value(client,
|
||||
W83792D_REG_I2C_ADDR) != address) {
|
||||
dev_warn(dev, "Detection failed at step 5\n");
|
||||
dev_dbg(dev, "Detection failed at step 3\n");
|
||||
goto ERROR1;
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +286,10 @@ config I2C_PARPORT
|
||||
This driver is a replacement for (and was inspired by) an older
|
||||
driver named i2c-philips-par. The new driver supports more devices,
|
||||
and makes it easier to add support for new devices.
|
||||
|
||||
|
||||
An adapter type parameter is now mandatory. Please read the file
|
||||
Documentation/i2c/busses/i2c-parport for details.
|
||||
|
||||
Another driver exists, named i2c-parport-light, which doesn't depend
|
||||
on the parport driver. This is meant for embedded systems. Don't say
|
||||
Y here if you intend to say Y or M there.
|
||||
|
@ -121,9 +121,14 @@ static struct i2c_adapter parport_adapter = {
|
||||
|
||||
static int __init i2c_parport_init(void)
|
||||
{
|
||||
if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
|
||||
if (type < 0) {
|
||||
printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (type >= ARRAY_SIZE(adapter_parm)) {
|
||||
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
|
||||
type = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (base == 0) {
|
||||
|
@ -241,9 +241,14 @@ static struct parport_driver i2c_parport_driver = {
|
||||
|
||||
static int __init i2c_parport_init(void)
|
||||
{
|
||||
if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
|
||||
if (type < 0) {
|
||||
printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (type >= ARRAY_SIZE(adapter_parm)) {
|
||||
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
|
||||
type = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return parport_register_driver(&i2c_parport_driver);
|
||||
|
@ -90,7 +90,7 @@ static struct adapter_parm adapter_parm[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int type;
|
||||
static int type = -1;
|
||||
module_param(type, int, 0);
|
||||
MODULE_PARM_DESC(type,
|
||||
"Type of adapter:\n"
|
||||
|
@ -43,13 +43,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
HISTORY:
|
||||
2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5
|
||||
(was i2c-sis645.c from lm_sensors 2.7.0)
|
||||
*/
|
||||
#define SIS96x_VERSION "1.0.0"
|
||||
|
||||
/* base address register in PCI config space */
|
||||
#define SIS96x_BAR 0x04
|
||||
|
||||
@ -337,7 +330,6 @@ static struct pci_driver sis96x_driver = {
|
||||
|
||||
static int __init i2c_sis96x_init(void)
|
||||
{
|
||||
printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION);
|
||||
return pci_register_driver(&sis96x_driver);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define DS1374_REG_TOD0 0x00
|
||||
#define DS1374_REG_TOD1 0x01
|
||||
@ -139,7 +140,7 @@ ulong ds1374_get_rtc_time(void)
|
||||
return t1;
|
||||
}
|
||||
|
||||
static void ds1374_set_tlet(ulong arg)
|
||||
static void ds1374_set_work(void *arg)
|
||||
{
|
||||
ulong t1, t2;
|
||||
int limit = 10; /* arbitrary retry limit */
|
||||
@ -168,17 +169,18 @@ static void ds1374_set_tlet(ulong arg)
|
||||
|
||||
static ulong new_time;
|
||||
|
||||
static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
|
||||
(ulong) & new_time);
|
||||
static struct workqueue_struct *ds1374_workqueue;
|
||||
|
||||
static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
|
||||
|
||||
int ds1374_set_rtc_time(ulong nowtime)
|
||||
{
|
||||
new_time = nowtime;
|
||||
|
||||
if (in_interrupt())
|
||||
tasklet_schedule(&ds1374_tasklet);
|
||||
queue_work(ds1374_workqueue, &ds1374_work);
|
||||
else
|
||||
ds1374_set_tlet((ulong) & new_time);
|
||||
ds1374_set_work(&new_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -204,6 +206,8 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
|
||||
client->adapter = adap;
|
||||
client->driver = &ds1374_driver;
|
||||
|
||||
ds1374_workqueue = create_singlethread_workqueue("ds1374");
|
||||
|
||||
if ((rc = i2c_attach_client(client)) != 0) {
|
||||
kfree(client);
|
||||
return rc;
|
||||
@ -227,7 +231,7 @@ static int ds1374_detach(struct i2c_client *client)
|
||||
|
||||
if ((rc = i2c_detach_client(client)) == 0) {
|
||||
kfree(i2c_get_clientdata(client));
|
||||
tasklet_kill(&ds1374_tasklet);
|
||||
destroy_workqueue(ds1374_workqueue);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/rtc.h>
|
||||
@ -111,7 +112,7 @@ m41t00_get_rtc_time(void)
|
||||
}
|
||||
|
||||
static void
|
||||
m41t00_set_tlet(ulong arg)
|
||||
m41t00_set(void *arg)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
ulong nowtime = *(ulong *)arg;
|
||||
@ -145,9 +146,9 @@ m41t00_set_tlet(ulong arg)
|
||||
return;
|
||||
}
|
||||
|
||||
static ulong new_time;
|
||||
|
||||
DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
|
||||
static ulong new_time;
|
||||
static struct workqueue_struct *m41t00_wq;
|
||||
static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
|
||||
|
||||
int
|
||||
m41t00_set_rtc_time(ulong nowtime)
|
||||
@ -155,9 +156,9 @@ m41t00_set_rtc_time(ulong nowtime)
|
||||
new_time = nowtime;
|
||||
|
||||
if (in_interrupt())
|
||||
tasklet_schedule(&m41t00_tasklet);
|
||||
queue_work(m41t00_wq, &m41t00_work);
|
||||
else
|
||||
m41t00_set_tlet((ulong)&new_time);
|
||||
m41t00_set(&new_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -189,6 +190,7 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
|
||||
return rc;
|
||||
}
|
||||
|
||||
m41t00_wq = create_singlethread_workqueue("m41t00");
|
||||
save_client = client;
|
||||
return 0;
|
||||
}
|
||||
@ -206,7 +208,7 @@ m41t00_detach(struct i2c_client *client)
|
||||
|
||||
if ((rc = i2c_detach_client(client)) == 0) {
|
||||
kfree(client);
|
||||
tasklet_kill(&m41t00_tasklet);
|
||||
destroy_workqueue(m41t00_wq);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ static void ib_cache_setup_one(struct ib_device *device)
|
||||
kmalloc(sizeof *device->cache.pkey_cache *
|
||||
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
|
||||
device->cache.gid_cache =
|
||||
kmalloc(sizeof *device->cache.pkey_cache *
|
||||
kmalloc(sizeof *device->cache.gid_cache *
|
||||
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
|
||||
|
||||
if (!device->cache.pkey_cache || !device->cache.gid_cache) {
|
||||
|
@ -2311,6 +2311,7 @@ static void local_completions(void *data)
|
||||
local = list_entry(mad_agent_priv->local_list.next,
|
||||
struct ib_mad_local_private,
|
||||
completion_list);
|
||||
list_del(&local->completion_list);
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
if (local->mad_priv) {
|
||||
recv_mad_agent = local->recv_mad_agent;
|
||||
@ -2362,7 +2363,6 @@ local_send_completion:
|
||||
&mad_send_wc);
|
||||
|
||||
spin_lock_irqsave(&mad_agent_priv->lock, flags);
|
||||
list_del(&local->completion_list);
|
||||
atomic_dec(&mad_agent_priv->refcount);
|
||||
if (!recv)
|
||||
kmem_cache_free(ib_mad_cache, local->mad_priv);
|
||||
|
@ -45,6 +45,40 @@
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
int ib_rate_to_mult(enum ib_rate rate)
|
||||
{
|
||||
switch (rate) {
|
||||
case IB_RATE_2_5_GBPS: return 1;
|
||||
case IB_RATE_5_GBPS: return 2;
|
||||
case IB_RATE_10_GBPS: return 4;
|
||||
case IB_RATE_20_GBPS: return 8;
|
||||
case IB_RATE_30_GBPS: return 12;
|
||||
case IB_RATE_40_GBPS: return 16;
|
||||
case IB_RATE_60_GBPS: return 24;
|
||||
case IB_RATE_80_GBPS: return 32;
|
||||
case IB_RATE_120_GBPS: return 48;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ib_rate_to_mult);
|
||||
|
||||
enum ib_rate mult_to_ib_rate(int mult)
|
||||
{
|
||||
switch (mult) {
|
||||
case 1: return IB_RATE_2_5_GBPS;
|
||||
case 2: return IB_RATE_5_GBPS;
|
||||
case 4: return IB_RATE_10_GBPS;
|
||||
case 8: return IB_RATE_20_GBPS;
|
||||
case 12: return IB_RATE_30_GBPS;
|
||||
case 16: return IB_RATE_40_GBPS;
|
||||
case 24: return IB_RATE_60_GBPS;
|
||||
case 32: return IB_RATE_80_GBPS;
|
||||
case 48: return IB_RATE_120_GBPS;
|
||||
default: return IB_RATE_PORT_CURRENT;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(mult_to_ib_rate);
|
||||
|
||||
/* Protection domains */
|
||||
|
||||
struct ib_pd *ib_alloc_pd(struct ib_device *device)
|
||||
|
@ -7,10 +7,11 @@ config INFINIBAND_MTHCA
|
||||
("Tavor") and the MT25208 PCI Express HCA ("Arbel").
|
||||
|
||||
config INFINIBAND_MTHCA_DEBUG
|
||||
bool "Verbose debugging output"
|
||||
bool "Verbose debugging output" if EMBEDDED
|
||||
depends on INFINIBAND_MTHCA
|
||||
default n
|
||||
default y
|
||||
---help---
|
||||
This option causes the mthca driver produce a bunch of debug
|
||||
messages. Select this is you are developing the driver or
|
||||
trying to diagnose a problem.
|
||||
This option causes debugging code to be compiled into the
|
||||
mthca driver. The output can be turned on via the
|
||||
debug_level module parameter (which can also be set after
|
||||
the driver is loaded through sysfs).
|
||||
|
@ -1,7 +1,3 @@
|
||||
ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
|
||||
|
||||
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
|
||||
|
@ -42,6 +42,20 @@
|
||||
|
||||
#include "mthca_dev.h"
|
||||
|
||||
enum {
|
||||
MTHCA_RATE_TAVOR_FULL = 0,
|
||||
MTHCA_RATE_TAVOR_1X = 1,
|
||||
MTHCA_RATE_TAVOR_4X = 2,
|
||||
MTHCA_RATE_TAVOR_1X_DDR = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
MTHCA_RATE_MEMFREE_FULL = 0,
|
||||
MTHCA_RATE_MEMFREE_QUARTER = 1,
|
||||
MTHCA_RATE_MEMFREE_EIGHTH = 2,
|
||||
MTHCA_RATE_MEMFREE_HALF = 3
|
||||
};
|
||||
|
||||
struct mthca_av {
|
||||
__be32 port_pd;
|
||||
u8 reserved1;
|
||||
@ -55,6 +69,90 @@ struct mthca_av {
|
||||
__be32 dgid[4];
|
||||
};
|
||||
|
||||
static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
|
||||
{
|
||||
switch (mthca_rate) {
|
||||
case MTHCA_RATE_MEMFREE_EIGHTH:
|
||||
return mult_to_ib_rate(port_rate >> 3);
|
||||
case MTHCA_RATE_MEMFREE_QUARTER:
|
||||
return mult_to_ib_rate(port_rate >> 2);
|
||||
case MTHCA_RATE_MEMFREE_HALF:
|
||||
return mult_to_ib_rate(port_rate >> 1);
|
||||
case MTHCA_RATE_MEMFREE_FULL:
|
||||
default:
|
||||
return mult_to_ib_rate(port_rate);
|
||||
}
|
||||
}
|
||||
|
||||
static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
|
||||
{
|
||||
switch (mthca_rate) {
|
||||
case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS;
|
||||
case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
|
||||
case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS;
|
||||
default: return port_rate;
|
||||
}
|
||||
}
|
||||
|
||||
enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
|
||||
{
|
||||
if (mthca_is_memfree(dev)) {
|
||||
/* Handle old Arbel FW */
|
||||
if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
|
||||
return IB_RATE_2_5_GBPS;
|
||||
|
||||
return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
|
||||
} else
|
||||
return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
|
||||
}
|
||||
|
||||
static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
|
||||
{
|
||||
if (cur_rate <= req_rate)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Inter-packet delay (IPD) to get from rate X down to a rate
|
||||
* no more than Y is (X - 1) / Y.
|
||||
*/
|
||||
switch ((cur_rate - 1) / req_rate) {
|
||||
case 0: return MTHCA_RATE_MEMFREE_FULL;
|
||||
case 1: return MTHCA_RATE_MEMFREE_HALF;
|
||||
case 2: /* fall through */
|
||||
case 3: return MTHCA_RATE_MEMFREE_QUARTER;
|
||||
default: return MTHCA_RATE_MEMFREE_EIGHTH;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 ib_rate_to_tavor(u8 static_rate)
|
||||
{
|
||||
switch (static_rate) {
|
||||
case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
|
||||
case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR;
|
||||
case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X;
|
||||
default: return MTHCA_RATE_TAVOR_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
|
||||
{
|
||||
u8 rate;
|
||||
|
||||
if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
|
||||
return 0;
|
||||
|
||||
if (mthca_is_memfree(dev))
|
||||
rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
|
||||
dev->rate[port - 1]);
|
||||
else
|
||||
rate = ib_rate_to_tavor(static_rate);
|
||||
|
||||
if (!(dev->limits.stat_rate_support & (1 << rate)))
|
||||
rate = 1;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
int mthca_create_ah(struct mthca_dev *dev,
|
||||
struct mthca_pd *pd,
|
||||
struct ib_ah_attr *ah_attr,
|
||||
@ -107,7 +205,7 @@ on_hca_fail:
|
||||
av->g_slid = ah_attr->src_path_bits;
|
||||
av->dlid = cpu_to_be16(ah_attr->dlid);
|
||||
av->msg_sr = (3 << 4) | /* 2K message */
|
||||
ah_attr->static_rate;
|
||||
mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
|
||||
av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
|
||||
if (ah_attr->ah_flags & IB_AH_GRH) {
|
||||
av->g_slid |= 0x80;
|
||||
|
@ -965,6 +965,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
|
||||
u32 *outbox;
|
||||
u8 field;
|
||||
u16 size;
|
||||
u16 stat_rate;
|
||||
int err;
|
||||
|
||||
#define QUERY_DEV_LIM_OUT_SIZE 0x100
|
||||
@ -995,6 +996,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
|
||||
#define QUERY_DEV_LIM_MTU_WIDTH_OFFSET 0x36
|
||||
#define QUERY_DEV_LIM_VL_PORT_OFFSET 0x37
|
||||
#define QUERY_DEV_LIM_MAX_GID_OFFSET 0x3b
|
||||
#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET 0x3c
|
||||
#define QUERY_DEV_LIM_MAX_PKEY_OFFSET 0x3f
|
||||
#define QUERY_DEV_LIM_FLAGS_OFFSET 0x44
|
||||
#define QUERY_DEV_LIM_RSVD_UAR_OFFSET 0x48
|
||||
@ -1086,6 +1088,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
|
||||
dev_lim->num_ports = field & 0xf;
|
||||
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
|
||||
dev_lim->max_gids = 1 << (field & 0xf);
|
||||
MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
|
||||
dev_lim->stat_rate_support = stat_rate;
|
||||
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
|
||||
dev_lim->max_pkeys = 1 << (field & 0xf);
|
||||
MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
|
||||
|
@ -146,6 +146,7 @@ struct mthca_dev_lim {
|
||||
int max_vl;
|
||||
int num_ports;
|
||||
int max_gids;
|
||||
u16 stat_rate_support;
|
||||
int max_pkeys;
|
||||
u32 flags;
|
||||
int reserved_uars;
|
||||
|
@ -151,6 +151,7 @@ struct mthca_limits {
|
||||
int reserved_qps;
|
||||
int num_srqs;
|
||||
int max_srq_wqes;
|
||||
int max_srq_sge;
|
||||
int reserved_srqs;
|
||||
int num_eecs;
|
||||
int reserved_eecs;
|
||||
@ -172,6 +173,7 @@ struct mthca_limits {
|
||||
int reserved_pds;
|
||||
u32 page_size_cap;
|
||||
u32 flags;
|
||||
u16 stat_rate_support;
|
||||
u8 port_width_cap;
|
||||
};
|
||||
|
||||
@ -353,10 +355,24 @@ struct mthca_dev {
|
||||
struct ib_mad_agent *send_agent[MTHCA_MAX_PORTS][2];
|
||||
struct ib_ah *sm_ah[MTHCA_MAX_PORTS];
|
||||
spinlock_t sm_lock;
|
||||
u8 rate[MTHCA_MAX_PORTS];
|
||||
};
|
||||
|
||||
#define mthca_dbg(mdev, format, arg...) \
|
||||
dev_dbg(&mdev->pdev->dev, format, ## arg)
|
||||
#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
|
||||
extern int mthca_debug_level;
|
||||
|
||||
#define mthca_dbg(mdev, format, arg...) \
|
||||
do { \
|
||||
if (mthca_debug_level) \
|
||||
dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \
|
||||
} while (0)
|
||||
|
||||
#else /* CONFIG_INFINIBAND_MTHCA_DEBUG */
|
||||
|
||||
#define mthca_dbg(mdev, format, arg...) do { (void) mdev; } while (0)
|
||||
|
||||
#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
|
||||
|
||||
#define mthca_err(mdev, format, arg...) \
|
||||
dev_err(&mdev->pdev->dev, format, ## arg)
|
||||
#define mthca_info(mdev, format, arg...) \
|
||||
@ -492,6 +508,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
|
||||
int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
|
||||
enum ib_srq_attr_mask attr_mask);
|
||||
int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
|
||||
int mthca_max_srq_sge(struct mthca_dev *dev);
|
||||
void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
|
||||
enum ib_event_type event_type);
|
||||
void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
|
||||
@ -542,6 +559,8 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
|
||||
struct ib_ud_header *header);
|
||||
int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr);
|
||||
int mthca_ah_grh_present(struct mthca_ah *ah);
|
||||
u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port);
|
||||
enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port);
|
||||
|
||||
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
|
||||
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
|
||||
|
@ -49,6 +49,30 @@ enum {
|
||||
MTHCA_VENDOR_CLASS2 = 0xa
|
||||
};
|
||||
|
||||
int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
|
||||
{
|
||||
struct ib_port_attr *tprops = NULL;
|
||||
int ret;
|
||||
|
||||
tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
|
||||
if (!tprops)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ib_query_port(&dev->ib_dev, port_num, tprops);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "ib_query_port failed (%d) for %s port %d\n",
|
||||
ret, dev->ib_dev.name, port_num);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->rate[port_num - 1] = tprops->active_speed *
|
||||
ib_width_enum_to_int(tprops->active_width);
|
||||
|
||||
out:
|
||||
kfree(tprops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void update_sm_ah(struct mthca_dev *dev,
|
||||
u8 port_num, u16 lid, u8 sl)
|
||||
{
|
||||
@ -90,6 +114,7 @@ static void smp_snoop(struct ib_device *ibdev,
|
||||
mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
|
||||
mad->mad_hdr.method == IB_MGMT_METHOD_SET) {
|
||||
if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
|
||||
mthca_update_rate(to_mdev(ibdev), port_num);
|
||||
update_sm_ah(to_mdev(ibdev), port_num,
|
||||
be16_to_cpup((__be16 *) (mad->data + 58)),
|
||||
(*(u8 *) (mad->data + 76)) & 0xf);
|
||||
@ -246,6 +271,7 @@ int mthca_create_agents(struct mthca_dev *dev)
|
||||
{
|
||||
struct ib_mad_agent *agent;
|
||||
int p, q;
|
||||
int ret;
|
||||
|
||||
spin_lock_init(&dev->sm_lock);
|
||||
|
||||
@ -255,11 +281,23 @@ int mthca_create_agents(struct mthca_dev *dev)
|
||||
q ? IB_QPT_GSI : IB_QPT_SMI,
|
||||
NULL, 0, send_handler,
|
||||
NULL, NULL);
|
||||
if (IS_ERR(agent))
|
||||
if (IS_ERR(agent)) {
|
||||
ret = PTR_ERR(agent);
|
||||
goto err;
|
||||
}
|
||||
dev->send_agent[p][q] = agent;
|
||||
}
|
||||
|
||||
|
||||
for (p = 1; p <= dev->limits.num_ports; ++p) {
|
||||
ret = mthca_update_rate(dev, p);
|
||||
if (ret) {
|
||||
mthca_err(dev, "Failed to obtain port %d rate."
|
||||
" aborting.\n", p);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@ -268,7 +306,7 @@ err:
|
||||
if (dev->send_agent[p][q])
|
||||
ib_unregister_mad_agent(dev->send_agent[p][q]);
|
||||
|
||||
return PTR_ERR(agent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __devexit mthca_free_agents(struct mthca_dev *dev)
|
||||
|
@ -52,6 +52,14 @@ MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
|
||||
|
||||
int mthca_debug_level = 0;
|
||||
module_param_named(debug_level, mthca_debug_level, int, 0644);
|
||||
MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
|
||||
|
||||
#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
|
||||
static int msi_x = 0;
|
||||
@ -69,6 +77,10 @@ MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero");
|
||||
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
||||
static int tune_pci = 0;
|
||||
module_param(tune_pci, int, 0444);
|
||||
MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
|
||||
|
||||
static const char mthca_version[] __devinitdata =
|
||||
DRV_NAME ": Mellanox InfiniBand HCA driver v"
|
||||
DRV_VERSION " (" DRV_RELDATE ")\n";
|
||||
@ -90,6 +102,9 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev)
|
||||
int cap;
|
||||
u16 val;
|
||||
|
||||
if (!tune_pci)
|
||||
return 0;
|
||||
|
||||
/* First try to max out Read Byte Count */
|
||||
cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
|
||||
if (cap) {
|
||||
@ -176,6 +191,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
|
||||
mdev->limits.reserved_srqs = dev_lim->reserved_srqs;
|
||||
mdev->limits.reserved_eecs = dev_lim->reserved_eecs;
|
||||
mdev->limits.max_desc_sz = dev_lim->max_desc_sz;
|
||||
mdev->limits.max_srq_sge = mthca_max_srq_sge(mdev);
|
||||
/*
|
||||
* Subtract 1 from the limit because we need to allocate a
|
||||
* spare CQE so the HCA HW can tell the difference between an
|
||||
@ -191,6 +207,18 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
|
||||
mdev->limits.port_width_cap = dev_lim->max_port_width;
|
||||
mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1);
|
||||
mdev->limits.flags = dev_lim->flags;
|
||||
/*
|
||||
* For old FW that doesn't return static rate support, use a
|
||||
* value of 0x3 (only static rate values of 0 or 1 are handled),
|
||||
* except on Sinai, where even old FW can handle static rate
|
||||
* values of 2 and 3.
|
||||
*/
|
||||
if (dev_lim->stat_rate_support)
|
||||
mdev->limits.stat_rate_support = dev_lim->stat_rate_support;
|
||||
else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
|
||||
mdev->limits.stat_rate_support = 0xf;
|
||||
else
|
||||
mdev->limits.stat_rate_support = 0x3;
|
||||
|
||||
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
|
||||
May be doable since hardware supports it for SRQ.
|
||||
|
@ -106,7 +106,7 @@ static int mthca_query_device(struct ib_device *ibdev,
|
||||
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
|
||||
props->max_srq = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
|
||||
props->max_srq_wr = mdev->limits.max_srq_wqes;
|
||||
props->max_srq_sge = mdev->limits.max_sg;
|
||||
props->max_srq_sge = mdev->limits.max_srq_sge;
|
||||
props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay;
|
||||
props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ?
|
||||
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
|
||||
|
@ -257,6 +257,8 @@ struct mthca_qp {
|
||||
atomic_t refcount;
|
||||
u32 qpn;
|
||||
int is_direct;
|
||||
u8 port; /* for SQP and memfree use only */
|
||||
u8 alt_port; /* for memfree use only */
|
||||
u8 transport;
|
||||
u8 state;
|
||||
u8 atomic_rd_en;
|
||||
@ -278,7 +280,6 @@ struct mthca_qp {
|
||||
|
||||
struct mthca_sqp {
|
||||
struct mthca_qp qp;
|
||||
int port;
|
||||
int pkey_index;
|
||||
u32 qkey;
|
||||
u32 send_psn;
|
||||
|
@ -248,6 +248,9 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event_type == IB_EVENT_PATH_MIG)
|
||||
qp->port = qp->alt_port;
|
||||
|
||||
event.device = &dev->ib_dev;
|
||||
event.event = event_type;
|
||||
event.element.qp = &qp->ibqp;
|
||||
@ -392,10 +395,16 @@ static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr,
|
||||
{
|
||||
memset(ib_ah_attr, 0, sizeof *path);
|
||||
ib_ah_attr->port_num = (be32_to_cpu(path->port_pkey) >> 24) & 0x3;
|
||||
|
||||
if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->limits.num_ports)
|
||||
return;
|
||||
|
||||
ib_ah_attr->dlid = be16_to_cpu(path->rlid);
|
||||
ib_ah_attr->sl = be32_to_cpu(path->sl_tclass_flowlabel) >> 28;
|
||||
ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f;
|
||||
ib_ah_attr->static_rate = path->static_rate & 0x7;
|
||||
ib_ah_attr->static_rate = mthca_rate_to_ib(dev,
|
||||
path->static_rate & 0x7,
|
||||
ib_ah_attr->port_num);
|
||||
ib_ah_attr->ah_flags = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
|
||||
if (ib_ah_attr->ah_flags) {
|
||||
ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1);
|
||||
@ -455,8 +464,10 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
|
||||
qp_attr->cap.max_recv_sge = qp->rq.max_gs;
|
||||
qp_attr->cap.max_inline_data = qp->max_inline_data;
|
||||
|
||||
to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
|
||||
to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
|
||||
if (qp->transport == RC || qp->transport == UC) {
|
||||
to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
|
||||
to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
|
||||
}
|
||||
|
||||
qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f;
|
||||
qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f;
|
||||
@ -484,11 +495,11 @@ out:
|
||||
}
|
||||
|
||||
static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
|
||||
struct mthca_qp_path *path)
|
||||
struct mthca_qp_path *path, u8 port)
|
||||
{
|
||||
path->g_mylmc = ah->src_path_bits & 0x7f;
|
||||
path->rlid = cpu_to_be16(ah->dlid);
|
||||
path->static_rate = !!ah->static_rate;
|
||||
path->static_rate = mthca_get_rate(dev, ah->static_rate, port);
|
||||
|
||||
if (ah->ah_flags & IB_AH_GRH) {
|
||||
if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
|
||||
@ -634,7 +645,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
|
||||
|
||||
if (qp->transport == MLX)
|
||||
qp_context->pri_path.port_pkey |=
|
||||
cpu_to_be32(to_msqp(qp)->port << 24);
|
||||
cpu_to_be32(qp->port << 24);
|
||||
else {
|
||||
if (attr_mask & IB_QP_PORT) {
|
||||
qp_context->pri_path.port_pkey |=
|
||||
@ -657,7 +668,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_AV) {
|
||||
if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path))
|
||||
if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
|
||||
attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
|
||||
return -EINVAL;
|
||||
|
||||
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
|
||||
@ -681,7 +693,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path))
|
||||
if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
|
||||
attr->alt_ah_attr.port_num))
|
||||
return -EINVAL;
|
||||
|
||||
qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
|
||||
@ -791,6 +804,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
|
||||
qp->atomic_rd_en = attr->qp_access_flags;
|
||||
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
|
||||
qp->resp_depth = attr->max_dest_rd_atomic;
|
||||
if (attr_mask & IB_QP_PORT)
|
||||
qp->port = attr->port_num;
|
||||
if (attr_mask & IB_QP_ALT_PATH)
|
||||
qp->alt_port = attr->alt_port_num;
|
||||
|
||||
if (is_sqp(dev, qp))
|
||||
store_attrs(to_msqp(qp), attr, attr_mask);
|
||||
@ -802,13 +819,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
|
||||
if (is_qp0(dev, qp)) {
|
||||
if (cur_state != IB_QPS_RTR &&
|
||||
new_state == IB_QPS_RTR)
|
||||
init_port(dev, to_msqp(qp)->port);
|
||||
init_port(dev, qp->port);
|
||||
|
||||
if (cur_state != IB_QPS_RESET &&
|
||||
cur_state != IB_QPS_ERR &&
|
||||
(new_state == IB_QPS_RESET ||
|
||||
new_state == IB_QPS_ERR))
|
||||
mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
|
||||
mthca_CLOSE_IB(dev, qp->port, &status);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1212,6 +1229,9 @@ int mthca_alloc_qp(struct mthca_dev *dev,
|
||||
if (qp->qpn == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
/* initialize port to zero for error-catching. */
|
||||
qp->port = 0;
|
||||
|
||||
err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
|
||||
send_policy, qp);
|
||||
if (err) {
|
||||
@ -1261,7 +1281,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
sqp->port = port;
|
||||
sqp->qp.port = port;
|
||||
sqp->qp.qpn = mqpn;
|
||||
sqp->qp.transport = MLX;
|
||||
|
||||
@ -1404,10 +1424,10 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
|
||||
sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
|
||||
sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
|
||||
if (!sqp->qp.ibqp.qp_num)
|
||||
ib_get_cached_pkey(&dev->ib_dev, sqp->port,
|
||||
ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
|
||||
sqp->pkey_index, &pkey);
|
||||
else
|
||||
ib_get_cached_pkey(&dev->ib_dev, sqp->port,
|
||||
ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
|
||||
wr->wr.ud.pkey_index, &pkey);
|
||||
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
|
||||
sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
|
||||
|
@ -192,7 +192,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
|
||||
|
||||
/* Sanity check SRQ size before proceeding */
|
||||
if (attr->max_wr > dev->limits.max_srq_wqes ||
|
||||
attr->max_sge > dev->limits.max_sg)
|
||||
attr->max_sge > dev->limits.max_srq_sge)
|
||||
return -EINVAL;
|
||||
|
||||
srq->max = attr->max_wr;
|
||||
@ -660,6 +660,31 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
|
||||
return err;
|
||||
}
|
||||
|
||||
int mthca_max_srq_sge(struct mthca_dev *dev)
|
||||
{
|
||||
if (mthca_is_memfree(dev))
|
||||
return dev->limits.max_sg;
|
||||
|
||||
/*
|
||||
* SRQ allocations are based on powers of 2 for Tavor,
|
||||
* (although they only need to be multiples of 16 bytes).
|
||||
*
|
||||
* Therefore, we need to base the max number of sg entries on
|
||||
* the largest power of 2 descriptor size that is <= to the
|
||||
* actual max WQE descriptor size, rather than return the
|
||||
* max_sg value given by the firmware (which is based on WQE
|
||||
* sizes as multiples of 16, not powers of 2).
|
||||
*
|
||||
* If SRQ implementation is changed for Tavor to be based on
|
||||
* multiples of 16, the calculation below can be deleted and
|
||||
* the FW max_sg value returned.
|
||||
*/
|
||||
return min_t(int, dev->limits.max_sg,
|
||||
((1 << (fls(dev->limits.max_desc_sz) - 1)) -
|
||||
sizeof (struct mthca_next_seg)) /
|
||||
sizeof (struct mthca_data_seg));
|
||||
}
|
||||
|
||||
int __devinit mthca_init_srq_table(struct mthca_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
@ -10,8 +10,9 @@ config INFINIBAND_IPOIB
|
||||
group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
|
||||
|
||||
config INFINIBAND_IPOIB_DEBUG
|
||||
bool "IP-over-InfiniBand debugging"
|
||||
bool "IP-over-InfiniBand debugging" if EMBEDDED
|
||||
depends on INFINIBAND_IPOIB
|
||||
default y
|
||||
---help---
|
||||
This option causes debugging code to be compiled into the
|
||||
IPoIB driver. The output can be turned on via the
|
||||
|
@ -65,6 +65,8 @@ enum {
|
||||
|
||||
IPOIB_RX_RING_SIZE = 128,
|
||||
IPOIB_TX_RING_SIZE = 64,
|
||||
IPOIB_MAX_QUEUE_SIZE = 8192,
|
||||
IPOIB_MIN_QUEUE_SIZE = 2,
|
||||
|
||||
IPOIB_NUM_WC = 4,
|
||||
|
||||
@ -230,6 +232,9 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
|
||||
INFINIBAND_ALEN, sizeof(void *));
|
||||
}
|
||||
|
||||
struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
|
||||
void ipoib_neigh_free(struct ipoib_neigh *neigh);
|
||||
|
||||
extern struct workqueue_struct *ipoib_workqueue;
|
||||
|
||||
/* functions */
|
||||
@ -329,6 +334,8 @@ static inline void ipoib_unregister_debugfs(void) { }
|
||||
#define ipoib_warn(priv, format, arg...) \
|
||||
ipoib_printk(KERN_WARNING, priv, format , ## arg)
|
||||
|
||||
extern int ipoib_sendq_size;
|
||||
extern int ipoib_recvq_size;
|
||||
|
||||
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
|
||||
extern int ipoib_debug_level;
|
||||
|
@ -213,7 +213,7 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
|
||||
gid_buf, path.pathrec.dlid ? "yes" : "no");
|
||||
|
||||
if (path.pathrec.dlid) {
|
||||
rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
|
||||
rate = ib_rate_to_mult(path.pathrec.rate) * 25;
|
||||
|
||||
seq_printf(file,
|
||||
" DLID: 0x%04x\n"
|
||||
|
@ -161,7 +161,7 @@ static int ipoib_ib_post_receives(struct net_device *dev)
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
|
||||
for (i = 0; i < ipoib_recvq_size; ++i) {
|
||||
if (ipoib_alloc_rx_skb(dev, i)) {
|
||||
ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
|
||||
return -ENOMEM;
|
||||
@ -187,7 +187,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
|
||||
if (wr_id & IPOIB_OP_RECV) {
|
||||
wr_id &= ~IPOIB_OP_RECV;
|
||||
|
||||
if (wr_id < IPOIB_RX_RING_SIZE) {
|
||||
if (wr_id < ipoib_recvq_size) {
|
||||
struct sk_buff *skb = priv->rx_ring[wr_id].skb;
|
||||
dma_addr_t addr = priv->rx_ring[wr_id].mapping;
|
||||
|
||||
@ -252,9 +252,9 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
|
||||
struct ipoib_tx_buf *tx_req;
|
||||
unsigned long flags;
|
||||
|
||||
if (wr_id >= IPOIB_TX_RING_SIZE) {
|
||||
if (wr_id >= ipoib_sendq_size) {
|
||||
ipoib_warn(priv, "completion event with wrid %d (> %d)\n",
|
||||
wr_id, IPOIB_TX_RING_SIZE);
|
||||
wr_id, ipoib_sendq_size);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
++priv->tx_tail;
|
||||
if (netif_queue_stopped(dev) &&
|
||||
priv->tx_head - priv->tx_tail <= IPOIB_TX_RING_SIZE / 2)
|
||||
priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
|
||||
netif_wake_queue(dev);
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
|
||||
@ -344,13 +344,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
|
||||
* means we have to make sure everything is properly recorded and
|
||||
* our state is consistent before we call post_send().
|
||||
*/
|
||||
tx_req = &priv->tx_ring[priv->tx_head & (IPOIB_TX_RING_SIZE - 1)];
|
||||
tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)];
|
||||
tx_req->skb = skb;
|
||||
addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
pci_unmap_addr_set(tx_req, mapping, addr);
|
||||
|
||||
if (unlikely(post_send(priv, priv->tx_head & (IPOIB_TX_RING_SIZE - 1),
|
||||
if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
|
||||
address->ah, qpn, addr, skb->len))) {
|
||||
ipoib_warn(priv, "post_send failed\n");
|
||||
++priv->stats.tx_errors;
|
||||
@ -363,7 +363,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
|
||||
address->last_send = priv->tx_head;
|
||||
++priv->tx_head;
|
||||
|
||||
if (priv->tx_head - priv->tx_tail == IPOIB_TX_RING_SIZE) {
|
||||
if (priv->tx_head - priv->tx_tail == ipoib_sendq_size) {
|
||||
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
@ -488,7 +488,7 @@ static int recvs_pending(struct net_device *dev)
|
||||
int pending = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
|
||||
for (i = 0; i < ipoib_recvq_size; ++i)
|
||||
if (priv->rx_ring[i].skb)
|
||||
++pending;
|
||||
|
||||
@ -527,7 +527,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
|
||||
*/
|
||||
while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
|
||||
tx_req = &priv->tx_ring[priv->tx_tail &
|
||||
(IPOIB_TX_RING_SIZE - 1)];
|
||||
(ipoib_sendq_size - 1)];
|
||||
dma_unmap_single(priv->ca->dma_device,
|
||||
pci_unmap_addr(tx_req, mapping),
|
||||
tx_req->skb->len,
|
||||
@ -536,7 +536,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
|
||||
++priv->tx_tail;
|
||||
}
|
||||
|
||||
for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
|
||||
for (i = 0; i < ipoib_recvq_size; ++i)
|
||||
if (priv->rx_ring[i].skb) {
|
||||
dma_unmap_single(priv->ca->dma_device,
|
||||
pci_unmap_addr(&priv->rx_ring[i],
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <linux/if_arp.h> /* For ARPHRD_xxx */
|
||||
|
||||
@ -53,6 +54,14 @@ MODULE_AUTHOR("Roland Dreier");
|
||||
MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE;
|
||||
int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE;
|
||||
|
||||
module_param_named(send_queue_size, ipoib_sendq_size, int, 0444);
|
||||
MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue");
|
||||
module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
|
||||
MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");
|
||||
|
||||
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
|
||||
int ipoib_debug_level;
|
||||
|
||||
@ -252,8 +261,8 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
|
||||
*/
|
||||
if (neigh->ah)
|
||||
ipoib_put_ah(neigh->ah);
|
||||
*to_ipoib_neigh(neigh->neighbour) = NULL;
|
||||
kfree(neigh);
|
||||
|
||||
ipoib_neigh_free(neigh);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@ -327,9 +336,8 @@ void ipoib_flush_paths(struct net_device *dev)
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
struct ipoib_path *path, *tp;
|
||||
LIST_HEAD(remove_list);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
spin_lock_irq(&priv->lock);
|
||||
|
||||
list_splice(&priv->path_list, &remove_list);
|
||||
INIT_LIST_HEAD(&priv->path_list);
|
||||
@ -337,14 +345,15 @@ void ipoib_flush_paths(struct net_device *dev)
|
||||
list_for_each_entry(path, &remove_list, list)
|
||||
rb_erase(&path->rb_node, &priv->path_tree);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
list_for_each_entry_safe(path, tp, &remove_list, list) {
|
||||
if (path->query)
|
||||
ib_sa_cancel_query(path->query_id, path->query);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
wait_for_completion(&path->done);
|
||||
path_free(dev, path);
|
||||
spin_lock_irq(&priv->lock);
|
||||
}
|
||||
spin_unlock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
static void path_rec_completion(int status,
|
||||
@ -373,16 +382,9 @@ static void path_rec_completion(int status,
|
||||
struct ib_ah_attr av = {
|
||||
.dlid = be16_to_cpu(pathrec->dlid),
|
||||
.sl = pathrec->sl,
|
||||
.port_num = priv->port
|
||||
.port_num = priv->port,
|
||||
.static_rate = pathrec->rate
|
||||
};
|
||||
int path_rate = ib_sa_rate_enum_to_int(pathrec->rate);
|
||||
|
||||
if (path_rate > 0 && priv->local_rate > path_rate)
|
||||
av.static_rate = (priv->local_rate - 1) / path_rate;
|
||||
|
||||
ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n",
|
||||
av.static_rate, priv->local_rate,
|
||||
ib_sa_rate_enum_to_int(pathrec->rate));
|
||||
|
||||
ah = ipoib_create_ah(dev, priv->pd, &av);
|
||||
}
|
||||
@ -481,7 +483,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
|
||||
struct ipoib_path *path;
|
||||
struct ipoib_neigh *neigh;
|
||||
|
||||
neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
|
||||
neigh = ipoib_neigh_alloc(skb->dst->neighbour);
|
||||
if (!neigh) {
|
||||
++priv->stats.tx_dropped;
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -489,8 +491,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
skb_queue_head_init(&neigh->queue);
|
||||
neigh->neighbour = skb->dst->neighbour;
|
||||
*to_ipoib_neigh(skb->dst->neighbour) = neigh;
|
||||
|
||||
/*
|
||||
* We can only be called from ipoib_start_xmit, so we're
|
||||
@ -503,7 +503,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
|
||||
path = path_rec_create(dev,
|
||||
(union ib_gid *) (skb->dst->neighbour->ha + 4));
|
||||
if (!path)
|
||||
goto err;
|
||||
goto err_path;
|
||||
|
||||
__path_add(dev, path);
|
||||
}
|
||||
@ -521,17 +521,17 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
|
||||
__skb_queue_tail(&neigh->queue, skb);
|
||||
|
||||
if (!path->query && path_rec_start(dev, path))
|
||||
goto err;
|
||||
goto err_list;
|
||||
}
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
return;
|
||||
|
||||
err:
|
||||
*to_ipoib_neigh(skb->dst->neighbour) = NULL;
|
||||
err_list:
|
||||
list_del(&neigh->list);
|
||||
kfree(neigh);
|
||||
|
||||
err_path:
|
||||
ipoib_neigh_free(neigh);
|
||||
++priv->stats.tx_dropped;
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
@ -763,8 +763,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
|
||||
if (neigh->ah)
|
||||
ah = neigh->ah;
|
||||
list_del(&neigh->list);
|
||||
*to_ipoib_neigh(n) = NULL;
|
||||
kfree(neigh);
|
||||
ipoib_neigh_free(neigh);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@ -773,6 +772,26 @@ static void ipoib_neigh_destructor(struct neighbour *n)
|
||||
ipoib_put_ah(ah);
|
||||
}
|
||||
|
||||
struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
|
||||
{
|
||||
struct ipoib_neigh *neigh;
|
||||
|
||||
neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
|
||||
if (!neigh)
|
||||
return NULL;
|
||||
|
||||
neigh->neighbour = neighbour;
|
||||
*to_ipoib_neigh(neighbour) = neigh;
|
||||
|
||||
return neigh;
|
||||
}
|
||||
|
||||
void ipoib_neigh_free(struct ipoib_neigh *neigh)
|
||||
{
|
||||
*to_ipoib_neigh(neigh->neighbour) = NULL;
|
||||
kfree(neigh);
|
||||
}
|
||||
|
||||
static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
|
||||
{
|
||||
parms->neigh_destructor = ipoib_neigh_destructor;
|
||||
@ -785,20 +804,19 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* Allocate RX/TX "rings" to hold queued skbs */
|
||||
|
||||
priv->rx_ring = kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
|
||||
priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
|
||||
GFP_KERNEL);
|
||||
if (!priv->rx_ring) {
|
||||
printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
|
||||
ca->name, IPOIB_RX_RING_SIZE);
|
||||
ca->name, ipoib_recvq_size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
|
||||
priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring,
|
||||
GFP_KERNEL);
|
||||
if (!priv->tx_ring) {
|
||||
printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
|
||||
ca->name, IPOIB_TX_RING_SIZE);
|
||||
ca->name, ipoib_sendq_size);
|
||||
goto out_rx_ring_cleanup;
|
||||
}
|
||||
|
||||
@ -866,7 +884,7 @@ static void ipoib_setup(struct net_device *dev)
|
||||
dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
|
||||
dev->addr_len = INFINIBAND_ALEN;
|
||||
dev->type = ARPHRD_INFINIBAND;
|
||||
dev->tx_queue_len = IPOIB_TX_RING_SIZE * 2;
|
||||
dev->tx_queue_len = ipoib_sendq_size * 2;
|
||||
dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
|
||||
|
||||
/* MTU will be reset when mcast join happens */
|
||||
@ -1118,6 +1136,14 @@ static int __init ipoib_init_module(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size);
|
||||
ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE);
|
||||
ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE);
|
||||
|
||||
ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
|
||||
ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
|
||||
ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
|
||||
|
||||
ret = ipoib_register_debugfs();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -114,8 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
|
||||
*/
|
||||
if (neigh->ah)
|
||||
ipoib_put_ah(neigh->ah);
|
||||
*to_ipoib_neigh(neigh->neighbour) = NULL;
|
||||
kfree(neigh);
|
||||
ipoib_neigh_free(neigh);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@ -251,6 +250,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
|
||||
.port_num = priv->port,
|
||||
.sl = mcast->mcmember.sl,
|
||||
.ah_flags = IB_AH_GRH,
|
||||
.static_rate = mcast->mcmember.rate,
|
||||
.grh = {
|
||||
.flow_label = be32_to_cpu(mcast->mcmember.flow_label),
|
||||
.hop_limit = mcast->mcmember.hop_limit,
|
||||
@ -258,17 +258,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
|
||||
.traffic_class = mcast->mcmember.traffic_class
|
||||
}
|
||||
};
|
||||
int path_rate = ib_sa_rate_enum_to_int(mcast->mcmember.rate);
|
||||
|
||||
av.grh.dgid = mcast->mcmember.mgid;
|
||||
|
||||
if (path_rate > 0 && priv->local_rate > path_rate)
|
||||
av.static_rate = (priv->local_rate - 1) / path_rate;
|
||||
|
||||
ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n",
|
||||
av.static_rate, priv->local_rate,
|
||||
ib_sa_rate_enum_to_int(mcast->mcmember.rate));
|
||||
|
||||
ah = ipoib_create_ah(dev, priv->pd, &av);
|
||||
if (!ah) {
|
||||
ipoib_warn(priv, "ib_address_create failed\n");
|
||||
@ -618,6 +609,22 @@ int ipoib_mcast_start_thread(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
|
||||
struct ipoib_mcast *mcast)
|
||||
{
|
||||
spin_lock_irq(&priv->lock);
|
||||
if (mcast && mcast->query) {
|
||||
ib_sa_cancel_query(mcast->query_id, mcast->query);
|
||||
mcast->query = NULL;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
|
||||
IPOIB_GID_ARG(mcast->mcmember.mgid));
|
||||
wait_for_completion(&mcast->done);
|
||||
}
|
||||
else
|
||||
spin_unlock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
@ -637,28 +644,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
|
||||
if (flush)
|
||||
flush_workqueue(ipoib_workqueue);
|
||||
|
||||
spin_lock_irq(&priv->lock);
|
||||
if (priv->broadcast && priv->broadcast->query) {
|
||||
ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
|
||||
priv->broadcast->query = NULL;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
ipoib_dbg_mcast(priv, "waiting for bcast\n");
|
||||
wait_for_completion(&priv->broadcast->done);
|
||||
} else
|
||||
spin_unlock_irq(&priv->lock);
|
||||
wait_for_mcast_join(priv, priv->broadcast);
|
||||
|
||||
list_for_each_entry(mcast, &priv->multicast_list, list) {
|
||||
spin_lock_irq(&priv->lock);
|
||||
if (mcast->query) {
|
||||
ib_sa_cancel_query(mcast->query_id, mcast->query);
|
||||
mcast->query = NULL;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
|
||||
IPOIB_GID_ARG(mcast->mcmember.mgid));
|
||||
wait_for_completion(&mcast->done);
|
||||
} else
|
||||
spin_unlock_irq(&priv->lock);
|
||||
}
|
||||
list_for_each_entry(mcast, &priv->multicast_list, list)
|
||||
wait_for_mcast_join(priv, mcast);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -772,13 +761,11 @@ out:
|
||||
if (skb->dst &&
|
||||
skb->dst->neighbour &&
|
||||
!*to_ipoib_neigh(skb->dst->neighbour)) {
|
||||
struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
|
||||
struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
|
||||
|
||||
if (neigh) {
|
||||
kref_get(&mcast->ah->ref);
|
||||
neigh->ah = mcast->ah;
|
||||
neigh->neighbour = skb->dst->neighbour;
|
||||
*to_ipoib_neigh(skb->dst->neighbour) = neigh;
|
||||
list_add_tail(&neigh->list, &mcast->neigh_list);
|
||||
}
|
||||
}
|
||||
@ -913,6 +900,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
|
||||
|
||||
/* We have to cancel outside of the spinlock */
|
||||
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
|
||||
wait_for_mcast_join(priv, mcast);
|
||||
ipoib_mcast_leave(mcast->dev, mcast);
|
||||
ipoib_mcast_free(mcast);
|
||||
}
|
||||
|
@ -159,8 +159,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
struct ib_qp_init_attr init_attr = {
|
||||
.cap = {
|
||||
.max_send_wr = IPOIB_TX_RING_SIZE,
|
||||
.max_recv_wr = IPOIB_RX_RING_SIZE,
|
||||
.max_send_wr = ipoib_sendq_size,
|
||||
.max_recv_wr = ipoib_recvq_size,
|
||||
.max_send_sge = 1,
|
||||
.max_recv_sge = 1
|
||||
},
|
||||
@ -175,7 +175,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
|
||||
}
|
||||
|
||||
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
|
||||
IPOIB_TX_RING_SIZE + IPOIB_RX_RING_SIZE + 1);
|
||||
ipoib_sendq_size + ipoib_recvq_size + 1);
|
||||
if (IS_ERR(priv->cq)) {
|
||||
printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
|
||||
goto out_free_pd;
|
||||
|
@ -1434,6 +1434,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
|
||||
p = match_strdup(args);
|
||||
if (strlen(p) != 32) {
|
||||
printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
|
||||
kfree(p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ isdn_ppp_free(isdn_net_local * lp)
|
||||
{
|
||||
struct ippp_struct *is;
|
||||
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
|
||||
__FUNCTION__, lp->ppp_slot);
|
||||
return 0;
|
||||
@ -126,7 +126,7 @@ isdn_ppp_free(isdn_net_local * lp)
|
||||
lp->netdev->pb->ref_ct--;
|
||||
spin_unlock(&lp->netdev->pb->lock);
|
||||
#endif /* CONFIG_ISDN_MPP */
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
|
||||
__FUNCTION__, lp->ppp_slot);
|
||||
return 0;
|
||||
@ -279,7 +279,7 @@ isdn_ppp_open(int min, struct file *file)
|
||||
int slot;
|
||||
struct ippp_struct *is;
|
||||
|
||||
if (min < 0 || min > ISDN_MAX_CHANNELS)
|
||||
if (min < 0 || min >= ISDN_MAX_CHANNELS)
|
||||
return -ENODEV;
|
||||
|
||||
slot = isdn_ppp_get_slot();
|
||||
@ -1042,7 +1042,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
|
||||
if (lp->master) { // FIXME?
|
||||
mlp = (isdn_net_local *) lp->master->priv;
|
||||
slot = mlp->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
|
||||
lp->ppp_slot);
|
||||
goto drop_packet;
|
||||
@ -1264,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
/* we have our lp locked from now on */
|
||||
|
||||
slot = lp->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
|
||||
lp->ppp_slot);
|
||||
kfree_skb(skb);
|
||||
@ -1603,7 +1603,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
|
||||
mp = net_dev->pb;
|
||||
stats = &mp->stats;
|
||||
slot = lp->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
|
||||
__FUNCTION__, lp->ppp_slot);
|
||||
stats->frame_drops++;
|
||||
@ -1640,7 +1640,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
|
||||
is->last_link_seqno = minseq = newseq;
|
||||
for (lpq = net_dev->queue;;) {
|
||||
slot = lpq->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
|
||||
__FUNCTION__, lpq->ppp_slot);
|
||||
} else {
|
||||
@ -2648,7 +2648,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
|
||||
|
||||
printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
|
||||
lp->ppp_slot);
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
|
||||
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
|
||||
__FUNCTION__, lp->ppp_slot);
|
||||
return;
|
||||
@ -2658,7 +2658,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
|
||||
|
||||
if(lp->master) {
|
||||
int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: slot(%d) out of range\n",
|
||||
__FUNCTION__, slot);
|
||||
return;
|
||||
@ -2845,7 +2845,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
|
||||
|
||||
if (lp->master) {
|
||||
slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
|
||||
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
|
||||
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
|
||||
printk(KERN_ERR "%s: slot(%d) out of range\n",
|
||||
__FUNCTION__, slot);
|
||||
return;
|
||||
|
@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev)
|
||||
{
|
||||
atomic_inc(&md_event_count);
|
||||
wake_up(&md_event_waiters);
|
||||
sysfs_notify(&mddev->kobj, NULL, "sync_action");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(md_new_event);
|
||||
|
||||
|
@ -366,7 +366,15 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
|
||||
static int
|
||||
mptsas_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
sas_read_port_mode_page(sdev);
|
||||
struct Scsi_Host *host = sdev->host;
|
||||
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
* Ignore sending sas mode pages in that case..
|
||||
*/
|
||||
if (sdev->channel < hd->ioc->num_ports)
|
||||
sas_read_port_mode_page(sdev);
|
||||
|
||||
return mptscsih_slave_configure(sdev);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
|
||||
* Copyright (C) 2006 Broadcom Corporation.
|
||||
*
|
||||
* Distribute under GPL.
|
||||
*/
|
||||
@ -28,8 +29,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "b44"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "0.97"
|
||||
#define DRV_MODULE_RELDATE "Nov 30, 2005"
|
||||
#define DRV_MODULE_VERSION "1.00"
|
||||
#define DRV_MODULE_RELDATE "Apr 7, 2006"
|
||||
|
||||
#define B44_DEF_MSG_ENABLE \
|
||||
(NETIF_MSG_DRV | \
|
||||
@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
||||
return readl(bp->regs + reg);
|
||||
}
|
||||
|
||||
static inline void bw32(const struct b44 *bp,
|
||||
static inline void bw32(const struct b44 *bp,
|
||||
unsigned long reg, unsigned long val)
|
||||
{
|
||||
writel(val, bp->regs + reg);
|
||||
@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
|
||||
val |= ((u32) data[4]) << 8;
|
||||
val |= ((u32) data[5]) << 0;
|
||||
bw32(bp, B44_CAM_DATA_LO, val);
|
||||
val = (CAM_DATA_HI_VALID |
|
||||
val = (CAM_DATA_HI_VALID |
|
||||
(((u32) data[0]) << 8) |
|
||||
(((u32) data[1]) << 0));
|
||||
bw32(bp, B44_CAM_DATA_HI, val);
|
||||
bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
|
||||
(index << CAM_CTRL_INDEX_SHIFT)));
|
||||
b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
|
||||
b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
|
||||
}
|
||||
|
||||
static inline void __b44_disable_ints(struct b44 *bp)
|
||||
@ -410,25 +411,18 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
|
||||
|
||||
static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
|
||||
{
|
||||
u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE |
|
||||
B44_FLAG_RX_PAUSE);
|
||||
u32 pause_enab = 0;
|
||||
|
||||
if (local & ADVERTISE_PAUSE_CAP) {
|
||||
if (local & ADVERTISE_PAUSE_ASYM) {
|
||||
if (remote & LPA_PAUSE_CAP)
|
||||
pause_enab |= (B44_FLAG_TX_PAUSE |
|
||||
B44_FLAG_RX_PAUSE);
|
||||
else if (remote & LPA_PAUSE_ASYM)
|
||||
pause_enab |= B44_FLAG_RX_PAUSE;
|
||||
} else {
|
||||
if (remote & LPA_PAUSE_CAP)
|
||||
pause_enab |= (B44_FLAG_TX_PAUSE |
|
||||
B44_FLAG_RX_PAUSE);
|
||||
}
|
||||
} else if (local & ADVERTISE_PAUSE_ASYM) {
|
||||
if ((remote & LPA_PAUSE_CAP) &&
|
||||
(remote & LPA_PAUSE_ASYM))
|
||||
pause_enab |= B44_FLAG_TX_PAUSE;
|
||||
/* The driver supports only rx pause by default because
|
||||
the b44 mac tx pause mechanism generates excessive
|
||||
pause frames.
|
||||
Use ethtool to turn on b44 tx pause if necessary.
|
||||
*/
|
||||
if ((local & ADVERTISE_PAUSE_CAP) &&
|
||||
(local & ADVERTISE_PAUSE_ASYM)){
|
||||
if ((remote & LPA_PAUSE_ASYM) &&
|
||||
!(remote & LPA_PAUSE_CAP))
|
||||
pause_enab |= B44_FLAG_RX_PAUSE;
|
||||
}
|
||||
|
||||
__b44_set_flow_ctrl(bp, pause_enab);
|
||||
@ -1063,7 +1057,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
b44_enable_ints(bp);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1381,7 +1375,7 @@ static void b44_init_hw(struct b44 *bp)
|
||||
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
|
||||
|
||||
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
|
||||
bp->rx_prod = bp->rx_pending;
|
||||
bp->rx_prod = bp->rx_pending;
|
||||
|
||||
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
|
||||
|
||||
@ -1553,9 +1547,9 @@ static void __b44_set_rx_mode(struct net_device *dev)
|
||||
val |= RXCONFIG_ALLMULTI;
|
||||
else
|
||||
i = __b44_load_mcast(bp, dev);
|
||||
|
||||
|
||||
for (; i < 64; i++) {
|
||||
__b44_cam_write(bp, zero, i);
|
||||
__b44_cam_write(bp, zero, i);
|
||||
}
|
||||
bw32(bp, B44_RXCONFIG, val);
|
||||
val = br32(bp, B44_CAM_CTRL);
|
||||
@ -1737,7 +1731,7 @@ static int b44_set_ringparam(struct net_device *dev,
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
b44_enable_ints(bp);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1782,7 +1776,7 @@ static int b44_set_pauseparam(struct net_device *dev,
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
b44_enable_ints(bp);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1898,7 +1892,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
|
||||
bp->core_unit = ssb_core_unit(bp);
|
||||
bp->dma_offset = SB_PCI_DMA;
|
||||
|
||||
/* XXX - really required?
|
||||
/* XXX - really required?
|
||||
bp->flags |= B44_FLAG_BUGGY_TXPTR;
|
||||
*/
|
||||
out:
|
||||
@ -1946,7 +1940,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
||||
"aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
||||
|
||||
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "No usable DMA configuration, "
|
||||
@ -2041,9 +2035,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
||||
|
||||
pci_save_state(bp->pdev);
|
||||
|
||||
/* Chip reset provides power to the b44 MAC & PCI cores, which
|
||||
/* Chip reset provides power to the b44 MAC & PCI cores, which
|
||||
* is necessary for MAC register access.
|
||||
*/
|
||||
*/
|
||||
b44_chip_reset(bp);
|
||||
|
||||
printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
|
||||
@ -2091,10 +2085,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
del_timer_sync(&bp->timer);
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
spin_lock_irq(&bp->lock);
|
||||
|
||||
b44_halt(bp);
|
||||
netif_carrier_off(bp->dev);
|
||||
netif_carrier_off(bp->dev);
|
||||
netif_device_detach(bp->dev);
|
||||
b44_free_rings(bp);
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
/* Time in jiffies before concluding the transmitter is hung. */
|
||||
#define TX_TIMEOUT (5*HZ)
|
||||
|
||||
static char version[] __devinitdata =
|
||||
static const char version[] __devinitdata =
|
||||
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
||||
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
|
||||
|
@ -1,177 +0,0 @@
|
||||
/* $Linux: hydra.h,v 1.0 1994/10/26 02:03:47 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Timo Rossi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Timo Rossi
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The Hydra Systems card uses the National Semiconductor
|
||||
* 8390 NIC (Network Interface Controller) chip, located
|
||||
* at card base address + 0xffe1. NIC registers are accessible
|
||||
* only at odd byte addresses, so the register offsets must
|
||||
* be multiplied by two.
|
||||
*
|
||||
* Card address PROM is located at card base + 0xffc0 (even byte addresses)
|
||||
*
|
||||
* RAM starts at the card base address, and is 16K or 64K.
|
||||
* The current Amiga NetBSD hydra driver is hardwired for 16K.
|
||||
* It seems that the RAM should be accessed as words or longwords only.
|
||||
*
|
||||
*/
|
||||
|
||||
/* adapted for Linux by Topi Kanerva 03/29/95
|
||||
with original author's permission */
|
||||
|
||||
#define HYDRA_NIC_BASE 0xffe1
|
||||
|
||||
/* Page0 registers */
|
||||
|
||||
#define NIC_CR 0 /* Command register */
|
||||
#define NIC_PSTART (1*2) /* Page start (write) */
|
||||
#define NIC_PSTOP (2*2) /* Page stop (write) */
|
||||
#define NIC_BNDRY (3*2) /* Boundary pointer */
|
||||
#define NIC_TSR (4*2) /* Transmit status (read) */
|
||||
#define NIC_TPSR (4*2) /* Transmit page start (write) */
|
||||
#define NIC_NCR (5*2) /* Number of collisions, read */
|
||||
#define NIC_TBCR0 (5*2) /* Transmit byte count low (write) */
|
||||
#define NIC_FIFO (6*2) /* FIFO reg. (read) */
|
||||
#define NIC_TBCR1 (6*2) /* Transmit byte count high (write) */
|
||||
#define NIC_ISR (7*2) /* Interrupt status register */
|
||||
#define NIC_RBCR0 (0xa*2) /* Remote byte count low (write) */
|
||||
#define NIC_RBCR1 (0xb*2) /* Remote byte count high (write) */
|
||||
#define NIC_RSR (0xc*2) /* Receive status (read) */
|
||||
#define NIC_RCR (0xc*2) /* Receive config (write) */
|
||||
#define NIC_CNTR0 (0xd*2) /* Frame alignment error count (read) */
|
||||
#define NIC_TCR (0xd*2) /* Transmit config (write) */
|
||||
#define NIC_CNTR1 (0xe*2) /* CRC error counter (read) */
|
||||
#define NIC_DCR (0xe*2) /* Data config (write) */
|
||||
#define NIC_CNTR2 (0xf*2) /* missed packet counter (read) */
|
||||
#define NIC_IMR (0xf*2) /* Interrupt mask reg. (write) */
|
||||
|
||||
/* Page1 registers */
|
||||
|
||||
#define NIC_PAR0 (1*2) /* Physical address */
|
||||
#define NIC_PAR1 (2*2)
|
||||
#define NIC_PAR2 (3*2)
|
||||
#define NIC_PAR3 (4*2)
|
||||
#define NIC_PAR4 (5*2)
|
||||
#define NIC_PAR5 (6*2)
|
||||
#define NIC_CURR (7*2) /* Current RX ring-buffer page */
|
||||
#define NIC_MAR0 (8*2) /* Multicast address */
|
||||
#define NIC_MAR1 (9*2)
|
||||
#define NIC_MAR2 (0xa*2)
|
||||
#define NIC_MAR3 (0xb*2)
|
||||
#define NIC_MAR4 (0xc*2)
|
||||
#define NIC_MAR5 (0xd*2)
|
||||
#define NIC_MAR6 (0xe*2)
|
||||
#define NIC_MAR7 (0xf*2)
|
||||
|
||||
/* Command register definitions */
|
||||
|
||||
#define CR_STOP 0x01 /* Stop -- software reset command */
|
||||
#define CR_START 0x02 /* Start */
|
||||
#define CR_TXP 0x04 /* Transmit packet */
|
||||
|
||||
#define CR_RD0 0x08 /* Remote DMA cmd */
|
||||
#define CR_RD1 0x10
|
||||
#define CR_RD2 0x20
|
||||
|
||||
#define CR_NODMA CR_RD2
|
||||
|
||||
#define CR_PS0 0x40 /* Page select */
|
||||
#define CR_PS1 0x80
|
||||
|
||||
#define CR_PAGE0 0
|
||||
#define CR_PAGE1 CR_PS0
|
||||
#define CR_PAGE2 CR_PS1
|
||||
|
||||
/* Interrupt status reg. definitions */
|
||||
|
||||
#define ISR_PRX 0x01 /* Packet received without errors */
|
||||
#define ISR_PTX 0x02 /* Packet transmitted without errors */
|
||||
#define ISR_RXE 0x04 /* Receive error */
|
||||
#define ISR_TXE 0x08 /* Transmit error */
|
||||
#define ISR_OVW 0x10 /* Ring buffer overrun */
|
||||
#define ISR_CNT 0x20 /* Counter overflow */
|
||||
#define ISR_RDC 0x40 /* Remote DMA compile */
|
||||
#define ISR_RST 0x80 /* Reset status */
|
||||
|
||||
/* Data config reg. definitions */
|
||||
|
||||
#define DCR_WTS 0x01 /* Word transfer select */
|
||||
#define DCR_BOS 0x02 /* Byte order select */
|
||||
#define DCR_LAS 0x04 /* Long address select */
|
||||
#define DCR_LS 0x08 /* Loopback select */
|
||||
#define DCR_AR 0x10 /* Auto-init remote */
|
||||
#define DCR_FT0 0x20 /* FIFO threshold select */
|
||||
#define DCR_FT1 0x40
|
||||
|
||||
/* Transmit config reg. definitions */
|
||||
|
||||
#define TCR_CRC 0x01 /* Inhibit CRC */
|
||||
#define TCR_LB0 0x02 /* Loopback control */
|
||||
#define TCR_LB1 0x04
|
||||
#define TCR_ATD 0x08 /* Auto transmit disable */
|
||||
#define TCR_OFST 0x10 /* Collision offset enable */
|
||||
|
||||
/* Transmit status reg. definitions */
|
||||
|
||||
#define TSR_PTX 0x01 /* Packet transmitted */
|
||||
#define TSR_COL 0x04 /* Transmit collided */
|
||||
#define TSR_ABT 0x08 /* Transmit aborted */
|
||||
#define TSR_CRS 0x10 /* Carrier sense lost */
|
||||
#define TSR_FU 0x20 /* FIFO underrun */
|
||||
#define TSR_CDH 0x40 /* CD Heartbeat */
|
||||
#define TSR_OWC 0x80 /* Out of Window Collision */
|
||||
|
||||
/* Receiver config register definitions */
|
||||
|
||||
#define RCR_SEP 0x01 /* Save errored packets */
|
||||
#define RCR_AR 0x02 /* Accept runt packets */
|
||||
#define RCR_AB 0x04 /* Accept broadcast */
|
||||
#define RCR_AM 0x08 /* Accept multicast */
|
||||
#define RCR_PRO 0x10 /* Promiscuous mode */
|
||||
#define RCR_MON 0x20 /* Monitor mode */
|
||||
|
||||
/* Receiver status register definitions */
|
||||
|
||||
#define RSR_PRX 0x01 /* Packet received without error */
|
||||
#define RSR_CRC 0x02 /* CRC error */
|
||||
#define RSR_FAE 0x04 /* Frame alignment error */
|
||||
#define RSR_FO 0x08 /* FIFO overrun */
|
||||
#define RSR_MPA 0x10 /* Missed packet */
|
||||
#define RSR_PHY 0x20 /* Physical address */
|
||||
#define RSR_DIS 0x40 /* Received disabled */
|
||||
#define RSR_DFR 0x80 /* Deferring (jabber) */
|
||||
|
||||
/* Hydra System card address PROM offset */
|
||||
|
||||
#define HYDRA_ADDRPROM 0xffc0
|
||||
|
||||
|
@ -1815,14 +1815,14 @@ static int irda_usb_probe(struct usb_interface *intf,
|
||||
self->needspatch = (ret < 0);
|
||||
if (ret < 0) {
|
||||
printk("patch_device failed\n");
|
||||
goto err_out_4;
|
||||
goto err_out_5;
|
||||
}
|
||||
|
||||
/* replace IrDA class descriptor with what patched device is now reporting */
|
||||
irda_desc = irda_usb_find_class_desc (self->usbintf);
|
||||
if (irda_desc == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err_out_4;
|
||||
goto err_out_5;
|
||||
}
|
||||
if (self->irda_desc)
|
||||
kfree (self->irda_desc);
|
||||
@ -1832,6 +1832,8 @@ static int irda_usb_probe(struct usb_interface *intf,
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_5:
|
||||
unregister_netdev(self->netdev);
|
||||
err_out_4:
|
||||
kfree(self->speed_buff);
|
||||
err_out_3:
|
||||
|
@ -225,6 +225,8 @@ static int __init smsc_superio_lpc(unsigned short cfg_base);
|
||||
#ifdef CONFIG_PCI
|
||||
static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
|
||||
static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
|
||||
static void __init preconfigure_ali_port(struct pci_dev *dev,
|
||||
unsigned short port);
|
||||
static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
|
||||
static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
|
||||
unsigned short ircc_fir,
|
||||
@ -2327,9 +2329,14 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
|
||||
* pre-configuration not properly done by the BIOS (especially laptops)
|
||||
* This code is based in part on smcinit.c, tosh1800-smcinit.c
|
||||
* and tosh2450-smcinit.c. The table lists the device entries
|
||||
* for ISA bridges with an LPC (Local Peripheral Configurator)
|
||||
* that are in turn used to configure the SMSC device with default
|
||||
* SIR and FIR I/O ports, DMA and IRQ.
|
||||
* for ISA bridges with an LPC (Low Pin Count) controller which
|
||||
* handles the communication with the SMSC device. After the LPC
|
||||
* controller is initialized through PCI, the SMSC device is initialized
|
||||
* through a dedicated port in the ISA port-mapped I/O area, this latter
|
||||
* area is used to configure the SMSC device with default
|
||||
* SIR and FIR I/O ports, DMA and IRQ. Different vendors have
|
||||
* used different sets of parameters and different control port
|
||||
* addresses making a subsystem device table necessary.
|
||||
*/
|
||||
#ifdef CONFIG_PCI
|
||||
#define PCIID_VENDOR_INTEL 0x8086
|
||||
@ -2340,9 +2347,10 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __dev
|
||||
.device = 0x24cc,
|
||||
.subvendor = 0x103c,
|
||||
.subdevice = 0x088c,
|
||||
.sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */
|
||||
/* Quite certain these are the same for nc8000 as for nc6000 */
|
||||
.sir_io = 0x02f8,
|
||||
.fir_io = 0x0130,
|
||||
.fir_irq = 0x09,
|
||||
.fir_irq = 0x05,
|
||||
.fir_dma = 0x03,
|
||||
.cfg_base = 0x004e,
|
||||
.preconfigure = preconfigure_through_82801,
|
||||
@ -2355,60 +2363,79 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __dev
|
||||
.subdevice = 0x0890,
|
||||
.sir_io = 0x02f8,
|
||||
.fir_io = 0x0130,
|
||||
.fir_irq = 0x09,
|
||||
.fir_irq = 0x05,
|
||||
.fir_dma = 0x03,
|
||||
.cfg_base = 0x004e,
|
||||
.preconfigure = preconfigure_through_82801,
|
||||
.name = "HP nc6000",
|
||||
},
|
||||
{
|
||||
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
|
||||
/* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
|
||||
.vendor = PCIID_VENDOR_INTEL,
|
||||
.device = 0x24c0,
|
||||
.subvendor = 0x1179,
|
||||
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
|
||||
.subdevice = 0xffff, /* 0xffff is "any" */
|
||||
.sir_io = 0x03f8,
|
||||
.fir_io = 0x0130,
|
||||
.fir_irq = 0x07,
|
||||
.fir_dma = 0x01,
|
||||
.cfg_base = 0x002e,
|
||||
.preconfigure = preconfigure_through_82801,
|
||||
.name = "Toshiba Satellite 2450",
|
||||
.name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
|
||||
},
|
||||
{
|
||||
.vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
|
||||
.device = 0x248c, /* Some use 24cc? */
|
||||
.device = 0x248c,
|
||||
.subvendor = 0x1179,
|
||||
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
|
||||
.subdevice = 0xffff, /* 0xffff is "any" */
|
||||
.sir_io = 0x03f8,
|
||||
.fir_io = 0x0130,
|
||||
.fir_irq = 0x03,
|
||||
.fir_dma = 0x03,
|
||||
.cfg_base = 0x002e,
|
||||
.preconfigure = preconfigure_through_82801,
|
||||
.name = "Toshiba Satellite 5100/5200, Tecra 9100",
|
||||
.name = "Toshiba laptop with Intel 82801CAM ISA bridge",
|
||||
},
|
||||
{
|
||||
.vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
|
||||
/* 82801DBM (ICH4-M) LPC Interface Bridge */
|
||||
.vendor = PCIID_VENDOR_INTEL,
|
||||
.device = 0x24cc,
|
||||
.subvendor = 0x1179,
|
||||
.subdevice = 0xffff, /* 0xffff is "any" */
|
||||
.sir_io = 0x03f8,
|
||||
.fir_io = 0x0130,
|
||||
.fir_irq = 0x03,
|
||||
.fir_dma = 0x03,
|
||||
.cfg_base = 0x002e,
|
||||
.preconfigure = preconfigure_through_82801,
|
||||
.name = "Toshiba laptop with Intel 8281DBM LPC bridge",
|
||||
},
|
||||
{
|
||||
/* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
|
||||
.vendor = PCIID_VENDOR_ALI,
|
||||
.device = 0x1533,
|
||||
.subvendor = 0x1179,
|
||||
.subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
|
||||
.subdevice = 0xffff, /* 0xffff is "any" */
|
||||
.sir_io = 0x02e8,
|
||||
.fir_io = 0x02f8,
|
||||
.fir_irq = 0x07,
|
||||
.fir_dma = 0x03,
|
||||
.cfg_base = 0x002e,
|
||||
.preconfigure = preconfigure_through_ali,
|
||||
.name = "Toshiba Satellite 1800",
|
||||
.name = "Toshiba laptop with ALi ISA bridge",
|
||||
},
|
||||
{ } // Terminator
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ)
|
||||
* This sets up the basic SMSC parameters
|
||||
* (FIR port, SIR port, FIR DMA, FIR IRQ)
|
||||
* through the chip configuration port.
|
||||
*/
|
||||
static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf)
|
||||
static int __init preconfigure_smsc_chip(struct
|
||||
smsc_ircc_subsystem_configuration
|
||||
*conf)
|
||||
{
|
||||
unsigned short iobase = conf->cfg_base;
|
||||
unsigned char tmpbyte;
|
||||
@ -2416,7 +2443,9 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
|
||||
outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
|
||||
outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
|
||||
tmpbyte = inb(iobase +1); // Read device ID
|
||||
IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte);
|
||||
IRDA_DEBUG(0,
|
||||
"Detected Chip id: 0x%02x, setting up registers...\n",
|
||||
tmpbyte);
|
||||
|
||||
/* Disable UART1 and set up SIR I/O port */
|
||||
outb(0x24, iobase); // select CR24 - UART1 base addr
|
||||
@ -2426,6 +2455,7 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
|
||||
tmpbyte = inb(iobase + 1);
|
||||
if (tmpbyte != (conf->sir_io >> 2) ) {
|
||||
IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
|
||||
IRDA_WARNING("Try to supply ircc_cfg argument.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
@ -2461,7 +2491,8 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
|
||||
|
||||
outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
|
||||
tmpbyte = inb(iobase + 1);
|
||||
tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA;
|
||||
tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK |
|
||||
SMSCSIOFLAT_UART2MODE_VAL_IRDA;
|
||||
outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
|
||||
|
||||
outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
|
||||
@ -2486,53 +2517,226 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 82801CAM registers */
|
||||
/* 82801CAM generic registers */
|
||||
#define VID 0x00
|
||||
#define DID 0x02
|
||||
#define PIRQA_ROUT 0x60
|
||||
#define PIRQ_A_D_ROUT 0x60
|
||||
#define SIRQ_CNTL 0x64
|
||||
#define PIRQ_E_H_ROUT 0x68
|
||||
#define PCI_DMA_C 0x90
|
||||
/* LPC-specific registers */
|
||||
#define COM_DEC 0xe0
|
||||
#define GEN1_DEC 0xe4
|
||||
#define LPC_EN 0xe6
|
||||
#define GEN2_DEC 0xec
|
||||
/*
|
||||
* Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or
|
||||
* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way!
|
||||
* Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge
|
||||
* or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.
|
||||
* They all work the same way!
|
||||
*/
|
||||
static int __init preconfigure_through_82801(struct pci_dev *dev,
|
||||
struct smsc_ircc_subsystem_configuration *conf)
|
||||
struct
|
||||
smsc_ircc_subsystem_configuration
|
||||
*conf)
|
||||
{
|
||||
unsigned short tmpword;
|
||||
int ret;
|
||||
unsigned char tmpbyte;
|
||||
|
||||
IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n");
|
||||
pci_write_config_byte(dev, COM_DEC, 0x10);
|
||||
IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n");
|
||||
/*
|
||||
* Select the range for the COMA COM port (SIR)
|
||||
* Register COM_DEC:
|
||||
* Bit 7: reserved
|
||||
* Bit 6-4, COMB decode range
|
||||
* Bit 3: reserved
|
||||
* Bit 2-0, COMA decode range
|
||||
*
|
||||
* Decode ranges:
|
||||
* 000 = 0x3f8-0x3ff (COM1)
|
||||
* 001 = 0x2f8-0x2ff (COM2)
|
||||
* 010 = 0x220-0x227
|
||||
* 011 = 0x228-0x22f
|
||||
* 100 = 0x238-0x23f
|
||||
* 101 = 0x2e8-0x2ef (COM4)
|
||||
* 110 = 0x338-0x33f
|
||||
* 111 = 0x3e8-0x3ef (COM3)
|
||||
*/
|
||||
pci_read_config_byte(dev, COM_DEC, &tmpbyte);
|
||||
tmpbyte &= 0xf8; /* mask COMA bits */
|
||||
switch(conf->sir_io) {
|
||||
case 0x3f8:
|
||||
tmpbyte |= 0x00;
|
||||
break;
|
||||
case 0x2f8:
|
||||
tmpbyte |= 0x01;
|
||||
break;
|
||||
case 0x220:
|
||||
tmpbyte |= 0x02;
|
||||
break;
|
||||
case 0x228:
|
||||
tmpbyte |= 0x03;
|
||||
break;
|
||||
case 0x238:
|
||||
tmpbyte |= 0x04;
|
||||
break;
|
||||
case 0x2e8:
|
||||
tmpbyte |= 0x05;
|
||||
break;
|
||||
case 0x338:
|
||||
tmpbyte |= 0x06;
|
||||
break;
|
||||
case 0x3e8:
|
||||
tmpbyte |= 0x07;
|
||||
break;
|
||||
default:
|
||||
tmpbyte |= 0x01; /* COM2 default */
|
||||
}
|
||||
IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte);
|
||||
pci_write_config_byte(dev, COM_DEC, tmpbyte);
|
||||
|
||||
/* Enable LPC */
|
||||
pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
|
||||
tmpword &= 0xfffd; /* mask bit 1 */
|
||||
tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */
|
||||
/* Enable Low Pin Count interface */
|
||||
pci_read_config_word(dev, LPC_EN, &tmpword);
|
||||
/* These seem to be set up at all times,
|
||||
* just make sure it is properly set.
|
||||
*/
|
||||
switch(conf->cfg_base) {
|
||||
case 0x04e:
|
||||
tmpword |= 0x2000;
|
||||
break;
|
||||
case 0x02e:
|
||||
tmpword |= 0x1000;
|
||||
break;
|
||||
case 0x062:
|
||||
tmpword |= 0x0800;
|
||||
break;
|
||||
case 0x060:
|
||||
tmpword |= 0x0400;
|
||||
break;
|
||||
default:
|
||||
IRDA_WARNING("Uncommon I/O base address: 0x%04x\n",
|
||||
conf->cfg_base);
|
||||
break;
|
||||
}
|
||||
tmpword &= 0xfffd; /* disable LPC COMB */
|
||||
tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */
|
||||
IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword);
|
||||
pci_write_config_word(dev, LPC_EN, tmpword);
|
||||
|
||||
/* Setup DMA */
|
||||
pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */
|
||||
pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */
|
||||
/*
|
||||
* Configure LPC DMA channel
|
||||
* PCI_DMA_C bits:
|
||||
* Bit 15-14: DMA channel 7 select
|
||||
* Bit 13-12: DMA channel 6 select
|
||||
* Bit 11-10: DMA channel 5 select
|
||||
* Bit 9-8: Reserved
|
||||
* Bit 7-6: DMA channel 3 select
|
||||
* Bit 5-4: DMA channel 2 select
|
||||
* Bit 3-2: DMA channel 1 select
|
||||
* Bit 1-0: DMA channel 0 select
|
||||
* 00 = Reserved value
|
||||
* 01 = PC/PCI DMA
|
||||
* 10 = Reserved value
|
||||
* 11 = LPC I/F DMA
|
||||
*/
|
||||
pci_read_config_word(dev, PCI_DMA_C, &tmpword);
|
||||
switch(conf->fir_dma) {
|
||||
case 0x07:
|
||||
tmpword |= 0xc000;
|
||||
break;
|
||||
case 0x06:
|
||||
tmpword |= 0x3000;
|
||||
break;
|
||||
case 0x05:
|
||||
tmpword |= 0x0c00;
|
||||
break;
|
||||
case 0x03:
|
||||
tmpword |= 0x00c0;
|
||||
break;
|
||||
case 0x02:
|
||||
tmpword |= 0x0030;
|
||||
break;
|
||||
case 0x01:
|
||||
tmpword |= 0x000c;
|
||||
break;
|
||||
case 0x00:
|
||||
tmpword |= 0x0003;
|
||||
break;
|
||||
default:
|
||||
break; /* do not change settings */
|
||||
}
|
||||
IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword);
|
||||
pci_write_config_word(dev, PCI_DMA_C, tmpword);
|
||||
|
||||
/*
|
||||
* GEN2_DEC bits:
|
||||
* Bit 15-4: Generic I/O range
|
||||
* Bit 3-1: reserved (read as 0)
|
||||
* Bit 0: enable GEN2 range on LPC I/F
|
||||
*/
|
||||
tmpword = conf->fir_io & 0xfff8;
|
||||
tmpword |= 0x0001;
|
||||
IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword);
|
||||
pci_write_config_word(dev, GEN2_DEC, tmpword);
|
||||
|
||||
/* Pre-configure chip */
|
||||
ret = preconfigure_smsc_chip(conf);
|
||||
return preconfigure_smsc_chip(conf);
|
||||
}
|
||||
|
||||
/* Disable LPC */
|
||||
pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
|
||||
tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */
|
||||
pci_write_config_word(dev, LPC_EN, tmpword);
|
||||
return ret;
|
||||
/*
|
||||
* Pre-configure a certain port on the ALi 1533 bridge.
|
||||
* This is based on reverse-engineering since ALi does not
|
||||
* provide any data sheet for the 1533 chip.
|
||||
*/
|
||||
static void __init preconfigure_ali_port(struct pci_dev *dev,
|
||||
unsigned short port)
|
||||
{
|
||||
unsigned char reg;
|
||||
/* These bits obviously control the different ports */
|
||||
unsigned char mask;
|
||||
unsigned char tmpbyte;
|
||||
|
||||
switch(port) {
|
||||
case 0x0130:
|
||||
case 0x0178:
|
||||
reg = 0xb0;
|
||||
mask = 0x80;
|
||||
break;
|
||||
case 0x03f8:
|
||||
reg = 0xb4;
|
||||
mask = 0x80;
|
||||
break;
|
||||
case 0x02f8:
|
||||
reg = 0xb4;
|
||||
mask = 0x30;
|
||||
break;
|
||||
case 0x02e8:
|
||||
reg = 0xb4;
|
||||
mask = 0x08;
|
||||
break;
|
||||
default:
|
||||
IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port);
|
||||
return;
|
||||
}
|
||||
|
||||
pci_read_config_byte(dev, reg, &tmpbyte);
|
||||
/* Turn on the right bits */
|
||||
tmpbyte |= mask;
|
||||
pci_write_config_byte(dev, reg, tmpbyte);
|
||||
IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init preconfigure_through_ali(struct pci_dev *dev,
|
||||
struct smsc_ircc_subsystem_configuration *conf)
|
||||
struct
|
||||
smsc_ircc_subsystem_configuration
|
||||
*conf)
|
||||
{
|
||||
/* TODO: put in ALi 1533 configuration here. */
|
||||
IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name);
|
||||
return -ENODEV;
|
||||
/* Configure the two ports on the ALi 1533 */
|
||||
preconfigure_ali_port(dev, conf->sir_io);
|
||||
preconfigure_ali_port(dev, conf->fir_io);
|
||||
|
||||
/* Pre-configure chip */
|
||||
return preconfigure_smsc_chip(conf);
|
||||
}
|
||||
|
||||
static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
|
||||
@ -2552,9 +2756,10 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
|
||||
struct smsc_ircc_subsystem_configuration *conf;
|
||||
|
||||
/*
|
||||
* Cache the subsystem vendor/device: some manufacturers fail to set
|
||||
* this for all components, so we save it in case there is just
|
||||
* 0x0000 0x0000 on the device we want to check.
|
||||
* Cache the subsystem vendor/device:
|
||||
* some manufacturers fail to set this for all components,
|
||||
* so we save it in case there is just 0x0000 0x0000 on the
|
||||
* device we want to check.
|
||||
*/
|
||||
if (dev->subsystem_vendor != 0x0000U) {
|
||||
ss_vendor = dev->subsystem_vendor;
|
||||
@ -2564,13 +2769,20 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
|
||||
for( ; conf->subvendor; conf++) {
|
||||
if(conf->vendor == dev->vendor &&
|
||||
conf->device == dev->device &&
|
||||
conf->subvendor == ss_vendor && /* Sometimes these are cached values */
|
||||
(conf->subdevice == ss_device || conf->subdevice == 0xffff)) {
|
||||
struct smsc_ircc_subsystem_configuration tmpconf;
|
||||
conf->subvendor == ss_vendor &&
|
||||
/* Sometimes these are cached values */
|
||||
(conf->subdevice == ss_device ||
|
||||
conf->subdevice == 0xffff)) {
|
||||
struct smsc_ircc_subsystem_configuration
|
||||
tmpconf;
|
||||
|
||||
memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration));
|
||||
memcpy(&tmpconf, conf,
|
||||
sizeof(struct smsc_ircc_subsystem_configuration));
|
||||
|
||||
/* Override the default values with anything passed in as parameter */
|
||||
/*
|
||||
* Override the default values with anything
|
||||
* passed in as parameter
|
||||
*/
|
||||
if (ircc_cfg != 0)
|
||||
tmpconf.cfg_base = ircc_cfg;
|
||||
if (ircc_fir != 0)
|
||||
|
@ -357,18 +357,20 @@ ixgb_probe(struct pci_dev *pdev,
|
||||
if((err = pci_enable_device(pdev)))
|
||||
return err;
|
||||
|
||||
if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
|
||||
if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
|
||||
!(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
|
||||
pci_using_dac = 1;
|
||||
} else {
|
||||
if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
|
||||
if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
|
||||
(err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
|
||||
IXGB_ERR("No usable DMA configuration, aborting\n");
|
||||
return err;
|
||||
goto err_dma_mask;
|
||||
}
|
||||
pci_using_dac = 0;
|
||||
}
|
||||
|
||||
if((err = pci_request_regions(pdev, ixgb_driver_name)))
|
||||
return err;
|
||||
goto err_request_regions;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
@ -502,6 +504,9 @@ err_ioremap:
|
||||
free_netdev(netdev);
|
||||
err_alloc_etherdev:
|
||||
pci_release_regions(pdev);
|
||||
err_request_regions:
|
||||
err_dma_mask:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -281,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
|
||||
{
|
||||
struct mv643xx_private *mp = netdev_priv(dev);
|
||||
|
||||
netif_device_detach(dev);
|
||||
if (!netif_running(dev))
|
||||
return;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
eth_port_reset(mp->port_num);
|
||||
eth_port_start(dev);
|
||||
netif_device_attach(dev);
|
||||
|
||||
if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -552,9 +558,9 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
|
||||
#else
|
||||
if (eth_int_cause & ETH_INT_CAUSE_RX)
|
||||
mv643xx_eth_receive_queue(dev, INT_MAX);
|
||||
#endif
|
||||
if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
|
||||
mv643xx_eth_free_completed_tx_descs(dev);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If no real interrupt occured, exit.
|
||||
@ -1186,7 +1192,12 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
BUG_ON(netif_queue_stopped(dev));
|
||||
BUG_ON(skb == NULL);
|
||||
BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
|
||||
|
||||
if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
|
||||
printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
|
||||
netif_stop_queue(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (has_tiny_unaligned_frags(skb)) {
|
||||
if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
|
||||
|
@ -238,7 +238,7 @@ static int full_duplex[MAX_UNITS];
|
||||
#define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */
|
||||
|
||||
/* These identify the driver base version and may not be removed. */
|
||||
static char version[] __devinitdata =
|
||||
static const char version[] __devinitdata =
|
||||
KERN_INFO DRV_NAME " dp8381x driver, version "
|
||||
DRV_VERSION ", " DRV_RELDATE "\n"
|
||||
KERN_INFO " originally by Donald Becker <becker@scyld.com>\n"
|
||||
|
@ -1560,7 +1560,7 @@ static void ei_receive(struct net_device *dev)
|
||||
|
||||
static void ei_rx_overrun(struct net_device *dev)
|
||||
{
|
||||
axnet_dev_t *info = (axnet_dev_t *)dev;
|
||||
axnet_dev_t *info = PRIV(dev);
|
||||
long e8390_base = dev->base_addr;
|
||||
unsigned char was_txing, must_resend = 0;
|
||||
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
|
||||
|
@ -78,6 +78,8 @@ static const struct pci_device_id skge_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
|
||||
|
@ -99,8 +99,6 @@ MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
|
||||
static const struct pci_device_id sky2_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
|
||||
@ -579,8 +577,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
|
||||
reg = gma_read16(hw, port, GM_PHY_ADDR);
|
||||
gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
|
||||
|
||||
for (i = 0; i < GM_MIB_CNT_SIZE; i++)
|
||||
gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
|
||||
for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
|
||||
gma_read16(hw, port, i);
|
||||
gma_write16(hw, port, GM_PHY_ADDR, reg);
|
||||
|
||||
/* transmit control */
|
||||
|
@ -1375,7 +1375,7 @@ enum {
|
||||
GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
|
||||
/* MIB Counters */
|
||||
GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */
|
||||
GM_MIB_CNT_SIZE = 256,
|
||||
GM_MIB_CNT_END = 0x025C, /* Last MIB counter */
|
||||
};
|
||||
|
||||
|
||||
|
@ -335,7 +335,7 @@ do { \
|
||||
|
||||
|
||||
/* These identify the driver base version and may not be removed. */
|
||||
static char version[] __devinitdata =
|
||||
static const char version[] __devinitdata =
|
||||
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"
|
||||
KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
|
||||
|
||||
|
@ -134,7 +134,7 @@ static const int multicast_filter_limit = 32;
|
||||
#include "typhoon.h"
|
||||
#include "typhoon-firmware.h"
|
||||
|
||||
static char version[] __devinitdata =
|
||||
static const char version[] __devinitdata =
|
||||
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
||||
MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
|
||||
|
@ -469,7 +469,7 @@ struct rhine_private {
|
||||
struct sk_buff *tx_skbuff[TX_RING_SIZE];
|
||||
dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
|
||||
|
||||
/* Tx bounce buffers */
|
||||
/* Tx bounce buffers (Rhine-I only) */
|
||||
unsigned char *tx_buf[TX_RING_SIZE];
|
||||
unsigned char *tx_bufs;
|
||||
dma_addr_t tx_bufs_dma;
|
||||
@ -1043,7 +1043,8 @@ static void alloc_tbufs(struct net_device* dev)
|
||||
rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
|
||||
next += sizeof(struct tx_desc);
|
||||
rp->tx_ring[i].next_desc = cpu_to_le32(next);
|
||||
rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
|
||||
if (rp->quirks & rqRhineI)
|
||||
rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
|
||||
}
|
||||
rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
|
||||
|
||||
@ -1091,7 +1092,7 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
|
||||
}
|
||||
|
||||
/* Called after status of force_media possibly changed */
|
||||
void rhine_set_carrier(struct mii_if_info *mii)
|
||||
static void rhine_set_carrier(struct mii_if_info *mii)
|
||||
{
|
||||
if (mii->force_media) {
|
||||
/* autoneg is off: Link is always assumed to be up */
|
||||
|
@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config VENDOR_SANGOMA
|
||||
tristate "Sangoma WANPIPE(tm) multiprotocol cards"
|
||||
depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
|
||||
---help---
|
||||
Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
|
||||
|
||||
WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
|
||||
is a family of intelligent multiprotocol WAN adapters with data
|
||||
transfer rates up to 4Mbps. Cards support:
|
||||
|
||||
- X.25, Frame Relay, PPP, Cisco HDLC protocols.
|
||||
|
||||
- API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
|
||||
Frame Relay and BiSync.
|
||||
|
||||
- Ethernet Bridging over Frame Relay protocol.
|
||||
|
||||
- MULTILINK PPP
|
||||
|
||||
- Async PPP (Modem Dialup)
|
||||
|
||||
The next questions will ask you about the protocols you want
|
||||
the driver to support.
|
||||
|
||||
If you have one or more of these cards, say M to this option;
|
||||
and read <file:Documentation/networking/wan-router.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wanpipe.
|
||||
|
||||
config WANPIPE_CHDLC
|
||||
bool "WANPIPE Cisco HDLC support"
|
||||
depends on VENDOR_SANGOMA
|
||||
---help---
|
||||
Connect a WANPIPE card to a leased line using the Cisco HDLC.
|
||||
|
||||
- Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
|
||||
which allows user to build applications using the HDLC streaming API.
|
||||
|
||||
- CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
|
||||
cards into a single logical channel.
|
||||
|
||||
Say Y and the Cisco HDLC support, HDLC streaming API and
|
||||
MULTILINK PPP will be included in the driver.
|
||||
|
||||
config WANPIPE_FR
|
||||
bool "WANPIPE Frame Relay support"
|
||||
depends on VENDOR_SANGOMA
|
||||
help
|
||||
Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
|
||||
API to develop custom applications.
|
||||
|
||||
Contains the Ethernet Bridging over Frame Relay feature, where
|
||||
a WANPIPE frame relay link can be directly connected to the Linux
|
||||
kernel bridge. The Frame Relay option is supported on S514-PCI
|
||||
and S508-ISA cards.
|
||||
|
||||
Say Y and the Frame Relay support will be included in the driver.
|
||||
|
||||
config WANPIPE_X25
|
||||
bool "WANPIPE X.25 support"
|
||||
depends on VENDOR_SANGOMA
|
||||
help
|
||||
Connect a WANPIPE card to an X.25 network.
|
||||
|
||||
Includes the X.25 API support for custom applications over the
|
||||
X.25 protocol. The X.25 option is supported on S514-PCI and
|
||||
S508-ISA cards.
|
||||
|
||||
Say Y and the X.25 support will be included in the driver.
|
||||
|
||||
config WANPIPE_PPP
|
||||
bool "WANPIPE PPP support"
|
||||
depends on VENDOR_SANGOMA
|
||||
help
|
||||
Connect a WANPIPE card to a leased line using Point-to-Point
|
||||
Protocol (PPP).
|
||||
|
||||
The PPP option is supported on S514-PCI/S508-ISA cards.
|
||||
|
||||
Say Y and the PPP support will be included in the driver.
|
||||
|
||||
config WANPIPE_MULTPPP
|
||||
bool "WANPIPE Multi-Port PPP support"
|
||||
depends on VENDOR_SANGOMA
|
||||
help
|
||||
Connect a WANPIPE card to a leased line using Point-to-Point
|
||||
Protocol (PPP).
|
||||
|
||||
Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
|
||||
adapter. In this case each Sangoma adapter port can support an
|
||||
independent PPP connection. For example, a single Quad-Port PCI
|
||||
adapter can support up to four independent PPP links. The PPP
|
||||
option is supported on S514-PCI/S508-ISA cards.
|
||||
|
||||
Say Y and the Multi-Port PPP support will be included in the driver.
|
||||
|
||||
config CYCLADES_SYNC
|
||||
tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
|
||||
depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
|
||||
|
@ -5,14 +5,6 @@
|
||||
# Rewritten to use lists instead of if-statements.
|
||||
#
|
||||
|
||||
wanpipe-y := sdlamain.o sdla_ft1.o
|
||||
wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o
|
||||
wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o
|
||||
wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o
|
||||
wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o
|
||||
wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
|
||||
wanpipe-objs := $(wanpipe-y)
|
||||
|
||||
cyclomx-y := cycx_main.o
|
||||
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
|
||||
cyclomx-objs := $(cyclomx-y)
|
||||
@ -43,11 +35,6 @@ obj-$(CONFIG_LANMEDIA) += lmc/
|
||||
|
||||
obj-$(CONFIG_DLCI) += dlci.o
|
||||
obj-$(CONFIG_SDLA) += sdla.o
|
||||
ifeq ($(CONFIG_WANPIPE_MULTPPP),y)
|
||||
obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o
|
||||
else
|
||||
obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o
|
||||
endif
|
||||
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
|
||||
obj-$(CONFIG_LAPBETHER) += lapbether.o
|
||||
obj-$(CONFIG_SBNI) += sbni.o
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,345 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
|
||||
*
|
||||
* Authors: Nenad Corbic <ncorbic@sangoma.com>
|
||||
* Gideon Hack
|
||||
*
|
||||
* Copyright: (c) 1995-1999 Sangoma Technologies Inc.
|
||||
*
|
||||
* 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.
|
||||
* ============================================================================
|
||||
* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
|
||||
* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
|
||||
* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
|
||||
* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
|
||||
* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
|
||||
* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
|
||||
* Aug 07, 1998 David Fong Initial version.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h> /* printk(), and other useful stuff */
|
||||
#include <linux/stddef.h> /* offsetof(), etc. */
|
||||
#include <linux/errno.h> /* return codes */
|
||||
#include <linux/string.h> /* inline memset(), etc. */
|
||||
#include <linux/slab.h> /* kmalloc(), kfree() */
|
||||
#include <linux/wanrouter.h> /* WAN router definitions */
|
||||
#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
|
||||
#include <linux/if_arp.h> /* ARPHRD_* defines */
|
||||
#include <linux/jiffies.h> /* time_after() macro */
|
||||
|
||||
#include <linux/inetdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <linux/in.h> /* sockaddr_in */
|
||||
#include <linux/inet.h>
|
||||
#include <linux/if.h>
|
||||
#include <asm/byteorder.h> /* htons(), etc. */
|
||||
#include <linux/sdlapci.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
|
||||
|
||||
/****** Defines & Macros ****************************************************/
|
||||
|
||||
/* reasons for enabling the timer interrupt on the adapter */
|
||||
#define TMR_INT_ENABLED_UDP 0x0001
|
||||
#define TMR_INT_ENABLED_UPDATE 0x0002
|
||||
|
||||
#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
|
||||
#define CHDLC_HDR_LEN 1
|
||||
|
||||
#define IFF_POINTTOPOINT 0x10
|
||||
|
||||
#define WANPIPE 0x00
|
||||
#define API 0x01
|
||||
#define CHDLC_API 0x01
|
||||
|
||||
#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
|
||||
|
||||
|
||||
/******Data Structures*****************************************************/
|
||||
|
||||
/* This structure is placed in the private data area of the device structure.
|
||||
* The card structure used to occupy the private area but now the following
|
||||
* structure will incorporate the card structure along with CHDLC specific data
|
||||
*/
|
||||
|
||||
typedef struct chdlc_private_area
|
||||
{
|
||||
struct net_device *slave;
|
||||
sdla_t *card;
|
||||
int TracingEnabled; /* For enabling Tracing */
|
||||
unsigned long curr_trace_addr; /* Used for Tracing */
|
||||
unsigned long start_trace_addr;
|
||||
unsigned long end_trace_addr;
|
||||
unsigned long base_addr_trace_buffer;
|
||||
unsigned long end_addr_trace_buffer;
|
||||
unsigned short number_trace_elements;
|
||||
unsigned available_buffer_space;
|
||||
unsigned long router_start_time;
|
||||
unsigned char route_status;
|
||||
unsigned char route_removed;
|
||||
unsigned long tick_counter; /* For 5s timeout counter */
|
||||
unsigned long router_up_time;
|
||||
u32 IP_address; /* IP addressing */
|
||||
u32 IP_netmask;
|
||||
unsigned char mc; /* Mulitcast support on/off */
|
||||
unsigned short udp_pkt_lgth; /* udp packet processing */
|
||||
char udp_pkt_src;
|
||||
char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
|
||||
unsigned short timer_int_enabled;
|
||||
char update_comms_stats; /* updating comms stats */
|
||||
//FIXME: add driver stats as per frame relay!
|
||||
|
||||
} chdlc_private_area_t;
|
||||
|
||||
/* Route Status options */
|
||||
#define NO_ROUTE 0x00
|
||||
#define ADD_ROUTE 0x01
|
||||
#define ROUTE_ADDED 0x02
|
||||
#define REMOVE_ROUTE 0x03
|
||||
|
||||
|
||||
/****** Function Prototypes *************************************************/
|
||||
/* WAN link driver entry points. These are called by the WAN router module. */
|
||||
static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
|
||||
static int chdlc_read_version (sdla_t* card, char* str);
|
||||
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
|
||||
|
||||
/****** Public Functions ****************************************************/
|
||||
|
||||
/*============================================================================
|
||||
* Cisco HDLC protocol initialization routine.
|
||||
*
|
||||
* This routine is called by the main WANPIPE module during setup. At this
|
||||
* point adapter is completely initialized and firmware is running.
|
||||
* o read firmware version (to make sure it's alive)
|
||||
* o configure adapter
|
||||
* o initialize protocol-specific fields of the adapter data space.
|
||||
*
|
||||
* Return: 0 o.k.
|
||||
* < 0 failure.
|
||||
*/
|
||||
int wpft1_init (sdla_t* card, wandev_conf_t* conf)
|
||||
{
|
||||
unsigned char port_num;
|
||||
int err;
|
||||
|
||||
union
|
||||
{
|
||||
char str[80];
|
||||
} u;
|
||||
volatile CHDLC_MAILBOX_STRUCT* mb;
|
||||
CHDLC_MAILBOX_STRUCT* mb1;
|
||||
unsigned long timeout;
|
||||
|
||||
/* Verify configuration ID */
|
||||
if (conf->config_id != WANCONFIG_CHDLC) {
|
||||
printk(KERN_INFO "%s: invalid configuration ID %u!\n",
|
||||
card->devname, conf->config_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Use primary port */
|
||||
card->u.c.comm_port = 0;
|
||||
|
||||
|
||||
/* Initialize protocol-specific fields */
|
||||
if(card->hw.type != SDLA_S514){
|
||||
card->mbox = (void *) card->hw.dpmbase;
|
||||
}else{
|
||||
card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
|
||||
}
|
||||
|
||||
mb = mb1 = card->mbox;
|
||||
|
||||
if (!card->configured){
|
||||
|
||||
/* The board will place an 'I' in the return code to indicate that it is
|
||||
ready to accept commands. We expect this to be completed in less
|
||||
than 1 second. */
|
||||
|
||||
timeout = jiffies;
|
||||
while (mb->return_code != 'I') /* Wait 1s for board to initialize */
|
||||
if (time_after(jiffies, timeout + 1*HZ)) break;
|
||||
|
||||
if (mb->return_code != 'I') {
|
||||
printk(KERN_INFO
|
||||
"%s: Initialization not completed by adapter\n",
|
||||
card->devname);
|
||||
printk(KERN_INFO "Please contact Sangoma representative.\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read firmware version. Note that when adapter initializes, it
|
||||
* clears the mailbox, so it may appear that the first command was
|
||||
* executed successfully when in fact it was merely erased. To work
|
||||
* around this, we execute the first command twice.
|
||||
*/
|
||||
|
||||
if (chdlc_read_version(card, u.str))
|
||||
return -EIO;
|
||||
|
||||
printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
|
||||
card->devname, u.str);
|
||||
|
||||
card->isr = NULL;
|
||||
card->poll = NULL;
|
||||
card->exec = &wpft1_exec;
|
||||
card->wandev.update = NULL;
|
||||
card->wandev.new_if = NULL;
|
||||
card->wandev.del_if = NULL;
|
||||
card->wandev.state = WAN_DUALPORT;
|
||||
card->wandev.udp_port = conf->udp_port;
|
||||
|
||||
card->wandev.new_if_cnt = 0;
|
||||
|
||||
/* This is for the ports link state */
|
||||
card->u.c.state = WAN_DISCONNECTED;
|
||||
|
||||
/* reset the number of times the 'update()' proc has been called */
|
||||
card->u.c.update_call_count = 0;
|
||||
|
||||
card->wandev.ttl = 0x7F;
|
||||
card->wandev.interface = 0;
|
||||
|
||||
card->wandev.clocking = 0;
|
||||
|
||||
port_num = card->u.c.comm_port;
|
||||
|
||||
/* Setup Port Bps */
|
||||
|
||||
card->wandev.bps = 0;
|
||||
|
||||
card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
|
||||
|
||||
/* Set up the interrupt status area */
|
||||
/* Read the CHDLC Configuration and obtain:
|
||||
* Ptr to shared memory infor struct
|
||||
* Use this pointer to calculate the value of card->u.c.flags !
|
||||
*/
|
||||
mb1->buffer_length = 0;
|
||||
mb1->command = READ_CHDLC_CONFIGURATION;
|
||||
err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
|
||||
if(err != COMMAND_OK) {
|
||||
chdlc_error(card, err, mb1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(card->hw.type == SDLA_S514){
|
||||
card->u.c.flags = (void *)(card->hw.dpmbase +
|
||||
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
|
||||
ptr_shared_mem_info_struct));
|
||||
}else{
|
||||
card->u.c.flags = (void *)(card->hw.dpmbase +
|
||||
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
|
||||
ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
|
||||
}
|
||||
|
||||
card->wandev.state = WAN_FT1_READY;
|
||||
printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
|
||||
{
|
||||
CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
|
||||
int len;
|
||||
|
||||
if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
len = mbox->buffer_length;
|
||||
|
||||
if (len) {
|
||||
if( copy_from_user((void*)&mbox->data, u_data, len)){
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/* execute command */
|
||||
if (!sdla_exec(mbox)){
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* return result */
|
||||
if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
len = mbox->buffer_length;
|
||||
|
||||
if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*============================================================================
|
||||
* Read firmware code version.
|
||||
* Put code version as ASCII string in str.
|
||||
*/
|
||||
static int chdlc_read_version (sdla_t* card, char* str)
|
||||
{
|
||||
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
|
||||
int len;
|
||||
char err;
|
||||
mb->buffer_length = 0;
|
||||
mb->command = READ_CHDLC_CODE_VERSION;
|
||||
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
|
||||
|
||||
if(err != COMMAND_OK) {
|
||||
chdlc_error(card,err,mb);
|
||||
}
|
||||
else if (str) { /* is not null */
|
||||
len = mb->buffer_length;
|
||||
memcpy(str, mb->data, len);
|
||||
str[len] = '\0';
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*============================================================================
|
||||
* Firmware error handler.
|
||||
* This routine is called whenever firmware command returns non-zero
|
||||
* return code.
|
||||
*
|
||||
* Return zero if previous command has to be cancelled.
|
||||
*/
|
||||
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
|
||||
{
|
||||
unsigned cmd = mb->command;
|
||||
|
||||
switch (err) {
|
||||
|
||||
case CMD_TIMEOUT:
|
||||
printk(KERN_ERR "%s: command 0x%02X timed out!\n",
|
||||
card->devname, cmd);
|
||||
break;
|
||||
|
||||
case S514_BOTH_PORTS_SAME_CLK_MODE:
|
||||
if(cmd == SET_CHDLC_CONFIGURATION) {
|
||||
printk(KERN_INFO
|
||||
"%s: Configure both ports for the same clock source\n",
|
||||
card->devname);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
|
||||
card->devname, cmd, err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -360,9 +360,6 @@ static int __init rpaphp_init(void)
|
||||
while ((dn = of_find_node_by_type(dn, "pci")))
|
||||
rpaphp_add_slot(dn);
|
||||
|
||||
if (!num_slots)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -504,6 +504,201 @@ void pci_scan_msi_device(struct pci_dev *dev)
|
||||
nr_reserved_vectors++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int pci_save_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
int pos, i = 0;
|
||||
u16 control;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
u32 *cap;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (pos <= 0 || dev->no_msi)
|
||||
return 0;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
if (!(control & PCI_MSI_FLAGS_ENABLE))
|
||||
return 0;
|
||||
|
||||
save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
|
||||
GFP_KERNEL);
|
||||
if (!save_state) {
|
||||
printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
cap = &save_state->data[0];
|
||||
|
||||
pci_read_config_dword(dev, pos, &cap[i++]);
|
||||
control = cap[0] >> 16;
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
|
||||
if (control & PCI_MSI_FLAGS_64BIT) {
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
|
||||
} else
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
|
||||
if (control & PCI_MSI_FLAGS_MASKBIT)
|
||||
pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
|
||||
disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
save_state->cap_nr = PCI_CAP_ID_MSI;
|
||||
pci_add_saved_cap(dev, save_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_restore_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
int i = 0, pos;
|
||||
u16 control;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
u32 *cap;
|
||||
|
||||
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (!save_state || pos <= 0)
|
||||
return;
|
||||
cap = &save_state->data[0];
|
||||
|
||||
control = cap[i++] >> 16;
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
|
||||
if (control & PCI_MSI_FLAGS_64BIT) {
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
|
||||
} else
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
|
||||
if (control & PCI_MSI_FLAGS_MASKBIT)
|
||||
pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
|
||||
pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
pci_remove_saved_cap(save_state);
|
||||
kfree(save_state);
|
||||
}
|
||||
|
||||
int pci_save_msix_state(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
u16 control;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos <= 0 || dev->no_msi)
|
||||
return 0;
|
||||
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
if (!(control & PCI_MSIX_FLAGS_ENABLE))
|
||||
return 0;
|
||||
save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
|
||||
GFP_KERNEL);
|
||||
if (!save_state) {
|
||||
printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
*((u16 *)&save_state->data[0]) = control;
|
||||
|
||||
disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
|
||||
save_state->cap_nr = PCI_CAP_ID_MSIX;
|
||||
pci_add_saved_cap(dev, save_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_restore_msix_state(struct pci_dev *dev)
|
||||
{
|
||||
u16 save;
|
||||
int pos;
|
||||
int vector, head, tail = 0;
|
||||
void __iomem *base;
|
||||
int j;
|
||||
struct msg_address address;
|
||||
struct msg_data data;
|
||||
struct msi_desc *entry;
|
||||
int temp;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
|
||||
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
|
||||
if (!save_state)
|
||||
return;
|
||||
save = *((u16 *)&save_state->data[0]);
|
||||
pci_remove_saved_cap(save_state);
|
||||
kfree(save_state);
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos <= 0)
|
||||
return;
|
||||
|
||||
/* route the table */
|
||||
temp = dev->irq;
|
||||
if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX))
|
||||
return;
|
||||
vector = head = dev->irq;
|
||||
while (head != tail) {
|
||||
entry = msi_desc[vector];
|
||||
base = entry->mask_base;
|
||||
j = entry->msi_attrib.entry_nr;
|
||||
|
||||
msi_address_init(&address);
|
||||
msi_data_init(&data, vector);
|
||||
|
||||
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
|
||||
address.lo_address.value |= entry->msi_attrib.current_cpu <<
|
||||
MSI_TARGET_CPU_SHIFT;
|
||||
|
||||
writel(address.lo_address.value,
|
||||
base + j * PCI_MSIX_ENTRY_SIZE +
|
||||
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
|
||||
writel(address.hi_address,
|
||||
base + j * PCI_MSIX_ENTRY_SIZE +
|
||||
PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
|
||||
writel(*(u32*)&data,
|
||||
base + j * PCI_MSIX_ENTRY_SIZE +
|
||||
PCI_MSIX_ENTRY_DATA_OFFSET);
|
||||
|
||||
tail = msi_desc[vector]->link.tail;
|
||||
vector = tail;
|
||||
}
|
||||
dev->irq = temp;
|
||||
|
||||
pci_write_config_word(dev, msi_control_reg(pos), save);
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
|
||||
{
|
||||
struct msg_address address;
|
||||
struct msg_data data;
|
||||
int pos, vector = dev->irq;
|
||||
u16 control;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
/* Configure MSI capability structure */
|
||||
msi_address_init(&address);
|
||||
msi_data_init(&data, vector);
|
||||
entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
|
||||
MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
|
||||
pci_write_config_dword(dev, msi_lower_address_reg(pos),
|
||||
address.lo_address.value);
|
||||
if (is_64bit_address(control)) {
|
||||
pci_write_config_dword(dev,
|
||||
msi_upper_address_reg(pos), address.hi_address);
|
||||
pci_write_config_word(dev,
|
||||
msi_data_reg(pos, 1), *((u32*)&data));
|
||||
} else
|
||||
pci_write_config_word(dev,
|
||||
msi_data_reg(pos, 0), *((u32*)&data));
|
||||
if (entry->msi_attrib.maskbit) {
|
||||
unsigned int maskbits, temp;
|
||||
/* All MSIs are unmasked by default, Mask them all */
|
||||
pci_read_config_dword(dev,
|
||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||
&maskbits);
|
||||
temp = (1 << multi_msi_capable(control));
|
||||
temp = ((temp - 1) & ~temp);
|
||||
maskbits |= temp;
|
||||
pci_write_config_dword(dev,
|
||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||
maskbits);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* msi_capability_init - configure device's MSI capability structure
|
||||
* @dev: pointer to the pci_dev data structure of MSI device function
|
||||
@ -516,8 +711,6 @@ void pci_scan_msi_device(struct pci_dev *dev)
|
||||
static int msi_capability_init(struct pci_dev *dev)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
struct msg_address address;
|
||||
struct msg_data data;
|
||||
int pos, vector;
|
||||
u16 control;
|
||||
|
||||
@ -549,33 +742,8 @@ static int msi_capability_init(struct pci_dev *dev)
|
||||
/* Replace with MSI handler */
|
||||
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
|
||||
/* Configure MSI capability structure */
|
||||
msi_address_init(&address);
|
||||
msi_data_init(&data, vector);
|
||||
entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
|
||||
MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
|
||||
pci_write_config_dword(dev, msi_lower_address_reg(pos),
|
||||
address.lo_address.value);
|
||||
if (is_64bit_address(control)) {
|
||||
pci_write_config_dword(dev,
|
||||
msi_upper_address_reg(pos), address.hi_address);
|
||||
pci_write_config_word(dev,
|
||||
msi_data_reg(pos, 1), *((u32*)&data));
|
||||
} else
|
||||
pci_write_config_word(dev,
|
||||
msi_data_reg(pos, 0), *((u32*)&data));
|
||||
if (entry->msi_attrib.maskbit) {
|
||||
unsigned int maskbits, temp;
|
||||
/* All MSIs are unmasked by default, Mask them all */
|
||||
pci_read_config_dword(dev,
|
||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||
&maskbits);
|
||||
temp = (1 << multi_msi_capable(control));
|
||||
temp = ((temp - 1) & ~temp);
|
||||
maskbits |= temp;
|
||||
pci_write_config_dword(dev,
|
||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||
maskbits);
|
||||
}
|
||||
msi_register_init(dev, entry);
|
||||
|
||||
attach_msi_entry(entry, vector);
|
||||
/* Set MSI enabled bits */
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
@ -731,6 +899,7 @@ int pci_enable_msi(struct pci_dev* dev)
|
||||
vector_irq[dev->irq] = -1;
|
||||
nr_released_vectors--;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
msi_register_init(dev, msi_desc[dev->irq]);
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
return 0;
|
||||
}
|
||||
|
@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
|
||||
struct pci_driver * drv = pci_dev->driver;
|
||||
int i = 0;
|
||||
|
||||
if (drv && drv->suspend)
|
||||
if (drv && drv->suspend) {
|
||||
i = drv->suspend(pci_dev, state);
|
||||
else
|
||||
suspend_report_result(drv->suspend, i);
|
||||
} else {
|
||||
pci_save_state(pci_dev);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
* Can enter D0 from any state, but if we can only go deeper
|
||||
* to sleep if we're already in a low power state
|
||||
*/
|
||||
if (state != PCI_D0 && dev->current_state > state)
|
||||
if (state != PCI_D0 && dev->current_state > state) {
|
||||
printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
|
||||
__FUNCTION__, pci_name(dev), state, dev->current_state);
|
||||
return -EINVAL;
|
||||
else if (dev->current_state == state)
|
||||
} else if (dev->current_state == state)
|
||||
return 0; /* we're already there */
|
||||
|
||||
/* find PCI PM capability in list */
|
||||
@ -444,6 +446,10 @@ pci_save_state(struct pci_dev *dev)
|
||||
/* XXX: 100% dword access ok here? */
|
||||
for (i = 0; i < 16; i++)
|
||||
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
|
||||
if ((i = pci_save_msi_state(dev)) != 0)
|
||||
return i;
|
||||
if ((i = pci_save_msix_state(dev)) != 0)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -458,6 +464,8 @@ pci_restore_state(struct pci_dev *dev)
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
|
||||
pci_restore_msi_state(dev);
|
||||
pci_restore_msix_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,17 @@ void pci_no_msi(void);
|
||||
static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
|
||||
static inline void pci_no_msi(void) { }
|
||||
#endif
|
||||
#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
|
||||
int pci_save_msi_state(struct pci_dev *dev);
|
||||
int pci_save_msix_state(struct pci_dev *dev);
|
||||
void pci_restore_msi_state(struct pci_dev *dev);
|
||||
void pci_restore_msix_state(struct pci_dev *dev);
|
||||
#else
|
||||
static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
|
||||
static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
|
||||
static inline void pci_restore_msi_state(struct pci_dev *dev) {}
|
||||
static inline void pci_restore_msix_state(struct pci_dev *dev) {}
|
||||
#endif
|
||||
|
||||
extern int pcie_mch_quirk;
|
||||
extern struct device_attribute pci_dev_attrs[];
|
||||
|
@ -592,7 +592,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
|
||||
pci_write_config_byte( dev, AMD8131_MISC, tmp);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
|
||||
|
||||
static void __init quirk_svw_msi(struct pci_dev *dev)
|
||||
{
|
||||
@ -921,6 +921,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x1882: /* M6V notebook */
|
||||
case 0x1977: /* A6VA notebook */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
}
|
||||
@ -999,6 +1000,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asu
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc );
|
||||
|
||||
static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include <asm/arch/gpio.h>
|
||||
|
||||
|
||||
#define CF_SIZE 0x30000000 /* CS5+CS6: unavailable */
|
||||
|
||||
/*
|
||||
* A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW;
|
||||
* some other bit in {A24,A22..A11} is nREG to flag memory access
|
||||
@ -76,7 +74,8 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
|
||||
/* kick pccard as needed */
|
||||
if (present != cf->present) {
|
||||
cf->present = present;
|
||||
pr_debug("%s: card %s\n", driver_name, present ? "present" : "gone");
|
||||
pr_debug("%s: card %s\n", driver_name,
|
||||
present ? "present" : "gone");
|
||||
pcmcia_parse_events(&cf->socket, SS_DETECT);
|
||||
}
|
||||
}
|
||||
@ -93,7 +92,7 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
|
||||
|
||||
cf = container_of(s, struct at91_cf_socket, socket);
|
||||
|
||||
/* NOTE: we assume 3VCARD, not XVCARD... */
|
||||
/* NOTE: CF is always 3VCARD */
|
||||
if (at91_cf_present(cf)) {
|
||||
int rdy = cf->board->irq_pin; /* RDY/nIRQ */
|
||||
int vcc = cf->board->vcc_pin;
|
||||
@ -109,7 +108,8 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
|
||||
static int
|
||||
at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
|
||||
{
|
||||
struct at91_cf_socket *cf;
|
||||
|
||||
@ -184,7 +184,8 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
|
||||
}
|
||||
|
||||
/* pcmcia layer maps/unmaps mem regions */
|
||||
static int at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
|
||||
static int
|
||||
at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
|
||||
{
|
||||
struct at91_cf_socket *cf;
|
||||
|
||||
@ -218,12 +219,17 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
struct at91_cf_socket *cf;
|
||||
struct at91_cf_data *board = dev->platform_data;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *io;
|
||||
unsigned int csa;
|
||||
int status;
|
||||
|
||||
if (!board || !board->det_pin || !board->rst_pin)
|
||||
return -ENODEV;
|
||||
|
||||
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!io)
|
||||
return -ENODEV;
|
||||
|
||||
cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
|
||||
if (!cf)
|
||||
return -ENOMEM;
|
||||
@ -250,10 +256,14 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
* REVISIT: these timings are in terms of MCK cycles, so
|
||||
* when MCK changes (cpufreq etc) so must these values...
|
||||
*/
|
||||
at91_sys_write(AT91_SMC_CSR(4), AT91_SMC_ACSS_STD | AT91_SMC_DBW_16 | AT91_SMC_BAT | AT91_SMC_WSEN
|
||||
| AT91_SMC_NWS_(32) /* wait states */
|
||||
| AT91_SMC_RWSETUP_(6) /* setup time */
|
||||
| AT91_SMC_RWHOLD_(4) /* hold time */
|
||||
at91_sys_write(AT91_SMC_CSR(4),
|
||||
AT91_SMC_ACSS_STD
|
||||
| AT91_SMC_DBW_16
|
||||
| AT91_SMC_BAT
|
||||
| AT91_SMC_WSEN
|
||||
| AT91_SMC_NWS_(32) /* wait states */
|
||||
| AT91_SMC_RWSETUP_(6) /* setup time */
|
||||
| AT91_SMC_RWHOLD_(4) /* hold time */
|
||||
);
|
||||
|
||||
/* must be a GPIO; ergo must trigger on both edges */
|
||||
@ -274,8 +284,7 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
if (status < 0)
|
||||
goto fail0a;
|
||||
cf->socket.pci_irq = board->irq_pin;
|
||||
}
|
||||
else
|
||||
} else
|
||||
cf->socket.pci_irq = NR_IRQS + 1;
|
||||
|
||||
/* pcmcia layer only remaps "real" memory not iospace */
|
||||
@ -284,7 +293,8 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
goto fail1;
|
||||
|
||||
/* reserve CS4, CS5, and CS6 regions; but use just CS4 */
|
||||
if (!request_mem_region(AT91_CF_BASE, CF_SIZE, driver_name))
|
||||
if (!request_mem_region(io->start, io->end + 1 - io->start,
|
||||
driver_name))
|
||||
goto fail1;
|
||||
|
||||
pr_info("%s: irqs det #%d, io #%d\n", driver_name,
|
||||
@ -297,7 +307,7 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
|
||||
| SS_CAP_MEM_ALIGN;
|
||||
cf->socket.map_size = SZ_2K;
|
||||
cf->socket.io[0].NumPorts = SZ_2K;
|
||||
cf->socket.io[0].res = io;
|
||||
|
||||
status = pcmcia_register_socket(&cf->socket);
|
||||
if (status < 0)
|
||||
@ -307,7 +317,7 @@ static int __init at91_cf_probe(struct device *dev)
|
||||
|
||||
fail2:
|
||||
iounmap((void __iomem *) cf->socket.io_offset);
|
||||
release_mem_region(AT91_CF_BASE, CF_SIZE);
|
||||
release_mem_region(io->start, io->end + 1 - io->start);
|
||||
fail1:
|
||||
if (board->irq_pin)
|
||||
free_irq(board->irq_pin, cf);
|
||||
@ -321,14 +331,15 @@ fail0:
|
||||
|
||||
static int __exit at91_cf_remove(struct device *dev)
|
||||
{
|
||||
struct at91_cf_socket *cf = dev_get_drvdata(dev);
|
||||
unsigned int csa;
|
||||
struct at91_cf_socket *cf = dev_get_drvdata(dev);
|
||||
struct resource *io = cf->socket.io[0].res;
|
||||
unsigned int csa;
|
||||
|
||||
pcmcia_unregister_socket(&cf->socket);
|
||||
free_irq(cf->board->irq_pin, cf);
|
||||
free_irq(cf->board->det_pin, cf);
|
||||
iounmap((void __iomem *) cf->socket.io_offset);
|
||||
release_mem_region(AT91_CF_BASE, CF_SIZE);
|
||||
release_mem_region(io->start, io->end + 1 - io->start);
|
||||
|
||||
csa = at91_sys_read(AT91_EBI_CSA);
|
||||
at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
|
||||
@ -342,8 +353,8 @@ static struct device_driver at91_cf_driver = {
|
||||
.bus = &platform_bus_type,
|
||||
.probe = at91_cf_probe,
|
||||
.remove = __exit_p(at91_cf_remove),
|
||||
.suspend = pcmcia_socket_dev_suspend,
|
||||
.resume = pcmcia_socket_dev_resume,
|
||||
.suspend = pcmcia_socket_dev_suspend,
|
||||
.resume = pcmcia_socket_dev_resume,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -65,6 +65,7 @@
|
||||
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
|
||||
2.26.02.006 - Fix 9550SX pchip reset timeout.
|
||||
Add big endian support.
|
||||
2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -88,7 +89,7 @@
|
||||
#include "3w-9xxx.h"
|
||||
|
||||
/* Globals */
|
||||
#define TW_DRIVER_VERSION "2.26.02.006"
|
||||
#define TW_DRIVER_VERSION "2.26.02.007"
|
||||
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
|
||||
static unsigned int twa_device_extension_count;
|
||||
static int twa_major = -1;
|
||||
@ -1942,9 +1943,13 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
|
||||
}
|
||||
if (tw_dev->srb[request_id]->use_sg == 1) {
|
||||
struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
|
||||
char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
||||
char *buf;
|
||||
unsigned long flags = 0;
|
||||
local_irq_save(flags);
|
||||
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
||||
memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
|
||||
kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
} /* End twa_scsiop_execute_scsi_complete() */
|
||||
|
@ -1079,7 +1079,7 @@ config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
|
||||
memory using PCI DAC cycles.
|
||||
|
||||
config SCSI_SYM53C8XX_DEFAULT_TAGS
|
||||
int "default tagged command queue depth"
|
||||
int "Default tagged command queue depth"
|
||||
depends on SCSI_SYM53C8XX_2
|
||||
default "16"
|
||||
help
|
||||
@ -1090,7 +1090,7 @@ config SCSI_SYM53C8XX_DEFAULT_TAGS
|
||||
exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
|
||||
|
||||
config SCSI_SYM53C8XX_MAX_TAGS
|
||||
int "maximum number of queued commands"
|
||||
int "Maximum number of queued commands"
|
||||
depends on SCSI_SYM53C8XX_2
|
||||
default "64"
|
||||
help
|
||||
@ -1099,13 +1099,14 @@ config SCSI_SYM53C8XX_MAX_TAGS
|
||||
possible. The driver supports up to 256 queued commands per device.
|
||||
This value is used as a compiled-in hard limit.
|
||||
|
||||
config SCSI_SYM53C8XX_IOMAPPED
|
||||
bool "use port IO"
|
||||
config SCSI_SYM53C8XX_MMIO
|
||||
bool "Use memory mapped IO"
|
||||
depends on SCSI_SYM53C8XX_2
|
||||
default y
|
||||
help
|
||||
If you say Y here, the driver will use port IO to access
|
||||
the card. This is significantly slower then using memory
|
||||
mapped IO. Most people should answer N.
|
||||
Memory mapped IO is faster than Port IO. Most people should
|
||||
answer Y here, but some machines may have problems. If you have
|
||||
to answer N here, please report the problem to the maintainer.
|
||||
|
||||
config SCSI_IPR
|
||||
tristate "IBM Power Linux RAID adapter support"
|
||||
@ -1309,15 +1310,6 @@ config SCSI_QLOGIC_FAS
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called qlogicfas.
|
||||
|
||||
config SCSI_QLOGIC_FC
|
||||
tristate "Qlogic ISP FC SCSI support"
|
||||
depends on PCI && SCSI
|
||||
help
|
||||
This is a driver for the QLogic ISP2100 SCSI-FCP host adapter.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called qlogicfc.
|
||||
|
||||
config SCSI_QLOGIC_FC_FIRMWARE
|
||||
bool "Include loadable firmware in driver"
|
||||
depends on SCSI_QLOGIC_FC
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user