forked from Minki/linux
Merge /spare/repo/linux-2.6/
This commit is contained in:
commit
502c7f1dd5
288
Documentation/networking/phy.txt
Normal file
288
Documentation/networking/phy.txt
Normal file
@ -0,0 +1,288 @@
|
||||
|
||||
-------
|
||||
PHY Abstraction Layer
|
||||
(Updated 2005-07-21)
|
||||
|
||||
Purpose
|
||||
|
||||
Most network devices consist of set of registers which provide an interface
|
||||
to a MAC layer, which communicates with the physical connection through a
|
||||
PHY. The PHY concerns itself with negotiating link parameters with the link
|
||||
partner on the other side of the network connection (typically, an ethernet
|
||||
cable), and provides a register interface to allow drivers to determine what
|
||||
settings were chosen, and to configure what settings are allowed.
|
||||
|
||||
While these devices are distinct from the network devices, and conform to a
|
||||
standard layout for the registers, it has been common practice to integrate
|
||||
the PHY management code with the network driver. This has resulted in large
|
||||
amounts of redundant code. Also, on embedded systems with multiple (and
|
||||
sometimes quite different) ethernet controllers connected to the same
|
||||
management bus, it is difficult to ensure safe use of the bus.
|
||||
|
||||
Since the PHYs are devices, and the management busses through which they are
|
||||
accessed are, in fact, busses, the PHY Abstraction Layer treats them as such.
|
||||
In doing so, it has these goals:
|
||||
|
||||
1) Increase code-reuse
|
||||
2) Increase overall code-maintainability
|
||||
3) Speed development time for new network drivers, and for new systems
|
||||
|
||||
Basically, this layer is meant to provide an interface to PHY devices which
|
||||
allows network driver writers to write as little code as possible, while
|
||||
still providing a full feature set.
|
||||
|
||||
The MDIO bus
|
||||
|
||||
Most network devices are connected to a PHY by means of a management bus.
|
||||
Different devices use different busses (though some share common interfaces).
|
||||
In order to take advantage of the PAL, each bus interface needs to be
|
||||
registered as a distinct device.
|
||||
|
||||
1) read and write functions must be implemented. Their prototypes are:
|
||||
|
||||
int write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
|
||||
int read(struct mii_bus *bus, int mii_id, int regnum);
|
||||
|
||||
mii_id is the address on the bus for the PHY, and regnum is the register
|
||||
number. These functions are guaranteed not to be called from interrupt
|
||||
time, so it is safe for them to block, waiting for an interrupt to signal
|
||||
the operation is complete
|
||||
|
||||
2) A reset function is necessary. This is used to return the bus to an
|
||||
initialized state.
|
||||
|
||||
3) A probe function is needed. This function should set up anything the bus
|
||||
driver needs, setup the mii_bus structure, and register with the PAL using
|
||||
mdiobus_register. Similarly, there's a remove function to undo all of
|
||||
that (use mdiobus_unregister).
|
||||
|
||||
4) Like any driver, the device_driver structure must be configured, and init
|
||||
exit functions are used to register the driver.
|
||||
|
||||
5) The bus must also be declared somewhere as a device, and registered.
|
||||
|
||||
As an example for how one driver implemented an mdio bus driver, see
|
||||
drivers/net/gianfar_mii.c and arch/ppc/syslib/mpc85xx_devices.c
|
||||
|
||||
Connecting to a PHY
|
||||
|
||||
Sometime during startup, the network driver needs to establish a connection
|
||||
between the PHY device, and the network device. At this time, the PHY's bus
|
||||
and drivers need to all have been loaded, so it is ready for the connection.
|
||||
At this point, there are several ways to connect to the PHY:
|
||||
|
||||
1) The PAL handles everything, and only calls the network driver when
|
||||
the link state changes, so it can react.
|
||||
|
||||
2) The PAL handles everything except interrupts (usually because the
|
||||
controller has the interrupt registers).
|
||||
|
||||
3) The PAL handles everything, but checks in with the driver every second,
|
||||
allowing the network driver to react first to any changes before the PAL
|
||||
does.
|
||||
|
||||
4) The PAL serves only as a library of functions, with the network device
|
||||
manually calling functions to update status, and configure the PHY
|
||||
|
||||
|
||||
Letting the PHY Abstraction Layer do Everything
|
||||
|
||||
If you choose option 1 (The hope is that every driver can, but to still be
|
||||
useful to drivers that can't), connecting to the PHY is simple:
|
||||
|
||||
First, you need a function to react to changes in the link state. This
|
||||
function follows this protocol:
|
||||
|
||||
static void adjust_link(struct net_device *dev);
|
||||
|
||||
Next, you need to know the device name of the PHY connected to this device.
|
||||
The name will look something like, "phy0:0", where the first number is the
|
||||
bus id, and the second is the PHY's address on that bus.
|
||||
|
||||
Now, to connect, just call this function:
|
||||
|
||||
phydev = phy_connect(dev, phy_name, &adjust_link, flags);
|
||||
|
||||
phydev is a pointer to the phy_device structure which represents the PHY. If
|
||||
phy_connect is successful, it will return the pointer. dev, here, is the
|
||||
pointer to your net_device. Once done, this function will have started the
|
||||
PHY's software state machine, and registered for the PHY's interrupt, if it
|
||||
has one. The phydev structure will be populated with information about the
|
||||
current state, though the PHY will not yet be truly operational at this
|
||||
point.
|
||||
|
||||
flags is a u32 which can optionally contain phy-specific flags.
|
||||
This is useful if the system has put hardware restrictions on
|
||||
the PHY/controller, of which the PHY needs to be aware.
|
||||
|
||||
Now just make sure that phydev->supported and phydev->advertising have any
|
||||
values pruned from them which don't make sense for your controller (a 10/100
|
||||
controller may be connected to a gigabit capable PHY, so you would need to
|
||||
mask off SUPPORTED_1000baseT*). See include/linux/ethtool.h for definitions
|
||||
for these bitfields. Note that you should not SET any bits, or the PHY may
|
||||
get put into an unsupported state.
|
||||
|
||||
Lastly, once the controller is ready to handle network traffic, you call
|
||||
phy_start(phydev). This tells the PAL that you are ready, and configures the
|
||||
PHY to connect to the network. If you want to handle your own interrupts,
|
||||
just set phydev->irq to PHY_IGNORE_INTERRUPT before you call phy_start.
|
||||
Similarly, if you don't want to use interrupts, set phydev->irq to PHY_POLL.
|
||||
|
||||
When you want to disconnect from the network (even if just briefly), you call
|
||||
phy_stop(phydev).
|
||||
|
||||
Keeping Close Tabs on the PAL
|
||||
|
||||
It is possible that the PAL's built-in state machine needs a little help to
|
||||
keep your network device and the PHY properly in sync. If so, you can
|
||||
register a helper function when connecting to the PHY, which will be called
|
||||
every second before the state machine reacts to any changes. To do this, you
|
||||
need to manually call phy_attach() and phy_prepare_link(), and then call
|
||||
phy_start_machine() with the second argument set to point to your special
|
||||
handler.
|
||||
|
||||
Currently there are no examples of how to use this functionality, and testing
|
||||
on it has been limited because the author does not have any drivers which use
|
||||
it (they all use option 1). So Caveat Emptor.
|
||||
|
||||
Doing it all yourself
|
||||
|
||||
There's a remote chance that the PAL's built-in state machine cannot track
|
||||
the complex interactions between the PHY and your network device. If this is
|
||||
so, you can simply call phy_attach(), and not call phy_start_machine or
|
||||
phy_prepare_link(). This will mean that phydev->state is entirely yours to
|
||||
handle (phy_start and phy_stop toggle between some of the states, so you
|
||||
might need to avoid them).
|
||||
|
||||
An effort has been made to make sure that useful functionality can be
|
||||
accessed without the state-machine running, and most of these functions are
|
||||
descended from functions which did not interact with a complex state-machine.
|
||||
However, again, no effort has been made so far to test running without the
|
||||
state machine, so tryer beware.
|
||||
|
||||
Here is a brief rundown of the functions:
|
||||
|
||||
int phy_read(struct phy_device *phydev, u16 regnum);
|
||||
int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
|
||||
|
||||
Simple read/write primitives. They invoke the bus's read/write function
|
||||
pointers.
|
||||
|
||||
void phy_print_status(struct phy_device *phydev);
|
||||
|
||||
A convenience function to print out the PHY status neatly.
|
||||
|
||||
int phy_clear_interrupt(struct phy_device *phydev);
|
||||
int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
|
||||
|
||||
Clear the PHY's interrupt, and configure which ones are allowed,
|
||||
respectively. Currently only supports all on, or all off.
|
||||
|
||||
int phy_enable_interrupts(struct phy_device *phydev);
|
||||
int phy_disable_interrupts(struct phy_device *phydev);
|
||||
|
||||
Functions which enable/disable PHY interrupts, clearing them
|
||||
before and after, respectively.
|
||||
|
||||
int phy_start_interrupts(struct phy_device *phydev);
|
||||
int phy_stop_interrupts(struct phy_device *phydev);
|
||||
|
||||
Requests the IRQ for the PHY interrupts, then enables them for
|
||||
start, or disables then frees them for stop.
|
||||
|
||||
struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
|
||||
u32 flags);
|
||||
|
||||
Attaches a network device to a particular PHY, binding the PHY to a generic
|
||||
driver if none was found during bus initialization. Passes in
|
||||
any phy-specific flags as needed.
|
||||
|
||||
int phy_start_aneg(struct phy_device *phydev);
|
||||
|
||||
Using variables inside the phydev structure, either configures advertising
|
||||
and resets autonegotiation, or disables autonegotiation, and configures
|
||||
forced settings.
|
||||
|
||||
static inline int phy_read_status(struct phy_device *phydev);
|
||||
|
||||
Fills the phydev structure with up-to-date information about the current
|
||||
settings in the PHY.
|
||||
|
||||
void phy_sanitize_settings(struct phy_device *phydev)
|
||||
|
||||
Resolves differences between currently desired settings, and
|
||||
supported settings for the given PHY device. Does not make
|
||||
the changes in the hardware, though.
|
||||
|
||||
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
|
||||
Ethtool convenience functions.
|
||||
|
||||
int phy_mii_ioctl(struct phy_device *phydev,
|
||||
struct mii_ioctl_data *mii_data, int cmd);
|
||||
|
||||
The MII ioctl. Note that this function will completely screw up the state
|
||||
machine if you write registers like BMCR, BMSR, ADVERTISE, etc. Best to
|
||||
use this only to write registers which are not standard, and don't set off
|
||||
a renegotiation.
|
||||
|
||||
|
||||
PHY Device Drivers
|
||||
|
||||
With the PHY Abstraction Layer, adding support for new PHYs is
|
||||
quite easy. In some cases, no work is required at all! However,
|
||||
many PHYs require a little hand-holding to get up-and-running.
|
||||
|
||||
Generic PHY driver
|
||||
|
||||
If the desired PHY doesn't have any errata, quirks, or special
|
||||
features you want to support, then it may be best to not add
|
||||
support, and let the PHY Abstraction Layer's Generic PHY Driver
|
||||
do all of the work.
|
||||
|
||||
Writing a PHY driver
|
||||
|
||||
If you do need to write a PHY driver, the first thing to do is
|
||||
make sure it can be matched with an appropriate PHY device.
|
||||
This is done during bus initialization by reading the device's
|
||||
UID (stored in registers 2 and 3), then comparing it to each
|
||||
driver's phy_id field by ANDing it with each driver's
|
||||
phy_id_mask field. Also, it needs a name. Here's an example:
|
||||
|
||||
static struct phy_driver dm9161_driver = {
|
||||
.phy_id = 0x0181b880,
|
||||
.name = "Davicom DM9161E",
|
||||
.phy_id_mask = 0x0ffffff0,
|
||||
...
|
||||
}
|
||||
|
||||
Next, you need to specify what features (speed, duplex, autoneg,
|
||||
etc) your PHY device and driver support. Most PHYs support
|
||||
PHY_BASIC_FEATURES, but you can look in include/mii.h for other
|
||||
features.
|
||||
|
||||
Each driver consists of a number of function pointers:
|
||||
|
||||
config_init: configures PHY into a sane state after a reset.
|
||||
For instance, a Davicom PHY requires descrambling disabled.
|
||||
probe: Does any setup needed by the driver
|
||||
suspend/resume: power management
|
||||
config_aneg: Changes the speed/duplex/negotiation settings
|
||||
read_status: Reads the current speed/duplex/negotiation settings
|
||||
ack_interrupt: Clear a pending interrupt
|
||||
config_intr: Enable or disable interrupts
|
||||
remove: Does any driver take-down
|
||||
|
||||
Of these, only config_aneg and read_status are required to be
|
||||
assigned by the driver code. The rest are optional. Also, it is
|
||||
preferred to use the generic phy driver's versions of these two
|
||||
functions if at all possible: genphy_read_status and
|
||||
genphy_config_aneg. If this is not possible, it is likely that
|
||||
you only need to perform some actions before and after invoking
|
||||
these functions, and so your functions will wrap the generic
|
||||
ones.
|
||||
|
||||
Feel free to look at the Marvell, Cicada, and Davicom drivers in
|
||||
drivers/net/phy/ for examples (the lxt and qsemi drivers have
|
||||
not been tested as of this writing)
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 13
|
||||
EXTRAVERSION =
|
||||
NAME=Woozy Numbat
|
||||
NAME=Affluent Albatross
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
|
@ -566,13 +566,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (ka->sa.sa_flags & SA_RESETHAND)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -635,10 +635,6 @@ config PM
|
||||
and the Battery Powered Linux mini-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
Note that, even if you say N here, Linux on the x86 architecture
|
||||
will issue the hlt instruction if nothing is to be done, thereby
|
||||
sending the processor to sleep and saving power.
|
||||
|
||||
config APM
|
||||
tristate "Advanced Power Management Emulation"
|
||||
depends on PM
|
||||
@ -650,12 +646,6 @@ config APM
|
||||
battery status information, and user-space programs will receive
|
||||
notification of APM "events" (e.g. battery status change).
|
||||
|
||||
If you select "Y" here, you can disable actual use of the APM
|
||||
BIOS by passing the "apm=off" option to the kernel at boot time.
|
||||
|
||||
Note that the APM support is almost completely disabled for
|
||||
machines with more than one CPU.
|
||||
|
||||
In order to use APM, you will need supporting software. For location
|
||||
and more information, read <file:Documentation/pm.txt> and the
|
||||
Battery Powered Linux mini-HOWTO, available from
|
||||
@ -665,39 +655,12 @@ config APM
|
||||
manpage ("man 8 hdparm") for that), and it doesn't turn off
|
||||
VESA-compliant "green" monitors.
|
||||
|
||||
This driver does not support the TI 4000M TravelMate and the ACER
|
||||
486/DX4/75 because they don't have compliant BIOSes. Many "green"
|
||||
desktop machines also don't have compliant BIOSes, and this driver
|
||||
may cause those machines to panic during the boot phase.
|
||||
|
||||
Generally, if you don't have a battery in your machine, there isn't
|
||||
much point in using this driver and you should say N. If you get
|
||||
random kernel OOPSes or reboots that don't seem to be related to
|
||||
anything, try disabling/enabling this option (or disabling/enabling
|
||||
APM in your BIOS).
|
||||
|
||||
Some other things you should try when experiencing seemingly random,
|
||||
"weird" problems:
|
||||
|
||||
1) make sure that you have enough swap space and that it is
|
||||
enabled.
|
||||
2) pass the "no-hlt" option to the kernel
|
||||
3) switch on floating point emulation in the kernel and pass
|
||||
the "no387" option to the kernel
|
||||
4) pass the "floppy=nodma" option to the kernel
|
||||
5) pass the "mem=4M" option to the kernel (thereby disabling
|
||||
all but the first 4 MB of RAM)
|
||||
6) make sure that the CPU is not over clocked.
|
||||
7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
|
||||
8) disable the cache from your BIOS settings
|
||||
9) install a fan for the video card or exchange video RAM
|
||||
10) install a better fan for the CPU
|
||||
11) exchange RAM chips
|
||||
12) exchange the motherboard.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called apm.
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
@ -752,6 +715,8 @@ source "drivers/hwmon/Kconfig"
|
||||
|
||||
source "drivers/misc/Kconfig"
|
||||
|
||||
source "drivers/mfd/Kconfig"
|
||||
|
||||
source "drivers/media/Kconfig"
|
||||
|
||||
source "drivers/video/Kconfig"
|
||||
|
@ -1,6 +1,9 @@
|
||||
config ICST525
|
||||
bool
|
||||
|
||||
config ARM_GIC
|
||||
bool
|
||||
|
||||
config ICST307
|
||||
bool
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
obj-y += rtctime.o
|
||||
obj-$(CONFIG_ARM_AMBA) += amba.o
|
||||
obj-$(CONFIG_ARM_GIC) += gic.o
|
||||
obj-$(CONFIG_ICST525) += icst525.o
|
||||
obj-$(CONFIG_ICST307) += icst307.o
|
||||
obj-$(CONFIG_SA1111) += sa1111.o
|
||||
|
166
arch/arm/common/gic.c
Normal file
166
arch/arm/common/gic.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* linux/arch/arm/common/gic.c
|
||||
*
|
||||
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Interrupt architecture for the GIC:
|
||||
*
|
||||
* o There is one Interrupt Distributor, which receives interrupts
|
||||
* from system devices and sends them to the Interrupt Controllers.
|
||||
*
|
||||
* o There is one CPU Interface per CPU, which sends interrupts sent
|
||||
* by the Distributor, and interrupts generated locally, to the
|
||||
* associated CPU.
|
||||
*
|
||||
* Note that IRQs 0-31 are special - they are local to each CPU.
|
||||
* As such, the enable set/clear, pending set/clear and active bit
|
||||
* registers are banked per-cpu for these sources.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
static void __iomem *gic_dist_base;
|
||||
static void __iomem *gic_cpu_base;
|
||||
|
||||
/*
|
||||
* Routines to acknowledge, disable and enable interrupts
|
||||
*
|
||||
* Linux assumes that when we're done with an interrupt we need to
|
||||
* unmask it, in the same way we need to unmask an interrupt when
|
||||
* we first enable it.
|
||||
*
|
||||
* The GIC has a seperate notion of "end of interrupt" to re-enable
|
||||
* an interrupt after handling, in order to support hardware
|
||||
* prioritisation.
|
||||
*
|
||||
* We can make the GIC behave in the way that Linux expects by making
|
||||
* our "acknowledge" routine disable the interrupt, then mark it as
|
||||
* complete.
|
||||
*/
|
||||
static void gic_ack_irq(unsigned int irq)
|
||||
{
|
||||
u32 mask = 1 << (irq % 32);
|
||||
writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
|
||||
writel(irq, gic_cpu_base + GIC_CPU_EOI);
|
||||
}
|
||||
|
||||
static void gic_mask_irq(unsigned int irq)
|
||||
{
|
||||
u32 mask = 1 << (irq % 32);
|
||||
writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
|
||||
}
|
||||
|
||||
static void gic_unmask_irq(unsigned int irq)
|
||||
{
|
||||
u32 mask = 1 << (irq % 32);
|
||||
writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
|
||||
}
|
||||
|
||||
static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
|
||||
{
|
||||
void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
|
||||
unsigned int shift = (irq % 4) * 8;
|
||||
u32 val;
|
||||
|
||||
val = readl(reg) & ~(0xff << shift);
|
||||
val |= 1 << (cpu + shift);
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
static struct irqchip gic_chip = {
|
||||
.ack = gic_ack_irq,
|
||||
.mask = gic_mask_irq,
|
||||
.unmask = gic_unmask_irq,
|
||||
#ifdef CONFIG_SMP
|
||||
.set_cpu = gic_set_cpu,
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init gic_dist_init(void __iomem *base)
|
||||
{
|
||||
unsigned int max_irq, i;
|
||||
u32 cpumask = 1 << smp_processor_id();
|
||||
|
||||
cpumask |= cpumask << 8;
|
||||
cpumask |= cpumask << 16;
|
||||
|
||||
gic_dist_base = base;
|
||||
|
||||
writel(0, base + GIC_DIST_CTRL);
|
||||
|
||||
/*
|
||||
* Find out how many interrupts are supported.
|
||||
*/
|
||||
max_irq = readl(base + GIC_DIST_CTR) & 0x1f;
|
||||
max_irq = (max_irq + 1) * 32;
|
||||
|
||||
/*
|
||||
* The GIC only supports up to 1020 interrupt sources.
|
||||
* Limit this to either the architected maximum, or the
|
||||
* platform maximum.
|
||||
*/
|
||||
if (max_irq > max(1020, NR_IRQS))
|
||||
max_irq = max(1020, NR_IRQS);
|
||||
|
||||
/*
|
||||
* Set all global interrupts to be level triggered, active low.
|
||||
*/
|
||||
for (i = 32; i < max_irq; i += 16)
|
||||
writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
|
||||
|
||||
/*
|
||||
* Set all global interrupts to this CPU only.
|
||||
*/
|
||||
for (i = 32; i < max_irq; i += 4)
|
||||
writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
|
||||
|
||||
/*
|
||||
* Set priority on all interrupts.
|
||||
*/
|
||||
for (i = 0; i < max_irq; i += 4)
|
||||
writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
|
||||
|
||||
/*
|
||||
* Disable all interrupts.
|
||||
*/
|
||||
for (i = 0; i < max_irq; i += 32)
|
||||
writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
|
||||
|
||||
/*
|
||||
* Setup the Linux IRQ subsystem.
|
||||
*/
|
||||
for (i = 29; i < max_irq; i++) {
|
||||
set_irq_chip(i, &gic_chip);
|
||||
set_irq_handler(i, do_level_IRQ);
|
||||
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
|
||||
writel(1, base + GIC_DIST_CTRL);
|
||||
}
|
||||
|
||||
void __cpuinit gic_cpu_init(void __iomem *base)
|
||||
{
|
||||
gic_cpu_base = base;
|
||||
writel(0xf0, base + GIC_CPU_PRIMASK);
|
||||
writel(1, base + GIC_CPU_CTRL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
|
||||
{
|
||||
unsigned long map = *cpus_addr(cpumask);
|
||||
|
||||
writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
|
||||
}
|
||||
#endif
|
@ -658,11 +658,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
/*
|
||||
* Block the signal if we were unsuccessful.
|
||||
*/
|
||||
if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
if (ret != 0) {
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
sigorsets(&tsk->blocked, &tsk->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
sigaddset(&tsk->blocked, sig);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&tsk->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <asm/arch/assabet.h>
|
||||
#include <asm/arch/mcp.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -198,6 +199,11 @@ static struct irda_platform_data assabet_irda_data = {
|
||||
.set_speed = assabet_irda_set_speed,
|
||||
};
|
||||
|
||||
static struct mcp_plat_data assabet_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
static void __init assabet_init(void)
|
||||
{
|
||||
/*
|
||||
@ -246,6 +252,7 @@ static void __init assabet_init(void)
|
||||
sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources,
|
||||
ARRAY_SIZE(assabet_flash_resources));
|
||||
sa11x0_set_irda_data(&assabet_irda_data);
|
||||
sa11x0_set_mcp_data(&assabet_mcp_data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
#include <asm/arch/cerf.h>
|
||||
#include <asm/arch/mcp.h>
|
||||
#include "generic.h"
|
||||
|
||||
static struct resource cerfuart2_resources[] = {
|
||||
@ -116,10 +117,16 @@ static void __init cerf_map_io(void)
|
||||
GPDR |= CERF_GPIO_CF_RESET;
|
||||
}
|
||||
|
||||
static struct mcp_plat_data cerf_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
static void __init cerf_init(void)
|
||||
{
|
||||
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
|
||||
sa11x0_set_flash_data(&cerf_flash_data, &cerf_flash_resource, 1);
|
||||
sa11x0_set_mcp_data(&cerf_mcp_data);
|
||||
}
|
||||
|
||||
MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
|
||||
|
@ -221,6 +221,11 @@ static struct platform_device sa11x0mcp_device = {
|
||||
.resource = sa11x0mcp_resources,
|
||||
};
|
||||
|
||||
void sa11x0_set_mcp_data(struct mcp_plat_data *data)
|
||||
{
|
||||
sa11x0mcp_device.dev.platform_data = data;
|
||||
}
|
||||
|
||||
static struct resource sa11x0ssp_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80070000,
|
||||
|
@ -34,5 +34,8 @@ struct resource;
|
||||
extern void sa11x0_set_flash_data(struct flash_platform_data *flash,
|
||||
struct resource *res, int nr);
|
||||
|
||||
struct sa11x0_ssp_plat_ops;
|
||||
extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops);
|
||||
|
||||
struct irda_platform_data;
|
||||
void sa11x0_set_irda_data(struct irda_platform_data *irda);
|
||||
|
@ -13,12 +13,23 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <asm/arch/mcp.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
||||
#warning "include/asm/arch-sa1100/ide.h needs fixing for lart"
|
||||
|
||||
static struct mcp_plat_data lart_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
static void __init lart_init(void)
|
||||
{
|
||||
sa11x0_set_mcp_data(&lart_mcp_data);
|
||||
}
|
||||
|
||||
static struct map_desc lart_io_desc[] __initdata = {
|
||||
/* virtual physical length type */
|
||||
{ 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */
|
||||
@ -47,5 +58,6 @@ MACHINE_START(LART, "LART")
|
||||
.boot_params = 0xc0000100,
|
||||
.map_io = lart_map_io,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.init_machine = lart_init,
|
||||
.timer = &sa1100_timer,
|
||||
MACHINE_END
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <asm/arch/mcp.h>
|
||||
#include <asm/arch/shannon.h>
|
||||
|
||||
#include "generic.h"
|
||||
@ -52,9 +53,15 @@ static struct resource shannon_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct mcp_plat_data shannon_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
static void __init shannon_init(void)
|
||||
{
|
||||
sa11x0_set_flash_data(&shannon_flash_data, &shannon_flash_resource, 1);
|
||||
sa11x0_set_mcp_data(&shannon_mcp_data);
|
||||
}
|
||||
|
||||
static void __init shannon_map_io(void)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <asm/arch/mcp.h>
|
||||
#include <asm/arch/simpad.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
@ -123,6 +124,11 @@ static struct resource simpad_flash_resources [] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct mcp_plat_data simpad_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void __init simpad_map_io(void)
|
||||
@ -157,6 +163,7 @@ static void __init simpad_map_io(void)
|
||||
|
||||
sa11x0_set_flash_data(&simpad_flash_data, simpad_flash_resources,
|
||||
ARRAY_SIZE(simpad_flash_resources));
|
||||
sa11x0_set_mcp_data(&simpad_mcp_data);
|
||||
}
|
||||
|
||||
static void simpad_power_off(void)
|
||||
|
@ -454,14 +454,13 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
sigorsets(&tsk->blocked, &tsk->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
sigorsets(&tsk->blocked, &tsk->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&tsk->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -517,13 +517,12 @@ handle_signal(int canrestart, unsigned long sig,
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -568,13 +568,12 @@ handle_signal(int canrestart, unsigned long sig,
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -506,13 +506,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
} /* end handle_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -488,13 +488,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -577,10 +577,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
sigaddset(¤t->blocked,sig);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
@ -467,15 +467,12 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
|
||||
if (!setup_frame(sig, ka, info, oldset, scr))
|
||||
return 0;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
{
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
}
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -341,13 +341,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
/* Set up the stack frame */
|
||||
setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -732,13 +732,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -155,13 +155,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
setup_irix_frame(ka, regs, sig, oldset);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
|
@ -425,13 +425,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
setup_frame(ka, regs, sig, oldset);
|
||||
#endif
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
|
||||
|
@ -751,13 +751,12 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
setup_frame(ka, regs, sig, oldset);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
int do_signal32(sigset_t *oldset, struct pt_regs *regs)
|
||||
|
@ -517,13 +517,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
|
||||
return 0;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -759,13 +759,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
else
|
||||
handle_signal(signr, &ka, &info, oldset, regs, newsp);
|
||||
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask);
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -481,10 +481,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
/* Set up Signal Frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
sigaddset(¤t->blocked,sig);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
@ -976,11 +976,12 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
|
||||
else
|
||||
ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp);
|
||||
|
||||
if (ret && !(ka.sa.sa_flags & SA_NODEFER)) {
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka.sa.sa_mask);
|
||||
sigaddset(¤t->blocked, signr);
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
@ -637,12 +637,11 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame32(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
|
@ -429,13 +429,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -546,13 +546,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -664,13 +664,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/root_dev.h>
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
|
@ -1034,13 +1034,12 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame(&ka->sa, regs, signr, oldset, info);
|
||||
}
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/mostek.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/profile.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/mostek.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/memreg.h>
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/vac-ops.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <asm/visasm.h>
|
||||
#include <asm/estate.h>
|
||||
#include <asm/auxio.h>
|
||||
#include <asm/sfafsr.h>
|
||||
|
||||
#define curptr g6
|
||||
|
||||
@ -690,79 +691,102 @@ netbsd_syscall:
|
||||
retl
|
||||
nop
|
||||
|
||||
/* These next few routines must be sure to clear the
|
||||
* SFSR FaultValid bit so that the fast tlb data protection
|
||||
* handler does not flush the wrong context and lock up the
|
||||
* box.
|
||||
/* We need to carefully read the error status, ACK
|
||||
* the errors, prevent recursive traps, and pass the
|
||||
* information on to C code for logging.
|
||||
*
|
||||
* We pass the AFAR in as-is, and we encode the status
|
||||
* information as described in asm-sparc64/sfafsr.h
|
||||
*/
|
||||
.globl __do_data_access_exception
|
||||
.globl __do_data_access_exception_tl1
|
||||
__do_data_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
.globl __spitfire_access_error
|
||||
__spitfire_access_error:
|
||||
/* Disable ESTATE error reporting so that we do not
|
||||
* take recursive traps and RED state the processor.
|
||||
*/
|
||||
stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
ba,pt %xcc, winfix_dax
|
||||
rdpr %tpc, %g3
|
||||
__do_data_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call data_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
.globl __do_instruction_access_exception
|
||||
.globl __do_instruction_access_exception_tl1
|
||||
__do_instruction_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
mov UDBE_UE, %g1
|
||||
ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
|
||||
|
||||
/* __spitfire_cee_trap branches here with AFSR in %g4 and
|
||||
* UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the
|
||||
* ESTATE Error Enable register.
|
||||
*/
|
||||
__spitfire_cee_trap_continue:
|
||||
ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
|
||||
|
||||
rdpr %tt, %g3
|
||||
and %g3, 0x1ff, %g3 ! Paranoia
|
||||
sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
|
||||
or %g4, %g3, %g4
|
||||
rdpr %tl, %g3
|
||||
cmp %g3, 1
|
||||
mov 1, %g3
|
||||
bleu %xcc, 1f
|
||||
sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
|
||||
|
||||
or %g4, %g3, %g4
|
||||
|
||||
/* Read in the UDB error register state, clearing the
|
||||
* sticky error bits as-needed. We only clear them if
|
||||
* the UE bit is set. Likewise, __spitfire_cee_trap
|
||||
* below will only do so if the CE bit is set.
|
||||
*
|
||||
* NOTE: UltraSparc-I/II have high and low UDB error
|
||||
* registers, corresponding to the two UDB units
|
||||
* present on those chips. UltraSparc-IIi only
|
||||
* has a single UDB, called "SDB" in the manual.
|
||||
* For IIi the upper UDB register always reads
|
||||
* as zero so for our purposes things will just
|
||||
* work with the checks below.
|
||||
*/
|
||||
1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
|
||||
and %g3, 0x3ff, %g7 ! Paranoia
|
||||
sllx %g7, SFSTAT_UDBH_SHIFT, %g7
|
||||
or %g4, %g7, %g4
|
||||
andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
|
||||
be,pn %xcc, 1f
|
||||
nop
|
||||
stxa %g3, [%g0] ASI_UDB_ERROR_W
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
|
||||
1: mov 0x18, %g3
|
||||
ldxa [%g3] ASI_UDBL_ERROR_R, %g3
|
||||
and %g3, 0x3ff, %g7 ! Paranoia
|
||||
sllx %g7, SFSTAT_UDBL_SHIFT, %g7
|
||||
or %g4, %g7, %g4
|
||||
andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
|
||||
be,pn %xcc, 1f
|
||||
nop
|
||||
mov 0x18, %g7
|
||||
stxa %g3, [%g7] ASI_UDB_ERROR_W
|
||||
membar #Sync
|
||||
|
||||
1: /* Ok, now that we've latched the error state,
|
||||
* clear the sticky bits in the AFSR.
|
||||
*/
|
||||
stxa %g4, [%g0] ASI_AFSR
|
||||
membar #Sync
|
||||
|
||||
rdpr %tl, %g2
|
||||
cmp %g2, 1
|
||||
rdpr %pil, %g2
|
||||
bleu,pt %xcc, 1f
|
||||
wrpr %g0, 15, %pil
|
||||
|
||||
ba,pt %xcc, etraptl1
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call instruction_access_exception_tl1
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
rd %pc, %g7
|
||||
|
||||
__do_instruction_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
ba,pt %xcc, 2f
|
||||
nop
|
||||
|
||||
1: ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
|
||||
2: mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call instruction_access_exception
|
||||
call spitfire_access_error
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
@ -784,79 +808,124 @@ __do_instruction_access_exception:
|
||||
* as it is the only situation where we can safely record
|
||||
* and log. For trap level >1 we just clear the CE bit
|
||||
* in the AFSR and return.
|
||||
*/
|
||||
|
||||
/* Our trap handling infrastructure allows us to preserve
|
||||
* two 64-bit values during etrap for arguments to
|
||||
* subsequent C code. Therefore we encode the information
|
||||
* as follows:
|
||||
*
|
||||
* value 1) Full 64-bits of AFAR
|
||||
* value 2) Low 33-bits of AFSR, then bits 33-->42
|
||||
* are UDBL error status and bits 43-->52
|
||||
* are UDBH error status
|
||||
* This is just like __spiftire_access_error above, but it
|
||||
* specifically handles correctable errors. If an
|
||||
* uncorrectable error is indicated in the AFSR we
|
||||
* will branch directly above to __spitfire_access_error
|
||||
* to handle it instead. Uncorrectable therefore takes
|
||||
* priority over correctable, and the error logging
|
||||
* C code will notice this case by inspecting the
|
||||
* trap type.
|
||||
*/
|
||||
.align 64
|
||||
.globl cee_trap
|
||||
cee_trap:
|
||||
ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
|
||||
ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
|
||||
sllx %g1, 31, %g1 ! Clear reserved bits
|
||||
srlx %g1, 31, %g1 ! in AFSR
|
||||
.globl __spitfire_cee_trap
|
||||
__spitfire_cee_trap:
|
||||
ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
|
||||
mov 1, %g3
|
||||
sllx %g3, SFAFSR_UE_SHIFT, %g3
|
||||
andcc %g4, %g3, %g0 ! Check for UE
|
||||
bne,pn %xcc, __spitfire_access_error
|
||||
nop
|
||||
|
||||
/* NOTE: UltraSparc-I/II have high and low UDB error
|
||||
* registers, corresponding to the two UDB units
|
||||
* present on those chips. UltraSparc-IIi only
|
||||
* has a single UDB, called "SDB" in the manual.
|
||||
* For IIi the upper UDB register always reads
|
||||
* as zero so for our purposes things will just
|
||||
* work with the checks below.
|
||||
/* Ok, in this case we only have a correctable error.
|
||||
* Indicate we only wish to capture that state in register
|
||||
* %g1, and we only disable CE error reporting unlike UE
|
||||
* handling which disables all errors.
|
||||
*/
|
||||
ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
|
||||
andcc %g3, (1 << 8), %g4 ! Check CE bit
|
||||
sllx %g3, (64 - 10), %g3 ! Clear reserved bits
|
||||
srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
|
||||
ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
|
||||
andn %g3, ESTATE_ERR_CE, %g3
|
||||
stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
|
||||
or %g1, %g3, %g1 ! Or it in
|
||||
be,pn %xcc, 1f ! Branch if CE bit was clear
|
||||
/* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
|
||||
ba,pt %xcc, __spitfire_cee_trap_continue
|
||||
mov UDBE_CE, %g1
|
||||
|
||||
.globl __spitfire_data_access_exception
|
||||
.globl __spitfire_data_access_exception_tl1
|
||||
__spitfire_data_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
membar #Sync
|
||||
rdpr %tt, %g3
|
||||
cmp %g3, 0x80 ! first win spill/fill trap
|
||||
blu,pn %xcc, 1f
|
||||
cmp %g3, 0xff ! last win spill/fill trap
|
||||
bgu,pn %xcc, 1f
|
||||
nop
|
||||
stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
|
||||
membar #Sync ! Synchronize ASI stores
|
||||
1: mov 0x18, %g5 ! Addr of UDB-High error status
|
||||
ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
|
||||
ba,pt %xcc, winfix_dax
|
||||
rdpr %tpc, %g3
|
||||
1: sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_data_access_exception_tl1
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
andcc %g3, (1 << 8), %g4 ! Check CE bit
|
||||
sllx %g3, (64 - 10), %g3 ! Clear reserved bits
|
||||
srlx %g3, (64 - 10), %g3 ! in UDB-High error status
|
||||
sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
|
||||
or %g1, %g3, %g1 ! Or it in
|
||||
be,pn %xcc, 1f ! Branch if CE bit was clear
|
||||
nop
|
||||
nop
|
||||
__spitfire_data_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_data_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
|
||||
membar #Sync ! Synchronize ASI stores
|
||||
1: mov 1, %g5 ! AFSR CE bit is
|
||||
sllx %g5, 20, %g5 ! bit 20
|
||||
stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
|
||||
membar #Sync ! Synchronize ASI stores
|
||||
sllx %g2, (64 - 41), %g2 ! Clear reserved bits
|
||||
srlx %g2, (64 - 41), %g2 ! in latched AFAR
|
||||
.globl __spitfire_insn_access_exception
|
||||
.globl __spitfire_insn_access_exception_tl1
|
||||
__spitfire_insn_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
|
||||
rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_insn_access_exception_tl1
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
andn %g2, 0x0f, %g2 ! Finish resv bit clearing
|
||||
mov %g1, %g4 ! Move AFSR+UDB* into save reg
|
||||
mov %g2, %g5 ! Move AFAR into save reg
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
mov %l4, %o0
|
||||
|
||||
mov %l5, %o1
|
||||
call cee_log
|
||||
add %sp, PTREGS_OFF, %o2
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
__spitfire_insn_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
|
||||
rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_insn_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
/* Capture I/D/E-cache state into per-cpu error scoreboard.
|
||||
*
|
||||
|
@ -466,7 +466,7 @@ do_flush_sync:
|
||||
if (!limit)
|
||||
break;
|
||||
udelay(1);
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
if (!limit)
|
||||
printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
|
||||
|
@ -103,7 +103,7 @@ void cpu_idle(void)
|
||||
* other cpus see our increasing idleness for the buddy
|
||||
* redistribution algorithm. -DaveM
|
||||
*/
|
||||
membar("#StoreStore | #StoreLoad");
|
||||
membar_storeload_storestore();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long
|
||||
if (!limit)
|
||||
break;
|
||||
udelay(1);
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
if (!limit)
|
||||
printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
|
@ -574,13 +574,12 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
|
||||
{
|
||||
setup_rt_frame(ka, regs, signr, oldset,
|
||||
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||
sigaddset(¤t->blocked,signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
|
@ -877,11 +877,12 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
unsigned long page = (unsigned long)
|
||||
page_address(pte_page(*ptep));
|
||||
|
||||
__asm__ __volatile__(
|
||||
" membar #StoreStore\n"
|
||||
" flush %0 + %1"
|
||||
: : "r" (page), "r" (address & (PAGE_SIZE - 1))
|
||||
: "memory");
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0 + %1"
|
||||
: /* no outputs */
|
||||
: "r" (page),
|
||||
"r" (address & (PAGE_SIZE - 1))
|
||||
: "memory");
|
||||
}
|
||||
pte_unmap(ptep);
|
||||
preempt_enable();
|
||||
@ -1292,11 +1293,12 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
unsigned long page = (unsigned long)
|
||||
page_address(pte_page(*ptep));
|
||||
|
||||
__asm__ __volatile__(
|
||||
" membar #StoreStore\n"
|
||||
" flush %0 + %1"
|
||||
: : "r" (page), "r" (address & (PAGE_SIZE - 1))
|
||||
: "memory");
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0 + %1"
|
||||
: /* no outputs */
|
||||
: "r" (page),
|
||||
"r" (address & (PAGE_SIZE - 1))
|
||||
: "memory");
|
||||
}
|
||||
pte_unmap(ptep);
|
||||
preempt_enable();
|
||||
@ -1325,13 +1327,12 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame32(&ka->sa, regs, signr, oldset, info);
|
||||
}
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||
sigaddset(¤t->blocked,signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
|
||||
|
@ -144,7 +144,7 @@ void __init smp_callin(void)
|
||||
current->active_mm = &init_mm;
|
||||
|
||||
while (!cpu_isset(cpuid, smp_commenced_mask))
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
|
||||
cpu_set(cpuid, cpu_online_map);
|
||||
}
|
||||
@ -184,11 +184,11 @@ static inline long get_delta (long *rt, long *master)
|
||||
for (i = 0; i < NUM_ITERS; i++) {
|
||||
t0 = tick_ops->get_tick();
|
||||
go[MASTER] = 1;
|
||||
membar("#StoreLoad");
|
||||
membar_storeload();
|
||||
while (!(tm = go[SLAVE]))
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
go[SLAVE] = 0;
|
||||
membar("#StoreStore");
|
||||
wmb();
|
||||
t1 = tick_ops->get_tick();
|
||||
|
||||
if (t1 - t0 < best_t1 - best_t0)
|
||||
@ -221,7 +221,7 @@ void smp_synchronize_tick_client(void)
|
||||
go[MASTER] = 1;
|
||||
|
||||
while (go[MASTER])
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
|
||||
local_irq_save(flags);
|
||||
{
|
||||
@ -273,21 +273,21 @@ static void smp_synchronize_one_tick(int cpu)
|
||||
|
||||
/* wait for client to be ready */
|
||||
while (!go[MASTER])
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
|
||||
/* now let the client proceed into his loop */
|
||||
go[MASTER] = 0;
|
||||
membar("#StoreLoad");
|
||||
membar_storeload();
|
||||
|
||||
spin_lock_irqsave(&itc_sync_lock, flags);
|
||||
{
|
||||
for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) {
|
||||
while (!go[MASTER])
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
go[MASTER] = 0;
|
||||
membar("#StoreStore");
|
||||
wmb();
|
||||
go[SLAVE] = tick_ops->get_tick();
|
||||
membar("#StoreLoad");
|
||||
membar_storeload();
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&itc_sync_lock, flags);
|
||||
@ -927,11 +927,11 @@ void smp_capture(void)
|
||||
smp_processor_id());
|
||||
#endif
|
||||
penguins_are_doing_time = 1;
|
||||
membar("#StoreStore | #LoadStore");
|
||||
membar_storestore_loadstore();
|
||||
atomic_inc(&smp_capture_registry);
|
||||
smp_cross_call(&xcall_capture, 0, 0, 0);
|
||||
while (atomic_read(&smp_capture_registry) != ncpus)
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
#ifdef CAPTURE_DEBUG
|
||||
printk("done\n");
|
||||
#endif
|
||||
@ -947,7 +947,7 @@ void smp_release(void)
|
||||
smp_processor_id());
|
||||
#endif
|
||||
penguins_are_doing_time = 0;
|
||||
membar("#StoreStore | #StoreLoad");
|
||||
membar_storeload_storestore();
|
||||
atomic_dec(&smp_capture_registry);
|
||||
}
|
||||
}
|
||||
@ -970,9 +970,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
|
||||
save_alternate_globals(global_save);
|
||||
prom_world(1);
|
||||
atomic_inc(&smp_capture_registry);
|
||||
membar("#StoreLoad | #StoreStore");
|
||||
membar_storeload_storestore();
|
||||
while (penguins_are_doing_time)
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
restore_alternate_globals(global_save);
|
||||
atomic_dec(&smp_capture_registry);
|
||||
prom_world(0);
|
||||
|
@ -99,17 +99,6 @@ extern int __ashrdi3(int, int);
|
||||
extern void dump_thread(struct pt_regs *, struct user *);
|
||||
extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK)
|
||||
extern void _do_spin_lock (spinlock_t *lock, char *str);
|
||||
extern void _do_spin_unlock (spinlock_t *lock);
|
||||
extern int _spin_trylock (spinlock_t *lock);
|
||||
extern void _do_read_lock(rwlock_t *rw, char *str);
|
||||
extern void _do_read_unlock(rwlock_t *rw, char *str);
|
||||
extern void _do_write_lock(rwlock_t *rw, char *str);
|
||||
extern void _do_write_unlock(rwlock_t *rw);
|
||||
extern int _do_write_trylock(rwlock_t *rw, char *str);
|
||||
#endif
|
||||
|
||||
extern unsigned long phys_base;
|
||||
extern unsigned long pfn_base;
|
||||
|
||||
@ -152,18 +141,6 @@ EXPORT_SYMBOL(_mcount);
|
||||
EXPORT_SYMBOL(cpu_online_map);
|
||||
EXPORT_SYMBOL(phys_cpu_present_map);
|
||||
|
||||
/* Spinlock debugging library, optional. */
|
||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||
EXPORT_SYMBOL(_do_spin_lock);
|
||||
EXPORT_SYMBOL(_do_spin_unlock);
|
||||
EXPORT_SYMBOL(_spin_trylock);
|
||||
EXPORT_SYMBOL(_do_read_lock);
|
||||
EXPORT_SYMBOL(_do_read_unlock);
|
||||
EXPORT_SYMBOL(_do_write_lock);
|
||||
EXPORT_SYMBOL(_do_write_unlock);
|
||||
EXPORT_SYMBOL(_do_write_trylock);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(smp_call_function);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
@ -429,3 +406,12 @@ EXPORT_SYMBOL(xor_vis_4);
|
||||
EXPORT_SYMBOL(xor_vis_5);
|
||||
|
||||
EXPORT_SYMBOL(prom_palette);
|
||||
|
||||
/* memory barriers */
|
||||
EXPORT_SYMBOL(mb);
|
||||
EXPORT_SYMBOL(rmb);
|
||||
EXPORT_SYMBOL(wmb);
|
||||
EXPORT_SYMBOL(membar_storeload);
|
||||
EXPORT_SYMBOL(membar_storeload_storestore);
|
||||
EXPORT_SYMBOL(membar_storeload_loadload);
|
||||
EXPORT_SYMBOL(membar_storestore_loadstore);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <asm/dcu.h>
|
||||
#include <asm/estate.h>
|
||||
#include <asm/chafsr.h>
|
||||
#include <asm/sfafsr.h>
|
||||
#include <asm/psrcompat.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/timer.h>
|
||||
@ -143,8 +144,7 @@ void do_BUG(const char *file, int line)
|
||||
}
|
||||
#endif
|
||||
|
||||
void instruction_access_exception(struct pt_regs *regs,
|
||||
unsigned long sfsr, unsigned long sfar)
|
||||
void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
@ -153,8 +153,8 @@ void instruction_access_exception(struct pt_regs *regs,
|
||||
return;
|
||||
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
|
||||
sfsr, sfar);
|
||||
printk("spitfire_insn_access_exception: SFSR[%016lx] "
|
||||
"SFAR[%016lx], going.\n", sfsr, sfar);
|
||||
die_if_kernel("Iax", regs);
|
||||
}
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
@ -169,19 +169,17 @@ void instruction_access_exception(struct pt_regs *regs,
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
}
|
||||
|
||||
void instruction_access_exception_tl1(struct pt_regs *regs,
|
||||
unsigned long sfsr, unsigned long sfar)
|
||||
void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
|
||||
0, 0x8, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
|
||||
instruction_access_exception(regs, sfsr, sfar);
|
||||
spitfire_insn_access_exception(regs, sfsr, sfar);
|
||||
}
|
||||
|
||||
void data_access_exception(struct pt_regs *regs,
|
||||
unsigned long sfsr, unsigned long sfar)
|
||||
void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
@ -207,8 +205,8 @@ void data_access_exception(struct pt_regs *regs,
|
||||
return;
|
||||
}
|
||||
/* Shit... */
|
||||
printk("data_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
|
||||
sfsr, sfar);
|
||||
printk("spitfire_data_access_exception: SFSR[%016lx] "
|
||||
"SFAR[%016lx], going.\n", sfsr, sfar);
|
||||
die_if_kernel("Dax", regs);
|
||||
}
|
||||
|
||||
@ -220,6 +218,16 @@ void data_access_exception(struct pt_regs *regs,
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
}
|
||||
|
||||
void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
|
||||
0, 0x30, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
|
||||
spitfire_data_access_exception(regs, sfsr, sfar);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* This is really pathetic... */
|
||||
extern volatile int pci_poke_in_progress;
|
||||
@ -253,54 +261,13 @@ static void spitfire_clean_and_reenable_l1_caches(void)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
void do_iae(struct pt_regs *regs)
|
||||
static void spitfire_enable_estate_errors(void)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
spitfire_clean_and_reenable_l1_caches();
|
||||
|
||||
if (notify_die(DIE_TRAP, "instruction access exception", regs,
|
||||
0, 0x8, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_OBJERR;
|
||||
info.si_addr = (void *)0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
}
|
||||
|
||||
void do_dae(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
|
||||
spitfire_clean_and_reenable_l1_caches();
|
||||
|
||||
pci_poke_faulted = 1;
|
||||
|
||||
/* Why the fuck did they have to change this? */
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus)
|
||||
regs->tpc += 4;
|
||||
|
||||
regs->tnpc = regs->tpc + 4;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
spitfire_clean_and_reenable_l1_caches();
|
||||
|
||||
if (notify_die(DIE_TRAP, "data access exception", regs,
|
||||
0, 0x30, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_OBJERR;
|
||||
info.si_addr = (void *)0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
__asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (ESTATE_ERR_ALL),
|
||||
"i" (ASI_ESTATE_ERROR_EN));
|
||||
}
|
||||
|
||||
static char ecc_syndrome_table[] = {
|
||||
@ -338,65 +305,15 @@ static char ecc_syndrome_table[] = {
|
||||
0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
|
||||
};
|
||||
|
||||
/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
|
||||
* in the following format. The AFAR is left as is, with
|
||||
* reserved bits cleared, and is a raw 40-bit physical
|
||||
* address.
|
||||
*/
|
||||
#define CE_STATUS_UDBH_UE (1UL << (43 + 9))
|
||||
#define CE_STATUS_UDBH_CE (1UL << (43 + 8))
|
||||
#define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
|
||||
#define CE_STATUS_UDBH_SHIFT 43
|
||||
#define CE_STATUS_UDBL_UE (1UL << (33 + 9))
|
||||
#define CE_STATUS_UDBL_CE (1UL << (33 + 8))
|
||||
#define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
|
||||
#define CE_STATUS_UDBL_SHIFT 33
|
||||
#define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
|
||||
#define CE_STATUS_AFSR_ME (1UL << 32)
|
||||
#define CE_STATUS_AFSR_PRIV (1UL << 31)
|
||||
#define CE_STATUS_AFSR_ISAP (1UL << 30)
|
||||
#define CE_STATUS_AFSR_ETP (1UL << 29)
|
||||
#define CE_STATUS_AFSR_IVUE (1UL << 28)
|
||||
#define CE_STATUS_AFSR_TO (1UL << 27)
|
||||
#define CE_STATUS_AFSR_BERR (1UL << 26)
|
||||
#define CE_STATUS_AFSR_LDP (1UL << 25)
|
||||
#define CE_STATUS_AFSR_CP (1UL << 24)
|
||||
#define CE_STATUS_AFSR_WP (1UL << 23)
|
||||
#define CE_STATUS_AFSR_EDP (1UL << 22)
|
||||
#define CE_STATUS_AFSR_UE (1UL << 21)
|
||||
#define CE_STATUS_AFSR_CE (1UL << 20)
|
||||
#define CE_STATUS_AFSR_ETS (0xfUL << 16)
|
||||
#define CE_STATUS_AFSR_ETS_SHIFT 16
|
||||
#define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
|
||||
#define CE_STATUS_AFSR_PSYND_SHIFT 0
|
||||
|
||||
/* Layout of Ecache TAG Parity Syndrome of AFSR */
|
||||
#define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
|
||||
#define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
|
||||
#define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
|
||||
#define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
|
||||
|
||||
static char *syndrome_unknown = "<Unknown>";
|
||||
|
||||
asmlinkage void cee_log(unsigned long ce_status,
|
||||
unsigned long afar,
|
||||
struct pt_regs *regs)
|
||||
static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
|
||||
{
|
||||
char memmod_str[64];
|
||||
char *p;
|
||||
unsigned short scode, udb_reg;
|
||||
unsigned short scode;
|
||||
char memmod_str[64], *p;
|
||||
|
||||
printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
|
||||
"AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",
|
||||
smp_processor_id(),
|
||||
(ce_status & CE_STATUS_AFSR_MASK),
|
||||
afar,
|
||||
((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
|
||||
((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
|
||||
|
||||
udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
|
||||
if (udb_reg & (1 << 8)) {
|
||||
scode = ecc_syndrome_table[udb_reg & 0xff];
|
||||
if (udbl & bit) {
|
||||
scode = ecc_syndrome_table[udbl & 0xff];
|
||||
if (prom_getunumber(scode, afar,
|
||||
memmod_str, sizeof(memmod_str)) == -1)
|
||||
p = syndrome_unknown;
|
||||
@ -407,9 +324,8 @@ asmlinkage void cee_log(unsigned long ce_status,
|
||||
smp_processor_id(), scode, p);
|
||||
}
|
||||
|
||||
udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);
|
||||
if (udb_reg & (1 << 8)) {
|
||||
scode = ecc_syndrome_table[udb_reg & 0xff];
|
||||
if (udbh & bit) {
|
||||
scode = ecc_syndrome_table[udbh & 0xff];
|
||||
if (prom_getunumber(scode, afar,
|
||||
memmod_str, sizeof(memmod_str)) == -1)
|
||||
p = syndrome_unknown;
|
||||
@ -419,6 +335,127 @@ asmlinkage void cee_log(unsigned long ce_status,
|
||||
"Memory Module \"%s\"\n",
|
||||
smp_processor_id(), scode, p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
|
||||
"AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
|
||||
smp_processor_id(), afsr, afar, udbl, udbh, tl1);
|
||||
|
||||
spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
|
||||
|
||||
/* We always log it, even if someone is listening for this
|
||||
* trap.
|
||||
*/
|
||||
notify_die(DIE_TRAP, "Correctable ECC Error", regs,
|
||||
0, TRAP_TYPE_CEE, SIGTRAP);
|
||||
|
||||
/* The Correctable ECC Error trap does not disable I/D caches. So
|
||||
* we only have to restore the ESTATE Error Enable register.
|
||||
*/
|
||||
spitfire_enable_estate_errors();
|
||||
}
|
||||
|
||||
static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
|
||||
"AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
|
||||
smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
|
||||
|
||||
/* XXX add more human friendly logging of the error status
|
||||
* XXX as is implemented for cheetah
|
||||
*/
|
||||
|
||||
spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
|
||||
|
||||
/* We always log it, even if someone is listening for this
|
||||
* trap.
|
||||
*/
|
||||
notify_die(DIE_TRAP, "Uncorrectable Error", regs,
|
||||
0, tt, SIGTRAP);
|
||||
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
if (tl1)
|
||||
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
|
||||
die_if_kernel("UE", regs);
|
||||
}
|
||||
|
||||
/* XXX need more intelligent processing here, such as is implemented
|
||||
* XXX for cheetah errors, in fact if the E-cache still holds the
|
||||
* XXX line with bad parity this will loop
|
||||
*/
|
||||
|
||||
spitfire_clean_and_reenable_l1_caches();
|
||||
spitfire_enable_estate_errors();
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_OBJERR;
|
||||
info.si_addr = (void *)0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
}
|
||||
|
||||
void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
|
||||
{
|
||||
unsigned long afsr, tt, udbh, udbl;
|
||||
int tl1;
|
||||
|
||||
afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
|
||||
tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
|
||||
tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
|
||||
udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
|
||||
udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (tt == TRAP_TYPE_DAE &&
|
||||
pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
|
||||
spitfire_clean_and_reenable_l1_caches();
|
||||
spitfire_enable_estate_errors();
|
||||
|
||||
pci_poke_faulted = 1;
|
||||
regs->tnpc = regs->tpc + 4;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (afsr & SFAFSR_UE)
|
||||
spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
|
||||
|
||||
if (tt == TRAP_TYPE_CEE) {
|
||||
/* Handle the case where we took a CEE trap, but ACK'd
|
||||
* only the UE state in the UDB error registers.
|
||||
*/
|
||||
if (afsr & SFAFSR_UE) {
|
||||
if (udbh & UDBE_CE) {
|
||||
__asm__ __volatile__(
|
||||
"stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (udbh & UDBE_CE),
|
||||
"r" (0x0), "i" (ASI_UDB_ERROR_W));
|
||||
}
|
||||
if (udbl & UDBE_CE) {
|
||||
__asm__ __volatile__(
|
||||
"stxa %0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (udbl & UDBE_CE),
|
||||
"r" (0x18), "i" (ASI_UDB_ERROR_W));
|
||||
}
|
||||
}
|
||||
|
||||
spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
|
||||
}
|
||||
}
|
||||
|
||||
int cheetah_pcache_forced_on;
|
||||
|
@ -18,9 +18,10 @@ sparc64_ttable_tl0:
|
||||
tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
|
||||
tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
|
||||
tl0_iax: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__do_instruction_access_exception)
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception)
|
||||
tl0_resv009: BTRAP(0x9)
|
||||
tl0_iae: TRAP(do_iae)
|
||||
tl0_iae: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||
tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
|
||||
tl0_ill: membar #Sync
|
||||
TRAP_7INSNS(do_illegal_instruction)
|
||||
@ -36,9 +37,10 @@ tl0_cwin: CLEAN_WINDOW
|
||||
tl0_div0: TRAP(do_div0)
|
||||
tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
|
||||
tl0_resv02f: BTRAP(0x2f)
|
||||
tl0_dax: TRAP_NOSAVE(__do_data_access_exception)
|
||||
tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
|
||||
tl0_resv031: BTRAP(0x31)
|
||||
tl0_dae: TRAP(do_dae)
|
||||
tl0_dae: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||
tl0_resv033: BTRAP(0x33)
|
||||
tl0_mna: TRAP_NOSAVE(do_mna)
|
||||
tl0_lddfmna: TRAP_NOSAVE(do_lddfmna)
|
||||
@ -73,7 +75,8 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)
|
||||
tl0_ivec: TRAP_IVEC
|
||||
tl0_paw: TRAP(do_paw)
|
||||
tl0_vaw: TRAP(do_vaw)
|
||||
tl0_cee: TRAP_NOSAVE(cee_trap)
|
||||
tl0_cee: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_cee_trap)
|
||||
tl0_iamiss:
|
||||
#include "itlb_base.S"
|
||||
tl0_damiss:
|
||||
@ -175,9 +178,10 @@ tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
|
||||
sparc64_ttable_tl1:
|
||||
tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3)
|
||||
tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7)
|
||||
tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1)
|
||||
tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
|
||||
tl1_resv009: BTRAPTL1(0x9)
|
||||
tl1_iae: TRAPTL1(do_iae_tl1)
|
||||
tl1_iae: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||
tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
|
||||
tl1_ill: TRAPTL1(do_ill_tl1)
|
||||
tl1_privop: BTRAPTL1(0x11)
|
||||
@ -193,9 +197,10 @@ tl1_cwin: CLEAN_WINDOW
|
||||
tl1_div0: TRAPTL1(do_div0_tl1)
|
||||
tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
|
||||
tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
|
||||
tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1)
|
||||
tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
|
||||
tl1_resv031: BTRAPTL1(0x31)
|
||||
tl1_dae: TRAPTL1(do_dae_tl1)
|
||||
tl1_dae: membar #Sync
|
||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||
tl1_resv033: BTRAPTL1(0x33)
|
||||
tl1_mna: TRAP_NOSAVE(do_mna)
|
||||
tl1_lddfmna: TRAPTL1(do_lddfmna_tl1)
|
||||
@ -219,8 +224,8 @@ tl1_paw: TRAPTL1(do_paw_tl1)
|
||||
tl1_vaw: TRAPTL1(do_vaw_tl1)
|
||||
|
||||
/* The grotty trick to save %g1 into current->thread.cee_stuff
|
||||
* is because when we take this trap we could be interrupting trap
|
||||
* code already using the trap alternate global registers.
|
||||
* is because when we take this trap we could be interrupting
|
||||
* trap code already using the trap alternate global registers.
|
||||
*
|
||||
* We cross our fingers and pray that this store/load does
|
||||
* not cause yet another CEE trap.
|
||||
|
@ -349,9 +349,9 @@ int handle_popc(u32 insn, struct pt_regs *regs)
|
||||
|
||||
extern void do_fpother(struct pt_regs *regs);
|
||||
extern void do_privact(struct pt_regs *regs);
|
||||
extern void data_access_exception(struct pt_regs *regs,
|
||||
unsigned long sfsr,
|
||||
unsigned long sfar);
|
||||
extern void spitfire_data_access_exception(struct pt_regs *regs,
|
||||
unsigned long sfsr,
|
||||
unsigned long sfar);
|
||||
|
||||
int handle_ldf_stq(u32 insn, struct pt_regs *regs)
|
||||
{
|
||||
@ -394,14 +394,14 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
data_access_exception(regs, 0, addr);
|
||||
spitfire_data_access_exception(regs, 0, addr);
|
||||
return 1;
|
||||
}
|
||||
if (put_user (first >> 32, (u32 __user *)addr) ||
|
||||
__put_user ((u32)first, (u32 __user *)(addr + 4)) ||
|
||||
__put_user (second >> 32, (u32 __user *)(addr + 8)) ||
|
||||
__put_user ((u32)second, (u32 __user *)(addr + 12))) {
|
||||
data_access_exception(regs, 0, addr);
|
||||
spitfire_data_access_exception(regs, 0, addr);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
@ -414,7 +414,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
|
||||
do_privact(regs);
|
||||
return 1;
|
||||
} else if (asi > ASI_SNFL) {
|
||||
data_access_exception(regs, 0, addr);
|
||||
spitfire_data_access_exception(regs, 0, addr);
|
||||
return 1;
|
||||
}
|
||||
switch (insn & 0x180000) {
|
||||
@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
|
||||
err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
|
||||
}
|
||||
if (err && !(asi & 0x2 /* NF */)) {
|
||||
data_access_exception(regs, 0, addr);
|
||||
spitfire_data_access_exception(regs, 0, addr);
|
||||
return 1;
|
||||
}
|
||||
if (asi & 0x8) /* Little */ {
|
||||
@ -534,7 +534,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
|
||||
*(u64 *)(f->regs + freg) = value;
|
||||
current_thread_info()->fpsaved[0] |= flag;
|
||||
} else {
|
||||
daex: data_access_exception(regs, sfsr, sfar);
|
||||
daex: spitfire_data_access_exception(regs, sfsr, sfar);
|
||||
return;
|
||||
}
|
||||
advance(regs);
|
||||
@ -578,7 +578,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
|
||||
__put_user ((u32)value, (u32 __user *)(sfar + 4)))
|
||||
goto daex;
|
||||
} else {
|
||||
daex: data_access_exception(regs, sfsr, sfar);
|
||||
daex: spitfire_data_access_exception(regs, sfsr, sfar);
|
||||
return;
|
||||
}
|
||||
advance(regs);
|
||||
|
@ -318,7 +318,7 @@ fill_fixup_dax:
|
||||
nop
|
||||
rdpr %pstate, %l1 ! Prepare to change globals.
|
||||
mov %g4, %o1 ! Setup args for
|
||||
mov %g5, %o2 ! final call to data_access_exception.
|
||||
mov %g5, %o2 ! final call to spitfire_data_access_exception.
|
||||
andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
|
||||
|
||||
mov %g6, %o7 ! Stash away current.
|
||||
@ -330,7 +330,7 @@ fill_fixup_dax:
|
||||
mov TSB_REG, %g1
|
||||
ldxa [%g1] ASI_IMMU, %g5
|
||||
#endif
|
||||
call data_access_exception
|
||||
call spitfire_data_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
b,pt %xcc, rtrap
|
||||
@ -391,7 +391,7 @@ window_dax_from_user_common:
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call data_access_exception
|
||||
call spitfire_data_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
@ -12,7 +12,7 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
|
||||
U1memcpy.o U1copy_from_user.o U1copy_to_user.o \
|
||||
U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
|
||||
copy_in_user.o user_fixup.o memmove.o \
|
||||
mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
|
||||
mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o mb.o
|
||||
|
||||
lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
|
||||
lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC))
|
||||
|
||||
static inline void show (char *str, spinlock_t *lock, unsigned long caller)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
@ -51,20 +49,19 @@ static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
|
||||
#undef INIT_STUCK
|
||||
#define INIT_STUCK 100000000
|
||||
|
||||
void _do_spin_lock(spinlock_t *lock, char *str)
|
||||
void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int stuck = INIT_STUCK;
|
||||
int cpu = get_cpu();
|
||||
int shown = 0;
|
||||
|
||||
GET_CALLER(caller);
|
||||
again:
|
||||
__asm__ __volatile__("ldstub [%1], %0"
|
||||
: "=r" (val)
|
||||
: "r" (&(lock->lock))
|
||||
: "memory");
|
||||
membar("#StoreLoad | #StoreStore");
|
||||
membar_storeload_storestore();
|
||||
if (val) {
|
||||
while (lock->lock) {
|
||||
if (!--stuck) {
|
||||
@ -72,7 +69,7 @@ again:
|
||||
show(str, lock, caller);
|
||||
stuck = INIT_STUCK;
|
||||
}
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
@ -84,17 +81,16 @@ again:
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
int _do_spin_trylock(spinlock_t *lock)
|
||||
int _do_spin_trylock(spinlock_t *lock, unsigned long caller)
|
||||
{
|
||||
unsigned long val, caller;
|
||||
unsigned long val;
|
||||
int cpu = get_cpu();
|
||||
|
||||
GET_CALLER(caller);
|
||||
__asm__ __volatile__("ldstub [%1], %0"
|
||||
: "=r" (val)
|
||||
: "r" (&(lock->lock))
|
||||
: "memory");
|
||||
membar("#StoreLoad | #StoreStore");
|
||||
membar_storeload_storestore();
|
||||
if (!val) {
|
||||
lock->owner_pc = ((unsigned int)caller);
|
||||
lock->owner_cpu = cpu;
|
||||
@ -111,21 +107,20 @@ void _do_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
lock->owner_pc = 0;
|
||||
lock->owner_cpu = NO_PROC_ID;
|
||||
membar("#StoreStore | #LoadStore");
|
||||
membar_storestore_loadstore();
|
||||
lock->lock = 0;
|
||||
current->thread.smp_lock_count--;
|
||||
}
|
||||
|
||||
/* Keep INIT_STUCK the same... */
|
||||
|
||||
void _do_read_lock (rwlock_t *rw, char *str)
|
||||
void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int stuck = INIT_STUCK;
|
||||
int cpu = get_cpu();
|
||||
int shown = 0;
|
||||
|
||||
GET_CALLER(caller);
|
||||
wlock_again:
|
||||
/* Wait for any writer to go away. */
|
||||
while (((long)(rw->lock)) < 0) {
|
||||
@ -134,7 +129,7 @@ wlock_again:
|
||||
show_read(str, rw, caller);
|
||||
stuck = INIT_STUCK;
|
||||
}
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
/* Try once to increment the counter. */
|
||||
__asm__ __volatile__(
|
||||
@ -147,7 +142,7 @@ wlock_again:
|
||||
"2:" : "=r" (val)
|
||||
: "0" (&(rw->lock))
|
||||
: "g1", "g7", "memory");
|
||||
membar("#StoreLoad | #StoreStore");
|
||||
membar_storeload_storestore();
|
||||
if (val)
|
||||
goto wlock_again;
|
||||
rw->reader_pc[cpu] = ((unsigned int)caller);
|
||||
@ -157,15 +152,13 @@ wlock_again:
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void _do_read_unlock (rwlock_t *rw, char *str)
|
||||
void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int stuck = INIT_STUCK;
|
||||
int cpu = get_cpu();
|
||||
int shown = 0;
|
||||
|
||||
GET_CALLER(caller);
|
||||
|
||||
/* Drop our identity _first_. */
|
||||
rw->reader_pc[cpu] = 0;
|
||||
current->thread.smp_lock_count--;
|
||||
@ -193,14 +186,13 @@ runlock_again:
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void _do_write_lock (rwlock_t *rw, char *str)
|
||||
void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int stuck = INIT_STUCK;
|
||||
int cpu = get_cpu();
|
||||
int shown = 0;
|
||||
|
||||
GET_CALLER(caller);
|
||||
wlock_again:
|
||||
/* Spin while there is another writer. */
|
||||
while (((long)rw->lock) < 0) {
|
||||
@ -209,7 +201,7 @@ wlock_again:
|
||||
show_write(str, rw, caller);
|
||||
stuck = INIT_STUCK;
|
||||
}
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
|
||||
/* Try to acuire the write bit. */
|
||||
@ -264,7 +256,7 @@ wlock_again:
|
||||
show_write(str, rw, caller);
|
||||
stuck = INIT_STUCK;
|
||||
}
|
||||
membar("#LoadLoad");
|
||||
rmb();
|
||||
}
|
||||
goto wlock_again;
|
||||
}
|
||||
@ -278,14 +270,12 @@ wlock_again:
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void _do_write_unlock(rwlock_t *rw)
|
||||
void _do_write_unlock(rwlock_t *rw, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int stuck = INIT_STUCK;
|
||||
int shown = 0;
|
||||
|
||||
GET_CALLER(caller);
|
||||
|
||||
/* Drop our identity _first_ */
|
||||
rw->writer_pc = 0;
|
||||
rw->writer_cpu = NO_PROC_ID;
|
||||
@ -313,13 +303,11 @@ wlock_again:
|
||||
}
|
||||
}
|
||||
|
||||
int _do_write_trylock (rwlock_t *rw, char *str)
|
||||
int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller)
|
||||
{
|
||||
unsigned long caller, val;
|
||||
unsigned long val;
|
||||
int cpu = get_cpu();
|
||||
|
||||
GET_CALLER(caller);
|
||||
|
||||
/* Try to acuire the write bit. */
|
||||
__asm__ __volatile__(
|
||||
" mov 1, %%g3\n"
|
||||
|
73
arch/sparc64/lib/mb.S
Normal file
73
arch/sparc64/lib/mb.S
Normal file
@ -0,0 +1,73 @@
|
||||
/* mb.S: Out of line memory barriers.
|
||||
*
|
||||
* Copyright (C) 2005 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
|
||||
/* These are here in an effort to more fully work around
|
||||
* Spitfire Errata #51. Essentially, if a memory barrier
|
||||
* occurs soon after a mispredicted branch, the chip can stop
|
||||
* executing instructions until a trap occurs. Therefore, if
|
||||
* interrupts are disabled, the chip can hang forever.
|
||||
*
|
||||
* It used to be believed that the memory barrier had to be
|
||||
* right in the delay slot, but a case has been traced
|
||||
* recently wherein the memory barrier was one instruction
|
||||
* after the branch delay slot and the chip still hung. The
|
||||
* offending sequence was the following in sym_wakeup_done()
|
||||
* of the sym53c8xx_2 driver:
|
||||
*
|
||||
* call sym_ccb_from_dsa, 0
|
||||
* movge %icc, 0, %l0
|
||||
* brz,pn %o0, .LL1303
|
||||
* mov %o0, %l2
|
||||
* membar #LoadLoad
|
||||
*
|
||||
* The branch has to be mispredicted for the bug to occur.
|
||||
* Therefore, we put the memory barrier explicitly into a
|
||||
* "branch always, predicted taken" delay slot to avoid the
|
||||
* problem case.
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
99: retl
|
||||
nop
|
||||
|
||||
.globl mb
|
||||
mb: ba,pt %xcc, 99b
|
||||
membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad
|
||||
.size mb, .-mb
|
||||
|
||||
.globl rmb
|
||||
rmb: ba,pt %xcc, 99b
|
||||
membar #LoadLoad
|
||||
.size rmb, .-rmb
|
||||
|
||||
.globl wmb
|
||||
wmb: ba,pt %xcc, 99b
|
||||
membar #StoreStore
|
||||
.size wmb, .-wmb
|
||||
|
||||
.globl membar_storeload
|
||||
membar_storeload:
|
||||
ba,pt %xcc, 99b
|
||||
membar #StoreLoad
|
||||
.size membar_storeload, .-membar_storeload
|
||||
|
||||
.globl membar_storeload_storestore
|
||||
membar_storeload_storestore:
|
||||
ba,pt %xcc, 99b
|
||||
membar #StoreLoad | #StoreStore
|
||||
.size membar_storeload_storestore, .-membar_storeload_storestore
|
||||
|
||||
.globl membar_storeload_loadload
|
||||
membar_storeload_loadload:
|
||||
ba,pt %xcc, 99b
|
||||
membar #StoreLoad | #LoadLoad
|
||||
.size membar_storeload_loadload, .-membar_storeload_loadload
|
||||
|
||||
.globl membar_storestore_loadstore
|
||||
membar_storestore_loadstore:
|
||||
ba,pt %xcc, 99b
|
||||
membar #StoreStore | #LoadStore
|
||||
.size membar_storestore_loadstore, .-membar_storestore_loadstore
|
@ -737,7 +737,8 @@ MODULE_LICENSE("GPL");
|
||||
extern u32 tl0_solaris[8];
|
||||
#define update_ttable(x) \
|
||||
tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
|
||||
__asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3]))
|
||||
wmb(); \
|
||||
__asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
|
||||
#else
|
||||
#endif
|
||||
|
||||
@ -761,7 +762,8 @@ int init_module(void)
|
||||
entry64_personality_patch |=
|
||||
(offsetof(struct task_struct, personality) +
|
||||
(sizeof(unsigned long) - 1));
|
||||
__asm__ __volatile__("membar #StoreStore; flush %0"
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0"
|
||||
: : "r" (&entry64_personality_patch));
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,12 +87,12 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
force_sigsegv(signr, current);
|
||||
}
|
||||
else if(!(ka->sa.sa_flags & SA_NODEFER)){
|
||||
} else {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
sigaddset(¤t->blocked, signr);
|
||||
if(!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
@ -462,13 +462,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -394,10 +394,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
#endif
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
sigaddset(¤t->blocked,sig);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
@ -702,12 +702,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
if (ka.sa.sa_flags & SA_ONESHOT)
|
||||
ka.sa.sa_handler = SIG_DFL;
|
||||
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER)) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask);
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
return 1;
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ source "drivers/hwmon/Kconfig"
|
||||
|
||||
source "drivers/misc/Kconfig"
|
||||
|
||||
source "drivers/mfd/Kconfig"
|
||||
|
||||
source "drivers/media/Kconfig"
|
||||
|
||||
source "drivers/video/Kconfig"
|
||||
|
@ -26,7 +26,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/
|
||||
obj-$(CONFIG_SERIO) += input/serio/
|
||||
obj-y += serial/
|
||||
obj-$(CONFIG_PARPORT) += parport/
|
||||
obj-y += base/ block/ misc/ net/ media/
|
||||
obj-y += base/ block/ misc/ mfd/ net/ media/
|
||||
obj-$(CONFIG_NUBUS) += nubus/
|
||||
obj-$(CONFIG_ATM) += atm/
|
||||
obj-$(CONFIG_PPC_PMAC) += macintosh/
|
||||
|
@ -1,5 +1,3 @@
|
||||
EXTRA_CFLAGS += -Idrivers/infiniband/include
|
||||
|
||||
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
|
||||
ib_cm.o ib_umad.o ib_ucm.o
|
||||
obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -40,7 +41,7 @@
|
||||
|
||||
#include <asm/bug.h>
|
||||
|
||||
#include <ib_smi.h>
|
||||
#include <rdma/ib_smi.h>
|
||||
|
||||
#include "smi.h"
|
||||
#include "agent_priv.h"
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
|
@ -1,5 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -32,12 +35,11 @@
|
||||
* $Id: cache.c 1349 2004-12-16 21:09:43Z roland $
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <ib_cache.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
#include "core_priv.h"
|
||||
|
||||
|
@ -43,8 +43,8 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <ib_cache.h>
|
||||
#include <ib_cm.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
#include <rdma/ib_cm.h>
|
||||
#include "cm_msgs.h"
|
||||
|
||||
MODULE_AUTHOR("Sean Hefty");
|
||||
@ -83,7 +83,7 @@ struct cm_port {
|
||||
struct cm_device {
|
||||
struct list_head list;
|
||||
struct ib_device *device;
|
||||
u64 ca_guid;
|
||||
__be64 ca_guid;
|
||||
struct cm_port port[0];
|
||||
};
|
||||
|
||||
@ -100,8 +100,8 @@ struct cm_work {
|
||||
struct list_head list;
|
||||
struct cm_port *port;
|
||||
struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */
|
||||
u32 local_id; /* Established / timewait */
|
||||
u32 remote_id;
|
||||
__be32 local_id; /* Established / timewait */
|
||||
__be32 remote_id;
|
||||
struct ib_cm_event cm_event;
|
||||
struct ib_sa_path_rec path[0];
|
||||
};
|
||||
@ -110,8 +110,8 @@ struct cm_timewait_info {
|
||||
struct cm_work work; /* Must be first. */
|
||||
struct rb_node remote_qp_node;
|
||||
struct rb_node remote_id_node;
|
||||
u64 remote_ca_guid;
|
||||
u32 remote_qpn;
|
||||
__be64 remote_ca_guid;
|
||||
__be32 remote_qpn;
|
||||
u8 inserted_remote_qp;
|
||||
u8 inserted_remote_id;
|
||||
};
|
||||
@ -132,11 +132,11 @@ struct cm_id_private {
|
||||
struct cm_av alt_av;
|
||||
|
||||
void *private_data;
|
||||
u64 tid;
|
||||
u32 local_qpn;
|
||||
u32 remote_qpn;
|
||||
u32 sq_psn;
|
||||
u32 rq_psn;
|
||||
__be64 tid;
|
||||
__be32 local_qpn;
|
||||
__be32 remote_qpn;
|
||||
__be32 sq_psn;
|
||||
__be32 rq_psn;
|
||||
int timeout_ms;
|
||||
enum ib_mtu path_mtu;
|
||||
u8 private_data_len;
|
||||
@ -253,7 +253,7 @@ static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
|
||||
u16 dlid, u8 sl, u16 src_path_bits)
|
||||
{
|
||||
memset(ah_attr, 0, sizeof ah_attr);
|
||||
ah_attr->dlid = be16_to_cpu(dlid);
|
||||
ah_attr->dlid = dlid;
|
||||
ah_attr->sl = sl;
|
||||
ah_attr->src_path_bits = src_path_bits;
|
||||
ah_attr->port_num = port_num;
|
||||
@ -264,7 +264,7 @@ static void cm_init_av_for_response(struct cm_port *port,
|
||||
{
|
||||
av->port = port;
|
||||
av->pkey_index = wc->pkey_index;
|
||||
cm_set_ah_attr(&av->ah_attr, port->port_num, cpu_to_be16(wc->slid),
|
||||
cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
|
||||
wc->sl, wc->dlid_path_bits);
|
||||
}
|
||||
|
||||
@ -295,8 +295,9 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
|
||||
return ret;
|
||||
|
||||
av->port = port;
|
||||
cm_set_ah_attr(&av->ah_attr, av->port->port_num, path->dlid,
|
||||
path->sl, path->slid & 0x7F);
|
||||
cm_set_ah_attr(&av->ah_attr, av->port->port_num,
|
||||
be16_to_cpu(path->dlid), path->sl,
|
||||
be16_to_cpu(path->slid) & 0x7F);
|
||||
av->packet_life_time = path->packet_life_time;
|
||||
return 0;
|
||||
}
|
||||
@ -309,26 +310,26 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
|
||||
do {
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
|
||||
(int *) &cm_id_priv->id.local_id);
|
||||
(__force int *) &cm_id_priv->id.local_id);
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cm_free_id(u32 local_id)
|
||||
static void cm_free_id(__be32 local_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
idr_remove(&cm.local_id_table, (int) local_id);
|
||||
idr_remove(&cm.local_id_table, (__force int) local_id);
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
}
|
||||
|
||||
static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
|
||||
static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv;
|
||||
|
||||
cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
|
||||
cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id);
|
||||
if (cm_id_priv) {
|
||||
if (cm_id_priv->id.remote_id == remote_id)
|
||||
atomic_inc(&cm_id_priv->refcount);
|
||||
@ -339,7 +340,7 @@ static struct cm_id_private * cm_get_id(u32 local_id, u32 remote_id)
|
||||
return cm_id_priv;
|
||||
}
|
||||
|
||||
static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
|
||||
static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv;
|
||||
unsigned long flags;
|
||||
@ -356,8 +357,8 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
|
||||
struct rb_node **link = &cm.listen_service_table.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
struct cm_id_private *cur_cm_id_priv;
|
||||
u64 service_id = cm_id_priv->id.service_id;
|
||||
u64 service_mask = cm_id_priv->id.service_mask;
|
||||
__be64 service_id = cm_id_priv->id.service_id;
|
||||
__be64 service_mask = cm_id_priv->id.service_mask;
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
@ -376,7 +377,7 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct cm_id_private * cm_find_listen(u64 service_id)
|
||||
static struct cm_id_private * cm_find_listen(__be64 service_id)
|
||||
{
|
||||
struct rb_node *node = cm.listen_service_table.rb_node;
|
||||
struct cm_id_private *cm_id_priv;
|
||||
@ -400,8 +401,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
|
||||
struct rb_node **link = &cm.remote_id_table.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
struct cm_timewait_info *cur_timewait_info;
|
||||
u64 remote_ca_guid = timewait_info->remote_ca_guid;
|
||||
u32 remote_id = timewait_info->work.remote_id;
|
||||
__be64 remote_ca_guid = timewait_info->remote_ca_guid;
|
||||
__be32 remote_id = timewait_info->work.remote_id;
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
@ -424,8 +425,8 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct cm_timewait_info * cm_find_remote_id(u64 remote_ca_guid,
|
||||
u32 remote_id)
|
||||
static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
|
||||
__be32 remote_id)
|
||||
{
|
||||
struct rb_node *node = cm.remote_id_table.rb_node;
|
||||
struct cm_timewait_info *timewait_info;
|
||||
@ -453,8 +454,8 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
|
||||
struct rb_node **link = &cm.remote_qp_table.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
struct cm_timewait_info *cur_timewait_info;
|
||||
u64 remote_ca_guid = timewait_info->remote_ca_guid;
|
||||
u32 remote_qpn = timewait_info->remote_qpn;
|
||||
__be64 remote_ca_guid = timewait_info->remote_ca_guid;
|
||||
__be32 remote_qpn = timewait_info->remote_qpn;
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
@ -484,7 +485,7 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
|
||||
struct rb_node *parent = NULL;
|
||||
struct cm_id_private *cur_cm_id_priv;
|
||||
union ib_gid *port_gid = &cm_id_priv->av.dgid;
|
||||
u32 remote_id = cm_id_priv->id.remote_id;
|
||||
__be32 remote_id = cm_id_priv->id.remote_id;
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
@ -598,7 +599,7 @@ static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
}
|
||||
|
||||
static struct cm_timewait_info * cm_create_timewait_info(u32 local_id)
|
||||
static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
|
||||
{
|
||||
struct cm_timewait_info *timewait_info;
|
||||
|
||||
@ -715,14 +716,15 @@ retest:
|
||||
EXPORT_SYMBOL(ib_destroy_cm_id);
|
||||
|
||||
int ib_cm_listen(struct ib_cm_id *cm_id,
|
||||
u64 service_id,
|
||||
u64 service_mask)
|
||||
__be64 service_id,
|
||||
__be64 service_mask)
|
||||
{
|
||||
struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
service_mask = service_mask ? service_mask : ~0ULL;
|
||||
service_mask = service_mask ? service_mask :
|
||||
__constant_cpu_to_be64(~0ULL);
|
||||
service_id &= service_mask;
|
||||
if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID &&
|
||||
(service_id != IB_CM_ASSIGN_SERVICE_ID))
|
||||
@ -735,8 +737,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
|
||||
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
if (service_id == IB_CM_ASSIGN_SERVICE_ID) {
|
||||
cm_id->service_id = __cpu_to_be64(cm.listen_service_id++);
|
||||
cm_id->service_mask = ~0ULL;
|
||||
cm_id->service_id = cpu_to_be64(cm.listen_service_id++);
|
||||
cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
|
||||
} else {
|
||||
cm_id->service_id = service_id;
|
||||
cm_id->service_mask = service_mask;
|
||||
@ -752,18 +754,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_cm_listen);
|
||||
|
||||
static u64 cm_form_tid(struct cm_id_private *cm_id_priv,
|
||||
enum cm_msg_sequence msg_seq)
|
||||
static __be64 cm_form_tid(struct cm_id_private *cm_id_priv,
|
||||
enum cm_msg_sequence msg_seq)
|
||||
{
|
||||
u64 hi_tid, low_tid;
|
||||
|
||||
hi_tid = ((u64) cm_id_priv->av.port->mad_agent->hi_tid) << 32;
|
||||
low_tid = (u64) (cm_id_priv->id.local_id | (msg_seq << 30));
|
||||
low_tid = (u64) ((__force u32)cm_id_priv->id.local_id |
|
||||
(msg_seq << 30));
|
||||
return cpu_to_be64(hi_tid | low_tid);
|
||||
}
|
||||
|
||||
static void cm_format_mad_hdr(struct ib_mad_hdr *hdr,
|
||||
enum cm_msg_attr_id attr_id, u64 tid)
|
||||
__be16 attr_id, __be64 tid)
|
||||
{
|
||||
hdr->base_version = IB_MGMT_BASE_VERSION;
|
||||
hdr->mgmt_class = IB_MGMT_CLASS_CM;
|
||||
@ -896,7 +899,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
|
||||
goto error1;
|
||||
}
|
||||
cm_id->service_id = param->service_id;
|
||||
cm_id->service_mask = ~0ULL;
|
||||
cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
|
||||
cm_id_priv->timeout_ms = cm_convert_to_ms(
|
||||
param->primary_path->packet_life_time) * 2 +
|
||||
cm_convert_to_ms(
|
||||
@ -963,7 +966,7 @@ static int cm_issue_rej(struct cm_port *port,
|
||||
rej_msg->remote_comm_id = rcv_msg->local_comm_id;
|
||||
rej_msg->local_comm_id = rcv_msg->remote_comm_id;
|
||||
cm_rej_set_msg_rejected(rej_msg, msg_rejected);
|
||||
rej_msg->reason = reason;
|
||||
rej_msg->reason = cpu_to_be16(reason);
|
||||
|
||||
if (ari && ari_length) {
|
||||
cm_rej_set_reject_info_len(rej_msg, ari_length);
|
||||
@ -977,8 +980,8 @@ static int cm_issue_rej(struct cm_port *port,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int cm_is_active_peer(u64 local_ca_guid, u64 remote_ca_guid,
|
||||
u32 local_qpn, u32 remote_qpn)
|
||||
static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
|
||||
__be32 local_qpn, __be32 remote_qpn)
|
||||
{
|
||||
return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||
|
||||
((local_ca_guid == remote_ca_guid) &&
|
||||
@ -1137,7 +1140,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
|
||||
break;
|
||||
}
|
||||
|
||||
rej_msg->reason = reason;
|
||||
rej_msg->reason = cpu_to_be16(reason);
|
||||
if (ari && ari_length) {
|
||||
cm_rej_set_reject_info_len(rej_msg, ari_length);
|
||||
memcpy(rej_msg->ari, ari, ari_length);
|
||||
@ -1276,7 +1279,7 @@ static int cm_req_handler(struct cm_work *work)
|
||||
cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
|
||||
cm_id_priv->id.context = listen_cm_id_priv->id.context;
|
||||
cm_id_priv->id.service_id = req_msg->service_id;
|
||||
cm_id_priv->id.service_mask = ~0ULL;
|
||||
cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
|
||||
|
||||
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
|
||||
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
|
||||
@ -1969,7 +1972,7 @@ static void cm_format_rej_event(struct cm_work *work)
|
||||
param = &work->cm_event.param.rej_rcvd;
|
||||
param->ari = rej_msg->ari;
|
||||
param->ari_length = cm_rej_get_reject_info_len(rej_msg);
|
||||
param->reason = rej_msg->reason;
|
||||
param->reason = __be16_to_cpu(rej_msg->reason);
|
||||
work->cm_event.private_data = &rej_msg->private_data;
|
||||
}
|
||||
|
||||
@ -1978,20 +1981,20 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
|
||||
struct cm_timewait_info *timewait_info;
|
||||
struct cm_id_private *cm_id_priv;
|
||||
unsigned long flags;
|
||||
u32 remote_id;
|
||||
__be32 remote_id;
|
||||
|
||||
remote_id = rej_msg->local_comm_id;
|
||||
|
||||
if (rej_msg->reason == IB_CM_REJ_TIMEOUT) {
|
||||
if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
|
||||
spin_lock_irqsave(&cm.lock, flags);
|
||||
timewait_info = cm_find_remote_id( *((u64 *) rej_msg->ari),
|
||||
timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
|
||||
remote_id);
|
||||
if (!timewait_info) {
|
||||
spin_unlock_irqrestore(&cm.lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
cm_id_priv = idr_find(&cm.local_id_table,
|
||||
(int) timewait_info->work.local_id);
|
||||
(__force int) timewait_info->work.local_id);
|
||||
if (cm_id_priv) {
|
||||
if (cm_id_priv->id.remote_id == remote_id)
|
||||
atomic_inc(&cm_id_priv->refcount);
|
||||
@ -2032,7 +2035,7 @@ static int cm_rej_handler(struct cm_work *work)
|
||||
/* fall through */
|
||||
case IB_CM_REQ_RCVD:
|
||||
case IB_CM_MRA_REQ_SENT:
|
||||
if (rej_msg->reason == IB_CM_REJ_STALE_CONN)
|
||||
if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)
|
||||
cm_enter_timewait(cm_id_priv);
|
||||
else
|
||||
cm_reset_to_idle(cm_id_priv);
|
||||
@ -2553,7 +2556,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
|
||||
cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
|
||||
cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
|
||||
sidr_req_msg->request_id = cm_id_priv->id.local_id;
|
||||
sidr_req_msg->pkey = param->pkey;
|
||||
sidr_req_msg->pkey = cpu_to_be16(param->pkey);
|
||||
sidr_req_msg->service_id = param->service_id;
|
||||
|
||||
if (param->private_data && param->private_data_len)
|
||||
@ -2580,7 +2583,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
|
||||
goto out;
|
||||
|
||||
cm_id->service_id = param->service_id;
|
||||
cm_id->service_mask = ~0ULL;
|
||||
cm_id->service_mask = __constant_cpu_to_be64(~0ULL);
|
||||
cm_id_priv->timeout_ms = param->timeout_ms;
|
||||
cm_id_priv->max_cm_retries = param->max_cm_retries;
|
||||
ret = cm_alloc_msg(cm_id_priv, &msg);
|
||||
@ -2621,7 +2624,7 @@ static void cm_format_sidr_req_event(struct cm_work *work,
|
||||
sidr_req_msg = (struct cm_sidr_req_msg *)
|
||||
work->mad_recv_wc->recv_buf.mad;
|
||||
param = &work->cm_event.param.sidr_req_rcvd;
|
||||
param->pkey = sidr_req_msg->pkey;
|
||||
param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
|
||||
param->listen_id = listen_id;
|
||||
param->device = work->port->mad_agent->device;
|
||||
param->port = work->port->port_num;
|
||||
@ -2645,7 +2648,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
|
||||
sidr_req_msg = (struct cm_sidr_req_msg *)
|
||||
work->mad_recv_wc->recv_buf.mad;
|
||||
wc = work->mad_recv_wc->wc;
|
||||
cm_id_priv->av.dgid.global.subnet_prefix = wc->slid;
|
||||
cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
|
||||
cm_id_priv->av.dgid.global.interface_id = 0;
|
||||
cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
|
||||
&cm_id_priv->av);
|
||||
@ -2673,7 +2676,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
|
||||
cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
|
||||
cm_id_priv->id.context = cur_cm_id_priv->id.context;
|
||||
cm_id_priv->id.service_id = sidr_req_msg->service_id;
|
||||
cm_id_priv->id.service_mask = ~0ULL;
|
||||
cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
|
||||
|
||||
cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
|
||||
cm_process_work(cm_id_priv, work);
|
||||
@ -3175,10 +3178,10 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
|
||||
}
|
||||
EXPORT_SYMBOL(ib_cm_init_qp_attr);
|
||||
|
||||
static u64 cm_get_ca_guid(struct ib_device *device)
|
||||
static __be64 cm_get_ca_guid(struct ib_device *device)
|
||||
{
|
||||
struct ib_device_attr *device_attr;
|
||||
u64 guid;
|
||||
__be64 guid;
|
||||
int ret;
|
||||
|
||||
device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
|
||||
|
@ -34,7 +34,7 @@
|
||||
#if !defined(CM_MSGS_H)
|
||||
#define CM_MSGS_H
|
||||
|
||||
#include <ib_mad.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
|
||||
/*
|
||||
* Parameters to routines below should be in network-byte order, and values
|
||||
@ -43,19 +43,17 @@
|
||||
|
||||
#define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */
|
||||
|
||||
enum cm_msg_attr_id {
|
||||
CM_REQ_ATTR_ID = __constant_htons(0x0010),
|
||||
CM_MRA_ATTR_ID = __constant_htons(0x0011),
|
||||
CM_REJ_ATTR_ID = __constant_htons(0x0012),
|
||||
CM_REP_ATTR_ID = __constant_htons(0x0013),
|
||||
CM_RTU_ATTR_ID = __constant_htons(0x0014),
|
||||
CM_DREQ_ATTR_ID = __constant_htons(0x0015),
|
||||
CM_DREP_ATTR_ID = __constant_htons(0x0016),
|
||||
CM_SIDR_REQ_ATTR_ID = __constant_htons(0x0017),
|
||||
CM_SIDR_REP_ATTR_ID = __constant_htons(0x0018),
|
||||
CM_LAP_ATTR_ID = __constant_htons(0x0019),
|
||||
CM_APR_ATTR_ID = __constant_htons(0x001A)
|
||||
};
|
||||
#define CM_REQ_ATTR_ID __constant_htons(0x0010)
|
||||
#define CM_MRA_ATTR_ID __constant_htons(0x0011)
|
||||
#define CM_REJ_ATTR_ID __constant_htons(0x0012)
|
||||
#define CM_REP_ATTR_ID __constant_htons(0x0013)
|
||||
#define CM_RTU_ATTR_ID __constant_htons(0x0014)
|
||||
#define CM_DREQ_ATTR_ID __constant_htons(0x0015)
|
||||
#define CM_DREP_ATTR_ID __constant_htons(0x0016)
|
||||
#define CM_SIDR_REQ_ATTR_ID __constant_htons(0x0017)
|
||||
#define CM_SIDR_REP_ATTR_ID __constant_htons(0x0018)
|
||||
#define CM_LAP_ATTR_ID __constant_htons(0x0019)
|
||||
#define CM_APR_ATTR_ID __constant_htons(0x001A)
|
||||
|
||||
enum cm_msg_sequence {
|
||||
CM_MSG_SEQUENCE_REQ,
|
||||
@ -67,35 +65,35 @@ enum cm_msg_sequence {
|
||||
struct cm_req_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 rsvd4;
|
||||
u64 service_id;
|
||||
u64 local_ca_guid;
|
||||
u32 rsvd24;
|
||||
u32 local_qkey;
|
||||
__be32 local_comm_id;
|
||||
__be32 rsvd4;
|
||||
__be64 service_id;
|
||||
__be64 local_ca_guid;
|
||||
__be32 rsvd24;
|
||||
__be32 local_qkey;
|
||||
/* local QPN:24, responder resources:8 */
|
||||
u32 offset32;
|
||||
__be32 offset32;
|
||||
/* local EECN:24, initiator depth:8 */
|
||||
u32 offset36;
|
||||
__be32 offset36;
|
||||
/*
|
||||
* remote EECN:24, remote CM response timeout:5,
|
||||
* transport service type:2, end-to-end flow control:1
|
||||
*/
|
||||
u32 offset40;
|
||||
__be32 offset40;
|
||||
/* starting PSN:24, local CM response timeout:5, retry count:3 */
|
||||
u32 offset44;
|
||||
u16 pkey;
|
||||
__be32 offset44;
|
||||
__be16 pkey;
|
||||
/* path MTU:4, RDC exists:1, RNR retry count:3. */
|
||||
u8 offset50;
|
||||
/* max CM Retries:4, SRQ:1, rsvd:3 */
|
||||
u8 offset51;
|
||||
|
||||
u16 primary_local_lid;
|
||||
u16 primary_remote_lid;
|
||||
__be16 primary_local_lid;
|
||||
__be16 primary_remote_lid;
|
||||
union ib_gid primary_local_gid;
|
||||
union ib_gid primary_remote_gid;
|
||||
/* flow label:20, rsvd:6, packet rate:6 */
|
||||
u32 primary_offset88;
|
||||
__be32 primary_offset88;
|
||||
u8 primary_traffic_class;
|
||||
u8 primary_hop_limit;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
@ -103,12 +101,12 @@ struct cm_req_msg {
|
||||
/* local ACK timeout:5, rsvd:3 */
|
||||
u8 primary_offset95;
|
||||
|
||||
u16 alt_local_lid;
|
||||
u16 alt_remote_lid;
|
||||
__be16 alt_local_lid;
|
||||
__be16 alt_remote_lid;
|
||||
union ib_gid alt_local_gid;
|
||||
union ib_gid alt_remote_gid;
|
||||
/* flow label:20, rsvd:6, packet rate:6 */
|
||||
u32 alt_offset132;
|
||||
__be32 alt_offset132;
|
||||
u8 alt_traffic_class;
|
||||
u8 alt_hop_limit;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
@ -120,12 +118,12 @@ struct cm_req_msg {
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
|
||||
static inline __be32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->offset32) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, u32 qpn)
|
||||
static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, __be32 qpn)
|
||||
{
|
||||
req_msg->offset32 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(req_msg->offset32) &
|
||||
@ -208,13 +206,13 @@ static inline void cm_req_set_flow_ctrl(struct cm_req_msg *req_msg,
|
||||
0xFFFFFFFE));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
|
||||
static inline __be32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->offset44) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_starting_psn(struct cm_req_msg *req_msg,
|
||||
u32 starting_psn)
|
||||
__be32 starting_psn)
|
||||
{
|
||||
req_msg->offset44 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
|
||||
(be32_to_cpu(req_msg->offset44) & 0x000000FF));
|
||||
@ -288,13 +286,13 @@ static inline void cm_req_set_srq(struct cm_req_msg *req_msg, u8 srq)
|
||||
((srq & 0x1) << 3));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
|
||||
static inline __be32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32((be32_to_cpu(req_msg->primary_offset88) >> 12));
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->primary_offset88) >> 12);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_flow_label(struct cm_req_msg *req_msg,
|
||||
u32 flow_label)
|
||||
__be32 flow_label)
|
||||
{
|
||||
req_msg->primary_offset88 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->primary_offset88) &
|
||||
@ -350,13 +348,13 @@ static inline void cm_req_set_primary_local_ack_timeout(struct cm_req_msg *req_m
|
||||
(local_ack_timeout << 3));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
|
||||
static inline __be32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32((be32_to_cpu(req_msg->alt_offset132) >> 12));
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->alt_offset132) >> 12);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_flow_label(struct cm_req_msg *req_msg,
|
||||
u32 flow_label)
|
||||
__be32 flow_label)
|
||||
{
|
||||
req_msg->alt_offset132 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->alt_offset132) &
|
||||
@ -422,8 +420,8 @@ enum cm_msg_response {
|
||||
struct cm_mra_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
/* message MRAed:2, rsvd:6 */
|
||||
u8 offset8;
|
||||
/* service timeout:5, rsvd:3 */
|
||||
@ -458,13 +456,13 @@ static inline void cm_mra_set_service_timeout(struct cm_mra_msg *mra_msg,
|
||||
struct cm_rej_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
/* message REJected:2, rsvd:6 */
|
||||
u8 offset8;
|
||||
/* reject info length:7, rsvd:1. */
|
||||
u8 offset9;
|
||||
u16 reason;
|
||||
__be16 reason;
|
||||
u8 ari[IB_CM_REJ_ARI_LENGTH];
|
||||
|
||||
u8 private_data[IB_CM_REJ_PRIVATE_DATA_SIZE];
|
||||
@ -495,45 +493,45 @@ static inline void cm_rej_set_reject_info_len(struct cm_rej_msg *rej_msg,
|
||||
struct cm_rep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
u32 local_qkey;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
__be32 local_qkey;
|
||||
/* local QPN:24, rsvd:8 */
|
||||
u32 offset12;
|
||||
__be32 offset12;
|
||||
/* local EECN:24, rsvd:8 */
|
||||
u32 offset16;
|
||||
__be32 offset16;
|
||||
/* starting PSN:24 rsvd:8 */
|
||||
u32 offset20;
|
||||
__be32 offset20;
|
||||
u8 resp_resources;
|
||||
u8 initiator_depth;
|
||||
/* target ACK delay:5, failover accepted:2, end-to-end flow control:1 */
|
||||
u8 offset26;
|
||||
/* RNR retry count:3, SRQ:1, rsvd:5 */
|
||||
u8 offset27;
|
||||
u64 local_ca_guid;
|
||||
__be64 local_ca_guid;
|
||||
|
||||
u8 private_data[IB_CM_REP_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
|
||||
static inline __be32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(rep_msg->offset12) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, u32 qpn)
|
||||
static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
|
||||
{
|
||||
rep_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
|
||||
}
|
||||
|
||||
static inline u32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
|
||||
static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_starting_psn(struct cm_rep_msg *rep_msg,
|
||||
u32 starting_psn)
|
||||
__be32 starting_psn)
|
||||
{
|
||||
rep_msg->offset20 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
|
||||
(be32_to_cpu(rep_msg->offset20) & 0x000000FF));
|
||||
@ -600,8 +598,8 @@ static inline void cm_rep_set_srq(struct cm_rep_msg *rep_msg, u8 srq)
|
||||
struct cm_rtu_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
|
||||
u8 private_data[IB_CM_RTU_PRIVATE_DATA_SIZE];
|
||||
|
||||
@ -610,21 +608,21 @@ struct cm_rtu_msg {
|
||||
struct cm_dreq_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
/* remote QPN/EECN:24, rsvd:8 */
|
||||
u32 offset8;
|
||||
__be32 offset8;
|
||||
|
||||
u8 private_data[IB_CM_DREQ_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
|
||||
static inline __be32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(dreq_msg->offset8) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
|
||||
static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, __be32 qpn)
|
||||
{
|
||||
dreq_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(dreq_msg->offset8) & 0x000000FF));
|
||||
@ -633,8 +631,8 @@ static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
|
||||
struct cm_drep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
|
||||
u8 private_data[IB_CM_DREP_PRIVATE_DATA_SIZE];
|
||||
|
||||
@ -643,37 +641,37 @@ struct cm_drep_msg {
|
||||
struct cm_lap_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
|
||||
u32 rsvd8;
|
||||
__be32 rsvd8;
|
||||
/* remote QPN/EECN:24, remote CM response timeout:5, rsvd:3 */
|
||||
u32 offset12;
|
||||
u32 rsvd16;
|
||||
__be32 offset12;
|
||||
__be32 rsvd16;
|
||||
|
||||
u16 alt_local_lid;
|
||||
u16 alt_remote_lid;
|
||||
__be16 alt_local_lid;
|
||||
__be16 alt_remote_lid;
|
||||
union ib_gid alt_local_gid;
|
||||
union ib_gid alt_remote_gid;
|
||||
/* flow label:20, rsvd:4, traffic class:8 */
|
||||
u32 offset56;
|
||||
__be32 offset56;
|
||||
u8 alt_hop_limit;
|
||||
/* rsvd:2, packet rate:6 */
|
||||
uint8_t offset61;
|
||||
u8 offset61;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
uint8_t offset62;
|
||||
u8 offset62;
|
||||
/* local ACK timeout:5, rsvd:3 */
|
||||
uint8_t offset63;
|
||||
u8 offset63;
|
||||
|
||||
u8 private_data[IB_CM_LAP_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
|
||||
static inline __be32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(lap_msg->offset12) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, u32 qpn)
|
||||
static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, __be32 qpn)
|
||||
{
|
||||
lap_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(lap_msg->offset12) &
|
||||
@ -693,17 +691,17 @@ static inline void cm_lap_set_remote_resp_timeout(struct cm_lap_msg *lap_msg,
|
||||
0xFFFFFF07));
|
||||
}
|
||||
|
||||
static inline u32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
|
||||
static inline __be32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return be32_to_cpu(lap_msg->offset56) >> 12;
|
||||
return cpu_to_be32(be32_to_cpu(lap_msg->offset56) >> 12);
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_flow_label(struct cm_lap_msg *lap_msg,
|
||||
u32 flow_label)
|
||||
__be32 flow_label)
|
||||
{
|
||||
lap_msg->offset56 = cpu_to_be32((flow_label << 12) |
|
||||
(be32_to_cpu(lap_msg->offset56) &
|
||||
0x00000FFF));
|
||||
lap_msg->offset56 = cpu_to_be32(
|
||||
(be32_to_cpu(lap_msg->offset56) & 0x00000FFF) |
|
||||
(be32_to_cpu(flow_label) << 12));
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_traffic_class(struct cm_lap_msg *lap_msg)
|
||||
@ -766,8 +764,8 @@ static inline void cm_lap_set_local_ack_timeout(struct cm_lap_msg *lap_msg,
|
||||
struct cm_apr_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
__be32 local_comm_id;
|
||||
__be32 remote_comm_id;
|
||||
|
||||
u8 info_length;
|
||||
u8 ap_status;
|
||||
@ -779,10 +777,10 @@ struct cm_apr_msg {
|
||||
struct cm_sidr_req_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 request_id;
|
||||
u16 pkey;
|
||||
u16 rsvd;
|
||||
u64 service_id;
|
||||
__be32 request_id;
|
||||
__be16 pkey;
|
||||
__be16 rsvd;
|
||||
__be64 service_id;
|
||||
|
||||
u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
@ -790,26 +788,26 @@ struct cm_sidr_req_msg {
|
||||
struct cm_sidr_rep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 request_id;
|
||||
__be32 request_id;
|
||||
u8 status;
|
||||
u8 info_length;
|
||||
u16 rsvd;
|
||||
__be16 rsvd;
|
||||
/* QPN:24, rsvd:8 */
|
||||
u32 offset8;
|
||||
u64 service_id;
|
||||
u32 qkey;
|
||||
__be32 offset8;
|
||||
__be64 service_id;
|
||||
__be32 qkey;
|
||||
u8 info[IB_CM_SIDR_REP_INFO_LENGTH];
|
||||
|
||||
u8 private_data[IB_CM_SIDR_REP_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
|
||||
static inline __be32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(sidr_rep_msg->offset8) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_sidr_rep_set_qpn(struct cm_sidr_rep_msg *sidr_rep_msg,
|
||||
u32 qpn)
|
||||
__be32 qpn)
|
||||
{
|
||||
sidr_rep_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(sidr_rep_msg->offset8) &
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
int ib_device_register_sysfs(struct ib_device *device);
|
||||
void ib_device_unregister_sysfs(struct ib_device *device);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <ib_fmr_pool.h>
|
||||
#include <rdma/ib_fmr_pool.h>
|
||||
|
||||
#include "core_priv.h"
|
||||
|
||||
@ -334,6 +334,7 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
|
||||
{
|
||||
struct ib_pool_fmr *fmr;
|
||||
struct ib_pool_fmr *tmp;
|
||||
LIST_HEAD(fmr_list);
|
||||
int i;
|
||||
|
||||
kthread_stop(pool->thread);
|
||||
@ -341,6 +342,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
|
||||
if (fmr->remap_count) {
|
||||
INIT_LIST_HEAD(&fmr_list);
|
||||
list_add_tail(&fmr->fmr->list, &fmr_list);
|
||||
ib_unmap_fmr(&fmr_list);
|
||||
}
|
||||
ib_dealloc_fmr(fmr->fmr);
|
||||
list_del(&fmr->list);
|
||||
kfree(fmr);
|
||||
|
@ -693,7 +693,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
build_smp_wc(send_wr->wr_id, smp->dr_slid, send_wr->wr.ud.pkey_index,
|
||||
build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
|
||||
send_wr->wr.ud.pkey_index,
|
||||
send_wr->wr.ud.port_num, &mad_wc);
|
||||
|
||||
/* No GRH for DR SMP */
|
||||
@ -1554,7 +1555,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
|
||||
}
|
||||
|
||||
struct ib_mad_send_wr_private*
|
||||
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid)
|
||||
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
|
||||
{
|
||||
struct ib_mad_send_wr_private *mad_send_wr;
|
||||
|
||||
@ -1597,7 +1598,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
|
||||
struct ib_mad_send_wr_private *mad_send_wr;
|
||||
struct ib_mad_send_wc mad_send_wc;
|
||||
unsigned long flags;
|
||||
u64 tid;
|
||||
__be64 tid;
|
||||
|
||||
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
|
||||
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
|
||||
@ -2165,7 +2166,8 @@ static void local_completions(void *data)
|
||||
* Defined behavior is to complete response
|
||||
* before request
|
||||
*/
|
||||
build_smp_wc(local->wr_id, IB_LID_PERMISSIVE,
|
||||
build_smp_wc(local->wr_id,
|
||||
be16_to_cpu(IB_LID_PERMISSIVE),
|
||||
0 /* pkey index */,
|
||||
recv_mad_agent->agent.port_num, &wc);
|
||||
|
||||
@ -2294,7 +2296,7 @@ static void timeout_sends(void *data)
|
||||
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
|
||||
}
|
||||
|
||||
static void ib_mad_thread_completion_handler(struct ib_cq *cq)
|
||||
static void ib_mad_thread_completion_handler(struct ib_cq *cq, void *arg)
|
||||
{
|
||||
struct ib_mad_port_private *port_priv = cq->cq_context;
|
||||
|
||||
@ -2574,8 +2576,7 @@ static int ib_mad_port_open(struct ib_device *device,
|
||||
|
||||
cq_size = (IB_MAD_QP_SEND_SIZE + IB_MAD_QP_RECV_SIZE) * 2;
|
||||
port_priv->cq = ib_create_cq(port_priv->device,
|
||||
(ib_comp_handler)
|
||||
ib_mad_thread_completion_handler,
|
||||
ib_mad_thread_completion_handler,
|
||||
NULL, port_priv, cq_size);
|
||||
if (IS_ERR(port_priv->cq)) {
|
||||
printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
|
||||
|
@ -40,8 +40,8 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <ib_mad.h>
|
||||
#include <ib_smi.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
#include <rdma/ib_smi.h>
|
||||
|
||||
|
||||
#define PFX "ib_mad: "
|
||||
@ -121,7 +121,7 @@ struct ib_mad_send_wr_private {
|
||||
struct ib_send_wr send_wr;
|
||||
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
|
||||
u64 wr_id; /* client WR ID */
|
||||
u64 tid;
|
||||
__be64 tid;
|
||||
unsigned long timeout;
|
||||
int retries;
|
||||
int retry;
|
||||
@ -144,7 +144,7 @@ struct ib_mad_local_private {
|
||||
struct ib_send_wr send_wr;
|
||||
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
|
||||
u64 wr_id; /* client WR ID */
|
||||
u64 tid;
|
||||
__be64 tid;
|
||||
};
|
||||
|
||||
struct ib_mad_mgmt_method_table {
|
||||
@ -210,7 +210,7 @@ extern kmem_cache_t *ib_mad_cache;
|
||||
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
|
||||
|
||||
struct ib_mad_send_wr_private *
|
||||
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid);
|
||||
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid);
|
||||
|
||||
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
struct ib_mad_send_wc *mad_send_wc);
|
||||
|
@ -61,7 +61,7 @@ struct mad_rmpp_recv {
|
||||
int seg_num;
|
||||
int newwin;
|
||||
|
||||
u64 tid;
|
||||
__be64 tid;
|
||||
u32 src_qp;
|
||||
u16 slid;
|
||||
u8 mgmt_class;
|
||||
@ -100,6 +100,121 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
|
||||
}
|
||||
}
|
||||
|
||||
static int data_offset(u8 mgmt_class)
|
||||
{
|
||||
if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
|
||||
return offsetof(struct ib_sa_mad, data);
|
||||
else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
|
||||
(mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
|
||||
return offsetof(struct ib_vendor_mad, data);
|
||||
else
|
||||
return offsetof(struct ib_rmpp_mad, data);
|
||||
}
|
||||
|
||||
static void format_ack(struct ib_rmpp_mad *ack,
|
||||
struct ib_rmpp_mad *data,
|
||||
struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
memcpy(&ack->mad_hdr, &data->mad_hdr,
|
||||
data_offset(data->mad_hdr.mgmt_class));
|
||||
|
||||
ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
|
||||
ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
|
||||
ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->lock, flags);
|
||||
rmpp_recv->last_ack = rmpp_recv->seg_num;
|
||||
ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
|
||||
ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
}
|
||||
|
||||
static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
|
||||
struct ib_mad_recv_wc *recv_wc)
|
||||
{
|
||||
struct ib_mad_send_buf *msg;
|
||||
struct ib_send_wr *bad_send_wr;
|
||||
int hdr_len, ret;
|
||||
|
||||
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
|
||||
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
|
||||
recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
|
||||
hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
|
||||
GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
format_ack((struct ib_rmpp_mad *) msg->mad,
|
||||
(struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
|
||||
ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
|
||||
&bad_send_wr);
|
||||
if (ret)
|
||||
ib_free_send_mad(msg);
|
||||
}
|
||||
|
||||
static int alloc_response_msg(struct ib_mad_agent *agent,
|
||||
struct ib_mad_recv_wc *recv_wc,
|
||||
struct ib_mad_send_buf **msg)
|
||||
{
|
||||
struct ib_mad_send_buf *m;
|
||||
struct ib_ah *ah;
|
||||
int hdr_len;
|
||||
|
||||
ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
|
||||
recv_wc->recv_buf.grh, agent->port_num);
|
||||
if (IS_ERR(ah))
|
||||
return PTR_ERR(ah);
|
||||
|
||||
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
|
||||
m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
|
||||
recv_wc->wc->pkey_index, ah, 1, hdr_len,
|
||||
sizeof(struct ib_rmpp_mad) - hdr_len,
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(m)) {
|
||||
ib_destroy_ah(ah);
|
||||
return PTR_ERR(m);
|
||||
}
|
||||
*msg = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_msg(struct ib_mad_send_buf *msg)
|
||||
{
|
||||
ib_destroy_ah(msg->send_wr.wr.ud.ah);
|
||||
ib_free_send_mad(msg);
|
||||
}
|
||||
|
||||
static void nack_recv(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *recv_wc, u8 rmpp_status)
|
||||
{
|
||||
struct ib_mad_send_buf *msg;
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
struct ib_send_wr *bad_send_wr;
|
||||
int ret;
|
||||
|
||||
ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *) msg->mad;
|
||||
memcpy(rmpp_mad, recv_wc->recv_buf.mad,
|
||||
data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
|
||||
|
||||
rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
|
||||
rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION;
|
||||
rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ABORT;
|
||||
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
|
||||
rmpp_mad->rmpp_hdr.rmpp_status = rmpp_status;
|
||||
rmpp_mad->rmpp_hdr.seg_num = 0;
|
||||
rmpp_mad->rmpp_hdr.paylen_newwin = 0;
|
||||
|
||||
ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr);
|
||||
if (ret)
|
||||
free_msg(msg);
|
||||
}
|
||||
|
||||
static void recv_timeout_handler(void *data)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv = data;
|
||||
@ -115,8 +230,8 @@ static void recv_timeout_handler(void *data)
|
||||
list_del(&rmpp_recv->list);
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
|
||||
/* TODO: send abort. */
|
||||
rmpp_wc = rmpp_recv->rmpp_wc;
|
||||
nack_recv(rmpp_recv->agent, rmpp_wc, IB_MGMT_RMPP_STATUS_T2L);
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
ib_free_recv_mad(rmpp_wc);
|
||||
}
|
||||
@ -230,60 +345,6 @@ insert_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
return cur_rmpp_recv;
|
||||
}
|
||||
|
||||
static int data_offset(u8 mgmt_class)
|
||||
{
|
||||
if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
|
||||
return offsetof(struct ib_sa_mad, data);
|
||||
else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
|
||||
(mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
|
||||
return offsetof(struct ib_vendor_mad, data);
|
||||
else
|
||||
return offsetof(struct ib_rmpp_mad, data);
|
||||
}
|
||||
|
||||
static void format_ack(struct ib_rmpp_mad *ack,
|
||||
struct ib_rmpp_mad *data,
|
||||
struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
memcpy(&ack->mad_hdr, &data->mad_hdr,
|
||||
data_offset(data->mad_hdr.mgmt_class));
|
||||
|
||||
ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
|
||||
ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
|
||||
ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->lock, flags);
|
||||
rmpp_recv->last_ack = rmpp_recv->seg_num;
|
||||
ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
|
||||
ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
}
|
||||
|
||||
static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
|
||||
struct ib_mad_recv_wc *recv_wc)
|
||||
{
|
||||
struct ib_mad_send_buf *msg;
|
||||
struct ib_send_wr *bad_send_wr;
|
||||
int hdr_len, ret;
|
||||
|
||||
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
|
||||
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
|
||||
recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
|
||||
hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
|
||||
GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
format_ack((struct ib_rmpp_mad *) msg->mad,
|
||||
(struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
|
||||
ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
|
||||
&bad_send_wr);
|
||||
if (ret)
|
||||
ib_free_send_mad(msg);
|
||||
}
|
||||
|
||||
static inline int get_last_flag(struct ib_mad_recv_buf *seg)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
@ -559,6 +620,34 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
return ib_send_mad(mad_send_wr);
|
||||
}
|
||||
|
||||
static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
|
||||
u8 rmpp_status)
|
||||
{
|
||||
struct ib_mad_send_wr_private *mad_send_wr;
|
||||
struct ib_mad_send_wc wc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
mad_send_wr = ib_find_send_mad(agent, tid);
|
||||
if (!mad_send_wr)
|
||||
goto out; /* Unmatched send */
|
||||
|
||||
if ((mad_send_wr->last_ack == mad_send_wr->total_seg) ||
|
||||
(!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
|
||||
goto out; /* Send is already done */
|
||||
|
||||
ib_mark_mad_done(mad_send_wr);
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
|
||||
wc.status = IB_WC_REM_ABORT_ERR;
|
||||
wc.vendor_err = rmpp_status;
|
||||
wc.wr_id = mad_send_wr->wr_id;
|
||||
ib_mad_complete_send_wr(mad_send_wr, &wc);
|
||||
return;
|
||||
out:
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
}
|
||||
|
||||
static void process_rmpp_ack(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
@ -568,11 +657,21 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
|
||||
int seg_num, newwin, ret;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_status)
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_status) {
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
|
||||
newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
|
||||
if (newwin < seg_num) {
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_W2S);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
|
||||
@ -583,8 +682,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
|
||||
(!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
|
||||
goto out; /* Send is already done */
|
||||
|
||||
if (seg_num > mad_send_wr->total_seg)
|
||||
goto out; /* Bad ACK */
|
||||
if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) {
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_S2B);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newwin < mad_send_wr->newwin || seg_num < mad_send_wr->last_ack)
|
||||
goto out; /* Old ACK */
|
||||
@ -628,6 +732,72 @@ out:
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
}
|
||||
|
||||
static struct ib_mad_recv_wc *
|
||||
process_rmpp_data(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct ib_rmpp_hdr *rmpp_hdr;
|
||||
u8 rmpp_status;
|
||||
|
||||
rmpp_hdr = &((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr;
|
||||
|
||||
if (rmpp_hdr->rmpp_status) {
|
||||
rmpp_status = IB_MGMT_RMPP_STATUS_BAD_STATUS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (rmpp_hdr->seg_num == __constant_htonl(1)) {
|
||||
if (!(ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST)) {
|
||||
rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
|
||||
goto bad;
|
||||
}
|
||||
return start_rmpp(agent, mad_recv_wc);
|
||||
} else {
|
||||
if (ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST) {
|
||||
rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG;
|
||||
goto bad;
|
||||
}
|
||||
return continue_rmpp(agent, mad_recv_wc);
|
||||
}
|
||||
bad:
|
||||
nack_recv(agent, mad_recv_wc, rmpp_status);
|
||||
ib_free_recv_mad(mad_recv_wc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void process_rmpp_stop(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) {
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
} else
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
rmpp_mad->rmpp_hdr.rmpp_status);
|
||||
}
|
||||
|
||||
static void process_rmpp_abort(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN ||
|
||||
rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) {
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
|
||||
} else
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
rmpp_mad->rmpp_hdr.rmpp_status);
|
||||
}
|
||||
|
||||
struct ib_mad_recv_wc *
|
||||
ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
@ -638,23 +808,29 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
|
||||
if (!(rmpp_mad->rmpp_hdr.rmpp_rtime_flags & IB_MGMT_RMPP_FLAG_ACTIVE))
|
||||
return mad_recv_wc;
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION)
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_UNV);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (rmpp_mad->rmpp_hdr.rmpp_type) {
|
||||
case IB_MGMT_RMPP_TYPE_DATA:
|
||||
if (rmpp_mad->rmpp_hdr.seg_num == __constant_htonl(1))
|
||||
return start_rmpp(agent, mad_recv_wc);
|
||||
else
|
||||
return continue_rmpp(agent, mad_recv_wc);
|
||||
return process_rmpp_data(agent, mad_recv_wc);
|
||||
case IB_MGMT_RMPP_TYPE_ACK:
|
||||
process_rmpp_ack(agent, mad_recv_wc);
|
||||
break;
|
||||
case IB_MGMT_RMPP_TYPE_STOP:
|
||||
process_rmpp_stop(agent, mad_recv_wc);
|
||||
break;
|
||||
case IB_MGMT_RMPP_TYPE_ABORT:
|
||||
/* TODO: process_rmpp_nack(agent, mad_recv_wc); */
|
||||
process_rmpp_abort(agent, mad_recv_wc);
|
||||
break;
|
||||
default:
|
||||
abort_send(agent, rmpp_mad->mad_hdr.tid,
|
||||
IB_MGMT_RMPP_STATUS_BADT);
|
||||
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
@ -714,7 +890,10 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
|
||||
msg = (struct ib_mad_send_buf *) (unsigned long)
|
||||
mad_send_wc->wr_id;
|
||||
ib_free_send_mad(msg);
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
|
||||
ib_free_send_mad(msg);
|
||||
else
|
||||
free_msg(msg);
|
||||
return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -32,7 +33,7 @@
|
||||
* $Id: packer.c 1349 2004-12-16 21:09:43Z roland $
|
||||
*/
|
||||
|
||||
#include <ib_pack.h>
|
||||
#include <rdma/ib_pack.h>
|
||||
|
||||
static u64 value_read(int offset, int size, void *structure)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -44,8 +44,8 @@
|
||||
#include <linux/kref.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <ib_pack.h>
|
||||
#include <ib_sa.h>
|
||||
#include <rdma/ib_pack.h>
|
||||
#include <rdma/ib_sa.h>
|
||||
|
||||
MODULE_AUTHOR("Roland Dreier");
|
||||
MODULE_DESCRIPTION("InfiniBand subnet administration query support");
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -36,7 +37,7 @@
|
||||
* $Id: smi.c 1389 2004-12-27 22:56:47Z roland $
|
||||
*/
|
||||
|
||||
#include <ib_smi.h>
|
||||
#include <rdma/ib_smi.h>
|
||||
#include "smi.h"
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -34,7 +36,7 @@
|
||||
|
||||
#include "core_priv.h"
|
||||
|
||||
#include <ib_mad.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
|
||||
struct ib_port {
|
||||
struct kobject kobj;
|
||||
@ -253,14 +255,14 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
be16_to_cpu(((u16 *) gid.raw)[0]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[1]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[2]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[3]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[4]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[5]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[6]),
|
||||
be16_to_cpu(((u16 *) gid.raw)[7]));
|
||||
be16_to_cpu(((__be16 *) gid.raw)[0]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[1]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[2]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[3]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[4]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[5]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[6]),
|
||||
be16_to_cpu(((__be16 *) gid.raw)[7]));
|
||||
}
|
||||
|
||||
static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
|
||||
@ -332,11 +334,11 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
|
||||
break;
|
||||
case 16:
|
||||
ret = sprintf(buf, "%u\n",
|
||||
be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8)));
|
||||
be16_to_cpup((__be16 *)(out_mad->data + 40 + offset / 8)));
|
||||
break;
|
||||
case 32:
|
||||
ret = sprintf(buf, "%u\n",
|
||||
be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8)));
|
||||
be32_to_cpup((__be32 *)(out_mad->data + 40 + offset / 8)));
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
@ -598,10 +600,10 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
|
||||
be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]),
|
||||
be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]),
|
||||
be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]),
|
||||
be16_to_cpu(((u16 *) &attr.sys_image_guid)[3]));
|
||||
be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),
|
||||
be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),
|
||||
be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),
|
||||
be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
|
||||
}
|
||||
|
||||
static ssize_t show_node_guid(struct class_device *cdev, char *buf)
|
||||
@ -615,10 +617,10 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
|
||||
be16_to_cpu(((u16 *) &attr.node_guid)[0]),
|
||||
be16_to_cpu(((u16 *) &attr.node_guid)[1]),
|
||||
be16_to_cpu(((u16 *) &attr.node_guid)[2]),
|
||||
be16_to_cpu(((u16 *) &attr.node_guid)[3]));
|
||||
be16_to_cpu(((__be16 *) &attr.node_guid)[0]),
|
||||
be16_to_cpu(((__be16 *) &attr.node_guid)[1]),
|
||||
be16_to_cpu(((__be16 *) &attr.node_guid)[2]),
|
||||
be16_to_cpu(((__be16 *) &attr.node_guid)[3]));
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -73,14 +74,18 @@ static struct semaphore ctx_id_mutex;
|
||||
static struct idr ctx_id_table;
|
||||
static int ctx_id_rover = 0;
|
||||
|
||||
static struct ib_ucm_context *ib_ucm_ctx_get(int id)
|
||||
static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
|
||||
{
|
||||
struct ib_ucm_context *ctx;
|
||||
|
||||
down(&ctx_id_mutex);
|
||||
ctx = idr_find(&ctx_id_table, id);
|
||||
if (ctx)
|
||||
ctx->ref++;
|
||||
if (!ctx)
|
||||
ctx = ERR_PTR(-ENOENT);
|
||||
else if (ctx->file != file)
|
||||
ctx = ERR_PTR(-EINVAL);
|
||||
else
|
||||
atomic_inc(&ctx->ref);
|
||||
up(&ctx_id_mutex);
|
||||
|
||||
return ctx;
|
||||
@ -88,21 +93,37 @@ static struct ib_ucm_context *ib_ucm_ctx_get(int id)
|
||||
|
||||
static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
|
||||
{
|
||||
if (atomic_dec_and_test(&ctx->ref))
|
||||
wake_up(&ctx->wait);
|
||||
}
|
||||
|
||||
static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
|
||||
{
|
||||
struct ib_ucm_context *ctx;
|
||||
struct ib_ucm_event *uevent;
|
||||
|
||||
down(&ctx_id_mutex);
|
||||
|
||||
ctx->ref--;
|
||||
if (!ctx->ref)
|
||||
ctx = idr_find(&ctx_id_table, id);
|
||||
if (!ctx)
|
||||
ctx = ERR_PTR(-ENOENT);
|
||||
else if (ctx->file != file)
|
||||
ctx = ERR_PTR(-EINVAL);
|
||||
else
|
||||
idr_remove(&ctx_id_table, ctx->id);
|
||||
|
||||
up(&ctx_id_mutex);
|
||||
|
||||
if (ctx->ref)
|
||||
return;
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
atomic_dec(&ctx->ref);
|
||||
wait_event(ctx->wait, !atomic_read(&ctx->ref));
|
||||
|
||||
/* No new events will be generated after destroying the cm_id. */
|
||||
if (!IS_ERR(ctx->cm_id))
|
||||
ib_destroy_cm_id(ctx->cm_id);
|
||||
|
||||
/* Cleanup events not yet reported to the user. */
|
||||
down(&file->mutex);
|
||||
list_del(&ctx->file_list);
|
||||
while (!list_empty(&ctx->events)) {
|
||||
|
||||
@ -117,13 +138,10 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
|
||||
|
||||
kfree(uevent);
|
||||
}
|
||||
up(&file->mutex);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
|
||||
ucm_dbg("Destroyed CM ID <%d>\n", ctx->id);
|
||||
|
||||
ib_destroy_cm_id(ctx->cm_id);
|
||||
kfree(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
|
||||
@ -135,11 +153,11 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->ref = 1; /* user reference */
|
||||
atomic_set(&ctx->ref, 1);
|
||||
init_waitqueue_head(&ctx->wait);
|
||||
ctx->file = file;
|
||||
|
||||
INIT_LIST_HEAD(&ctx->events);
|
||||
init_MUTEX(&ctx->mutex);
|
||||
|
||||
list_add_tail(&ctx->file_list, &file->ctxs);
|
||||
|
||||
@ -177,8 +195,8 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
|
||||
if (!kpath || !upath)
|
||||
return;
|
||||
|
||||
memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid));
|
||||
memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid));
|
||||
memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
|
||||
memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
|
||||
|
||||
upath->dlid = kpath->dlid;
|
||||
upath->slid = kpath->slid;
|
||||
@ -201,10 +219,11 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
|
||||
kpath->packet_life_time_selector;
|
||||
}
|
||||
|
||||
static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
|
||||
static void ib_ucm_event_req_get(struct ib_ucm_context *ctx,
|
||||
struct ib_ucm_req_event_resp *ureq,
|
||||
struct ib_cm_req_event_param *kreq)
|
||||
{
|
||||
ureq->listen_id = (long)kreq->listen_id->context;
|
||||
ureq->listen_id = ctx->id;
|
||||
|
||||
ureq->remote_ca_guid = kreq->remote_ca_guid;
|
||||
ureq->remote_qkey = kreq->remote_qkey;
|
||||
@ -240,34 +259,11 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
|
||||
urep->srq = krep->srq;
|
||||
}
|
||||
|
||||
static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej,
|
||||
struct ib_cm_rej_event_param *krej)
|
||||
{
|
||||
urej->reason = krej->reason;
|
||||
}
|
||||
|
||||
static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra,
|
||||
struct ib_cm_mra_event_param *kmra)
|
||||
{
|
||||
umra->timeout = kmra->service_timeout;
|
||||
}
|
||||
|
||||
static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap,
|
||||
struct ib_cm_lap_event_param *klap)
|
||||
{
|
||||
ib_ucm_event_path_get(&ulap->path, klap->alternate_path);
|
||||
}
|
||||
|
||||
static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr,
|
||||
struct ib_cm_apr_event_param *kapr)
|
||||
{
|
||||
uapr->status = kapr->ap_status;
|
||||
}
|
||||
|
||||
static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq,
|
||||
static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx,
|
||||
struct ib_ucm_sidr_req_event_resp *ureq,
|
||||
struct ib_cm_sidr_req_event_param *kreq)
|
||||
{
|
||||
ureq->listen_id = (long)kreq->listen_id->context;
|
||||
ureq->listen_id = ctx->id;
|
||||
ureq->pkey = kreq->pkey;
|
||||
}
|
||||
|
||||
@ -279,19 +275,18 @@ static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
|
||||
urep->qpn = krep->qpn;
|
||||
};
|
||||
|
||||
static int ib_ucm_event_process(struct ib_cm_event *evt,
|
||||
static int ib_ucm_event_process(struct ib_ucm_context *ctx,
|
||||
struct ib_cm_event *evt,
|
||||
struct ib_ucm_event *uvt)
|
||||
{
|
||||
void *info = NULL;
|
||||
int result;
|
||||
|
||||
switch (evt->event) {
|
||||
case IB_CM_REQ_RECEIVED:
|
||||
ib_ucm_event_req_get(&uvt->resp.u.req_resp,
|
||||
ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp,
|
||||
&evt->param.req_rcvd);
|
||||
uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE;
|
||||
uvt->resp.present |= (evt->param.req_rcvd.primary_path ?
|
||||
IB_UCM_PRES_PRIMARY : 0);
|
||||
uvt->resp.present = IB_UCM_PRES_PRIMARY;
|
||||
uvt->resp.present |= (evt->param.req_rcvd.alternate_path ?
|
||||
IB_UCM_PRES_ALTERNATE : 0);
|
||||
break;
|
||||
@ -299,57 +294,46 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
|
||||
ib_ucm_event_rep_get(&uvt->resp.u.rep_resp,
|
||||
&evt->param.rep_rcvd);
|
||||
uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
|
||||
|
||||
break;
|
||||
case IB_CM_RTU_RECEIVED:
|
||||
uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE;
|
||||
uvt->resp.u.send_status = evt->param.send_status;
|
||||
|
||||
break;
|
||||
case IB_CM_DREQ_RECEIVED:
|
||||
uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE;
|
||||
uvt->resp.u.send_status = evt->param.send_status;
|
||||
|
||||
break;
|
||||
case IB_CM_DREP_RECEIVED:
|
||||
uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE;
|
||||
uvt->resp.u.send_status = evt->param.send_status;
|
||||
|
||||
break;
|
||||
case IB_CM_MRA_RECEIVED:
|
||||
ib_ucm_event_mra_get(&uvt->resp.u.mra_resp,
|
||||
&evt->param.mra_rcvd);
|
||||
uvt->resp.u.mra_resp.timeout =
|
||||
evt->param.mra_rcvd.service_timeout;
|
||||
uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE;
|
||||
|
||||
break;
|
||||
case IB_CM_REJ_RECEIVED:
|
||||
ib_ucm_event_rej_get(&uvt->resp.u.rej_resp,
|
||||
&evt->param.rej_rcvd);
|
||||
uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason;
|
||||
uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
|
||||
uvt->info_len = evt->param.rej_rcvd.ari_length;
|
||||
info = evt->param.rej_rcvd.ari;
|
||||
|
||||
break;
|
||||
case IB_CM_LAP_RECEIVED:
|
||||
ib_ucm_event_lap_get(&uvt->resp.u.lap_resp,
|
||||
&evt->param.lap_rcvd);
|
||||
ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
|
||||
evt->param.lap_rcvd.alternate_path);
|
||||
uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
|
||||
uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ?
|
||||
IB_UCM_PRES_ALTERNATE : 0);
|
||||
uvt->resp.present = IB_UCM_PRES_ALTERNATE;
|
||||
break;
|
||||
case IB_CM_APR_RECEIVED:
|
||||
ib_ucm_event_apr_get(&uvt->resp.u.apr_resp,
|
||||
&evt->param.apr_rcvd);
|
||||
uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status;
|
||||
uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE;
|
||||
uvt->info_len = evt->param.apr_rcvd.info_len;
|
||||
info = evt->param.apr_rcvd.apr_info;
|
||||
|
||||
break;
|
||||
case IB_CM_SIDR_REQ_RECEIVED:
|
||||
ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp,
|
||||
ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp,
|
||||
&evt->param.sidr_req_rcvd);
|
||||
uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
|
||||
|
||||
break;
|
||||
case IB_CM_SIDR_REP_RECEIVED:
|
||||
ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp,
|
||||
@ -357,43 +341,35 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
|
||||
uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
|
||||
uvt->info_len = evt->param.sidr_rep_rcvd.info_len;
|
||||
info = evt->param.sidr_rep_rcvd.info;
|
||||
|
||||
break;
|
||||
default:
|
||||
uvt->resp.u.send_status = evt->param.send_status;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (uvt->data_len && evt->private_data) {
|
||||
|
||||
if (uvt->data_len) {
|
||||
uvt->data = kmalloc(uvt->data_len, GFP_KERNEL);
|
||||
if (!uvt->data) {
|
||||
result = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (!uvt->data)
|
||||
goto err1;
|
||||
|
||||
memcpy(uvt->data, evt->private_data, uvt->data_len);
|
||||
uvt->resp.present |= IB_UCM_PRES_DATA;
|
||||
}
|
||||
|
||||
if (uvt->info_len && info) {
|
||||
|
||||
if (uvt->info_len) {
|
||||
uvt->info = kmalloc(uvt->info_len, GFP_KERNEL);
|
||||
if (!uvt->info) {
|
||||
result = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (!uvt->info)
|
||||
goto err2;
|
||||
|
||||
memcpy(uvt->info, info, uvt->info_len);
|
||||
uvt->resp.present |= IB_UCM_PRES_INFO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(uvt->info);
|
||||
|
||||
err2:
|
||||
kfree(uvt->data);
|
||||
return result;
|
||||
err1:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
|
||||
@ -403,63 +379,42 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
|
||||
struct ib_ucm_context *ctx;
|
||||
int result = 0;
|
||||
int id;
|
||||
/*
|
||||
* lookup correct context based on event type.
|
||||
*/
|
||||
switch (event->event) {
|
||||
case IB_CM_REQ_RECEIVED:
|
||||
id = (long)event->param.req_rcvd.listen_id->context;
|
||||
break;
|
||||
case IB_CM_SIDR_REQ_RECEIVED:
|
||||
id = (long)event->param.sidr_req_rcvd.listen_id->context;
|
||||
break;
|
||||
default:
|
||||
id = (long)cm_id->context;
|
||||
break;
|
||||
}
|
||||
|
||||
ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event);
|
||||
|
||||
ctx = ib_ucm_ctx_get(id);
|
||||
if (!ctx)
|
||||
return -ENOENT;
|
||||
ctx = cm_id->context;
|
||||
|
||||
if (event->event == IB_CM_REQ_RECEIVED ||
|
||||
event->event == IB_CM_SIDR_REQ_RECEIVED)
|
||||
id = IB_UCM_CM_ID_INVALID;
|
||||
else
|
||||
id = ctx->id;
|
||||
|
||||
uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
|
||||
if (!uevent) {
|
||||
result = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
if (!uevent)
|
||||
goto err1;
|
||||
|
||||
memset(uevent, 0, sizeof(*uevent));
|
||||
|
||||
uevent->resp.id = id;
|
||||
uevent->resp.event = event->event;
|
||||
|
||||
result = ib_ucm_event_process(event, uevent);
|
||||
result = ib_ucm_event_process(ctx, event, uevent);
|
||||
if (result)
|
||||
goto done;
|
||||
goto err2;
|
||||
|
||||
uevent->ctx = ctx;
|
||||
uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED ||
|
||||
event->event == IB_CM_SIDR_REQ_RECEIVED ) ?
|
||||
cm_id : NULL);
|
||||
uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL;
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
|
||||
list_add_tail(&uevent->file_list, &ctx->file->events);
|
||||
list_add_tail(&uevent->ctx_list, &ctx->events);
|
||||
|
||||
wake_up_interruptible(&ctx->file->poll_wait);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
done:
|
||||
ctx->error = result;
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
return result;
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
kfree(uevent);
|
||||
err1:
|
||||
/* Destroy new cm_id's */
|
||||
return (id == IB_UCM_CM_ID_INVALID);
|
||||
}
|
||||
|
||||
static ssize_t ib_ucm_event(struct ib_ucm_file *file,
|
||||
@ -517,9 +472,8 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
|
||||
goto done;
|
||||
}
|
||||
|
||||
ctx->cm_id = uevent->cm_id;
|
||||
ctx->cm_id->cm_handler = ib_ucm_event_handler;
|
||||
ctx->cm_id->context = (void *)(unsigned long)ctx->id;
|
||||
ctx->cm_id = uevent->cm_id;
|
||||
ctx->cm_id->context = ctx;
|
||||
|
||||
uevent->resp.id = ctx->id;
|
||||
|
||||
@ -585,30 +539,29 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
down(&file->mutex);
|
||||
ctx = ib_ucm_ctx_alloc(file);
|
||||
up(&file->mutex);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler,
|
||||
(void *)(unsigned long)ctx->id);
|
||||
if (!ctx->cm_id) {
|
||||
result = -ENOMEM;
|
||||
goto err_cm;
|
||||
ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
|
||||
if (IS_ERR(ctx->cm_id)) {
|
||||
result = PTR_ERR(ctx->cm_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
resp.id = ctx->id;
|
||||
if (copy_to_user((void __user *)(unsigned long)cmd.response,
|
||||
&resp, sizeof(resp))) {
|
||||
result = -EFAULT;
|
||||
goto err_ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_ret:
|
||||
ib_destroy_cm_id(ctx->cm_id);
|
||||
err_cm:
|
||||
ib_ucm_ctx_put(ctx); /* user reference */
|
||||
|
||||
err:
|
||||
ib_ucm_destroy_ctx(file, ctx->id);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -617,19 +570,11 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
|
||||
int in_len, int out_len)
|
||||
{
|
||||
struct ib_ucm_destroy_id cmd;
|
||||
struct ib_ucm_context *ctx;
|
||||
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx)
|
||||
return -ENOENT;
|
||||
|
||||
ib_ucm_ctx_put(ctx); /* user reference */
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
|
||||
return 0;
|
||||
return ib_ucm_destroy_ctx(file, cmd.id);
|
||||
}
|
||||
|
||||
static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
|
||||
@ -647,15 +592,9 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx)
|
||||
return -ENOENT;
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file) {
|
||||
result = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
resp.service_id = ctx->cm_id->service_id;
|
||||
resp.service_mask = ctx->cm_id->service_mask;
|
||||
@ -666,9 +605,7 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
|
||||
&resp, sizeof(resp)))
|
||||
result = -EFAULT;
|
||||
|
||||
done:
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
ib_ucm_ctx_put(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -683,19 +620,12 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx)
|
||||
return -ENOENT;
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
result = ib_cm_listen(ctx->cm_id, cmd.service_id,
|
||||
cmd.service_mask);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -710,18 +640,12 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file,
|
||||
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx)
|
||||
return -ENOENT;
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
result = ib_cm_establish(ctx->cm_id);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
result = ib_cm_establish(ctx->cm_id);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -768,8 +692,8 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid));
|
||||
memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid));
|
||||
memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
|
||||
memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
|
||||
|
||||
sa_path->dlid = ucm_path.dlid;
|
||||
sa_path->slid = ucm_path.slid;
|
||||
@ -839,25 +763,17 @@ static ssize_t ib_ucm_send_req(struct ib_ucm_file *file,
|
||||
param.max_cm_retries = cmd.max_cm_retries;
|
||||
param.srq = cmd.srq;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_req(ctx->cm_id, ¶m);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(param.private_data);
|
||||
kfree(param.primary_path);
|
||||
kfree(param.alternate_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -890,23 +806,14 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
|
||||
param.rnr_retry_count = cmd.rnr_retry_count;
|
||||
param.srq = cmd.srq;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_rep(ctx->cm_id, ¶m);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(param.private_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -928,23 +835,14 @@ static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file,
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = func(ctx->cm_id, private_data, cmd.len);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(private_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -995,26 +893,17 @@ static ssize_t ib_ucm_send_info(struct ib_ucm_file *file,
|
||||
if (result)
|
||||
goto done;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
result = func(ctx->cm_id, cmd.status,
|
||||
info, cmd.info_len,
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = func(ctx->cm_id, cmd.status, info, cmd.info_len,
|
||||
data, cmd.data_len);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(data);
|
||||
kfree(info);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1048,24 +937,14 @@ static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file,
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
result = ib_send_cm_mra(ctx->cm_id, cmd.timeout,
|
||||
data, cmd.len);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1090,24 +969,16 @@ static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file,
|
||||
if (result)
|
||||
goto done;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(data);
|
||||
kfree(path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1140,24 +1011,16 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
|
||||
param.max_cm_retries = cmd.max_cm_retries;
|
||||
param.pkey = cmd.pkey;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_sidr_req(ctx->cm_id, ¶m);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(param.private_data);
|
||||
kfree(param.path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1184,30 +1047,22 @@ static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file,
|
||||
if (result)
|
||||
goto done;
|
||||
|
||||
param.qp_num = cmd.qpn;
|
||||
param.qkey = cmd.qkey;
|
||||
param.status = cmd.status;
|
||||
param.info_length = cmd.info_len;
|
||||
param.private_data_len = cmd.data_len;
|
||||
param.qp_num = cmd.qpn;
|
||||
param.qkey = cmd.qkey;
|
||||
param.status = cmd.status;
|
||||
param.info_length = cmd.info_len;
|
||||
param.private_data_len = cmd.data_len;
|
||||
|
||||
ctx = ib_ucm_ctx_get(cmd.id);
|
||||
if (!ctx) {
|
||||
result = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
down(&ctx->file->mutex);
|
||||
if (ctx->file != file)
|
||||
result = -EINVAL;
|
||||
else
|
||||
ctx = ib_ucm_ctx_get(file, cmd.id);
|
||||
if (!IS_ERR(ctx)) {
|
||||
result = ib_send_cm_sidr_rep(ctx->cm_id, ¶m);
|
||||
ib_ucm_ctx_put(ctx);
|
||||
} else
|
||||
result = PTR_ERR(ctx);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* func reference */
|
||||
done:
|
||||
kfree(param.private_data);
|
||||
kfree(param.info);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1305,22 +1160,17 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
|
||||
struct ib_ucm_context *ctx;
|
||||
|
||||
down(&file->mutex);
|
||||
|
||||
while (!list_empty(&file->ctxs)) {
|
||||
|
||||
ctx = list_entry(file->ctxs.next,
|
||||
struct ib_ucm_context, file_list);
|
||||
|
||||
up(&ctx->file->mutex);
|
||||
ib_ucm_ctx_put(ctx); /* user reference */
|
||||
up(&file->mutex);
|
||||
ib_ucm_destroy_ctx(file, ctx->id);
|
||||
down(&file->mutex);
|
||||
}
|
||||
|
||||
up(&file->mutex);
|
||||
|
||||
kfree(file);
|
||||
|
||||
ucm_dbg("Deleted struct\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -40,17 +40,15 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <ib_cm.h>
|
||||
#include <ib_user_cm.h>
|
||||
#include <rdma/ib_cm.h>
|
||||
#include <rdma/ib_user_cm.h>
|
||||
|
||||
#define IB_UCM_CM_ID_INVALID 0xffffffff
|
||||
|
||||
struct ib_ucm_file {
|
||||
struct semaphore mutex;
|
||||
struct file *filp;
|
||||
/*
|
||||
* list of pending events
|
||||
*/
|
||||
|
||||
struct list_head ctxs; /* list of active connections */
|
||||
struct list_head events; /* list of pending events */
|
||||
wait_queue_head_t poll_wait;
|
||||
@ -58,12 +56,11 @@ struct ib_ucm_file {
|
||||
|
||||
struct ib_ucm_context {
|
||||
int id;
|
||||
int ref;
|
||||
int error;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t ref;
|
||||
|
||||
struct ib_ucm_file *file;
|
||||
struct ib_cm_id *cm_id;
|
||||
struct semaphore mutex;
|
||||
|
||||
struct list_head events; /* list of pending events. */
|
||||
struct list_head file_list; /* member in file ctx list */
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -34,7 +35,7 @@
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <ib_pack.h>
|
||||
#include <rdma/ib_pack.h>
|
||||
|
||||
#define STRUCT_FIELD(header, field) \
|
||||
.struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \
|
||||
@ -194,6 +195,7 @@ void ib_ud_header_init(int payload_bytes,
|
||||
struct ib_ud_header *header)
|
||||
{
|
||||
int header_len;
|
||||
u16 packet_length;
|
||||
|
||||
memset(header, 0, sizeof *header);
|
||||
|
||||
@ -208,7 +210,7 @@ void ib_ud_header_init(int payload_bytes,
|
||||
header->lrh.link_version = 0;
|
||||
header->lrh.link_next_header =
|
||||
grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
|
||||
header->lrh.packet_length = (IB_LRH_BYTES +
|
||||
packet_length = (IB_LRH_BYTES +
|
||||
IB_BTH_BYTES +
|
||||
IB_DETH_BYTES +
|
||||
payload_bytes +
|
||||
@ -217,8 +219,7 @@ void ib_ud_header_init(int payload_bytes,
|
||||
|
||||
header->grh_present = grh_present;
|
||||
if (grh_present) {
|
||||
header->lrh.packet_length += IB_GRH_BYTES / 4;
|
||||
|
||||
packet_length += IB_GRH_BYTES / 4;
|
||||
header->grh.ip_version = 6;
|
||||
header->grh.payload_length =
|
||||
cpu_to_be16((IB_BTH_BYTES +
|
||||
@ -229,7 +230,7 @@ void ib_ud_header_init(int payload_bytes,
|
||||
header->grh.next_header = 0x1b;
|
||||
}
|
||||
|
||||
cpu_to_be16s(&header->lrh.packet_length);
|
||||
header->lrh.packet_length = cpu_to_be16(packet_length);
|
||||
|
||||
if (header->immediate_present)
|
||||
header->bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
@ -49,8 +49,8 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
#include <ib_mad.h>
|
||||
#include <ib_user_mad.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
#include <rdma/ib_user_mad.h>
|
||||
|
||||
MODULE_AUTHOR("Roland Dreier");
|
||||
MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
|
||||
@ -271,7 +271,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
|
||||
struct ib_send_wr *bad_wr;
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
u8 method;
|
||||
u64 *tid;
|
||||
__be64 *tid;
|
||||
int ret, length, hdr_len, data_len, rmpp_hdr_size;
|
||||
int rmpp_active = 0;
|
||||
|
||||
@ -316,7 +316,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
|
||||
if (packet->mad.hdr.grh_present) {
|
||||
ah_attr.ah_flags = IB_AH_GRH;
|
||||
memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
|
||||
ah_attr.grh.flow_label = packet->mad.hdr.flow_label;
|
||||
ah_attr.grh.flow_label = be32_to_cpu(packet->mad.hdr.flow_label);
|
||||
ah_attr.grh.hop_limit = packet->mad.hdr.hop_limit;
|
||||
ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -43,8 +45,8 @@
|
||||
#include <linux/kref.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <ib_user_verbs.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/ib_user_verbs.h>
|
||||
|
||||
struct ib_uverbs_device {
|
||||
int devnum;
|
||||
@ -97,10 +99,12 @@ extern struct idr ib_uverbs_mw_idr;
|
||||
extern struct idr ib_uverbs_ah_idr;
|
||||
extern struct idr ib_uverbs_cq_idr;
|
||||
extern struct idr ib_uverbs_qp_idr;
|
||||
extern struct idr ib_uverbs_srq_idr;
|
||||
|
||||
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
|
||||
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
|
||||
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
|
||||
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
|
||||
|
||||
int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
|
||||
void *addr, size_t size, int write);
|
||||
@ -129,5 +133,8 @@ IB_UVERBS_DECLARE_CMD(modify_qp);
|
||||
IB_UVERBS_DECLARE_CMD(destroy_qp);
|
||||
IB_UVERBS_DECLARE_CMD(attach_mcast);
|
||||
IB_UVERBS_DECLARE_CMD(detach_mcast);
|
||||
IB_UVERBS_DECLARE_CMD(create_srq);
|
||||
IB_UVERBS_DECLARE_CMD(modify_srq);
|
||||
IB_UVERBS_DECLARE_CMD(destroy_srq);
|
||||
|
||||
#endif /* UVERBS_H */
|
||||
|
@ -724,6 +724,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
||||
struct ib_uobject *uobj;
|
||||
struct ib_pd *pd;
|
||||
struct ib_cq *scq, *rcq;
|
||||
struct ib_srq *srq;
|
||||
struct ib_qp *qp;
|
||||
struct ib_qp_init_attr attr;
|
||||
int ret;
|
||||
@ -747,10 +748,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
||||
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
|
||||
scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
|
||||
rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
|
||||
srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
|
||||
|
||||
if (!pd || pd->uobject->context != file->ucontext ||
|
||||
!scq || scq->uobject->context != file->ucontext ||
|
||||
!rcq || rcq->uobject->context != file->ucontext) {
|
||||
!rcq || rcq->uobject->context != file->ucontext ||
|
||||
(cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
|
||||
ret = -EINVAL;
|
||||
goto err_up;
|
||||
}
|
||||
@ -759,7 +762,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
||||
attr.qp_context = file;
|
||||
attr.send_cq = scq;
|
||||
attr.recv_cq = rcq;
|
||||
attr.srq = NULL;
|
||||
attr.srq = srq;
|
||||
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
|
||||
attr.qp_type = cmd.qp_type;
|
||||
|
||||
@ -1004,3 +1007,178 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
|
||||
|
||||
return ret ? ret : in_len;
|
||||
}
|
||||
|
||||
ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
|
||||
const char __user *buf, int in_len,
|
||||
int out_len)
|
||||
{
|
||||
struct ib_uverbs_create_srq cmd;
|
||||
struct ib_uverbs_create_srq_resp resp;
|
||||
struct ib_udata udata;
|
||||
struct ib_uobject *uobj;
|
||||
struct ib_pd *pd;
|
||||
struct ib_srq *srq;
|
||||
struct ib_srq_init_attr attr;
|
||||
int ret;
|
||||
|
||||
if (out_len < sizeof resp)
|
||||
return -ENOSPC;
|
||||
|
||||
if (copy_from_user(&cmd, buf, sizeof cmd))
|
||||
return -EFAULT;
|
||||
|
||||
INIT_UDATA(&udata, buf + sizeof cmd,
|
||||
(unsigned long) cmd.response + sizeof resp,
|
||||
in_len - sizeof cmd, out_len - sizeof resp);
|
||||
|
||||
uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
|
||||
if (!uobj)
|
||||
return -ENOMEM;
|
||||
|
||||
down(&ib_uverbs_idr_mutex);
|
||||
|
||||
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
|
||||
|
||||
if (!pd || pd->uobject->context != file->ucontext) {
|
||||
ret = -EINVAL;
|
||||
goto err_up;
|
||||
}
|
||||
|
||||
attr.event_handler = ib_uverbs_srq_event_handler;
|
||||
attr.srq_context = file;
|
||||
attr.attr.max_wr = cmd.max_wr;
|
||||
attr.attr.max_sge = cmd.max_sge;
|
||||
attr.attr.srq_limit = cmd.srq_limit;
|
||||
|
||||
uobj->user_handle = cmd.user_handle;
|
||||
uobj->context = file->ucontext;
|
||||
|
||||
srq = pd->device->create_srq(pd, &attr, &udata);
|
||||
if (IS_ERR(srq)) {
|
||||
ret = PTR_ERR(srq);
|
||||
goto err_up;
|
||||
}
|
||||
|
||||
srq->device = pd->device;
|
||||
srq->pd = pd;
|
||||
srq->uobject = uobj;
|
||||
srq->event_handler = attr.event_handler;
|
||||
srq->srq_context = attr.srq_context;
|
||||
atomic_inc(&pd->usecnt);
|
||||
atomic_set(&srq->usecnt, 0);
|
||||
|
||||
memset(&resp, 0, sizeof resp);
|
||||
|
||||
retry:
|
||||
if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_destroy;
|
||||
}
|
||||
|
||||
ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id);
|
||||
|
||||
if (ret == -EAGAIN)
|
||||
goto retry;
|
||||
if (ret)
|
||||
goto err_destroy;
|
||||
|
||||
resp.srq_handle = uobj->id;
|
||||
|
||||
spin_lock_irq(&file->ucontext->lock);
|
||||
list_add_tail(&uobj->list, &file->ucontext->srq_list);
|
||||
spin_unlock_irq(&file->ucontext->lock);
|
||||
|
||||
if (copy_to_user((void __user *) (unsigned long) cmd.response,
|
||||
&resp, sizeof resp)) {
|
||||
ret = -EFAULT;
|
||||
goto err_list;
|
||||
}
|
||||
|
||||
up(&ib_uverbs_idr_mutex);
|
||||
|
||||
return in_len;
|
||||
|
||||
err_list:
|
||||
spin_lock_irq(&file->ucontext->lock);
|
||||
list_del(&uobj->list);
|
||||
spin_unlock_irq(&file->ucontext->lock);
|
||||
|
||||
err_destroy:
|
||||
ib_destroy_srq(srq);
|
||||
|
||||
err_up:
|
||||
up(&ib_uverbs_idr_mutex);
|
||||
|
||||
kfree(uobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
|
||||
const char __user *buf, int in_len,
|
||||
int out_len)
|
||||
{
|
||||
struct ib_uverbs_modify_srq cmd;
|
||||
struct ib_srq *srq;
|
||||
struct ib_srq_attr attr;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&cmd, buf, sizeof cmd))
|
||||
return -EFAULT;
|
||||
|
||||
down(&ib_uverbs_idr_mutex);
|
||||
|
||||
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
|
||||
if (!srq || srq->uobject->context != file->ucontext) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
attr.max_wr = cmd.max_wr;
|
||||
attr.max_sge = cmd.max_sge;
|
||||
attr.srq_limit = cmd.srq_limit;
|
||||
|
||||
ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
|
||||
|
||||
out:
|
||||
up(&ib_uverbs_idr_mutex);
|
||||
|
||||
return ret ? ret : in_len;
|
||||
}
|
||||
|
||||
ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
|
||||
const char __user *buf, int in_len,
|
||||
int out_len)
|
||||
{
|
||||
struct ib_uverbs_destroy_srq cmd;
|
||||
struct ib_srq *srq;
|
||||
struct ib_uobject *uobj;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (copy_from_user(&cmd, buf, sizeof cmd))
|
||||
return -EFAULT;
|
||||
|
||||
down(&ib_uverbs_idr_mutex);
|
||||
|
||||
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
|
||||
if (!srq || srq->uobject->context != file->ucontext)
|
||||
goto out;
|
||||
|
||||
uobj = srq->uobject;
|
||||
|
||||
ret = ib_destroy_srq(srq);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
|
||||
|
||||
spin_lock_irq(&file->ucontext->lock);
|
||||
list_del(&uobj->list);
|
||||
spin_unlock_irq(&file->ucontext->lock);
|
||||
|
||||
kfree(uobj);
|
||||
|
||||
out:
|
||||
up(&ib_uverbs_idr_mutex);
|
||||
|
||||
return ret ? ret : in_len;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -67,6 +69,7 @@ DEFINE_IDR(ib_uverbs_mw_idr);
|
||||
DEFINE_IDR(ib_uverbs_ah_idr);
|
||||
DEFINE_IDR(ib_uverbs_cq_idr);
|
||||
DEFINE_IDR(ib_uverbs_qp_idr);
|
||||
DEFINE_IDR(ib_uverbs_srq_idr);
|
||||
|
||||
static spinlock_t map_lock;
|
||||
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
|
||||
@ -91,6 +94,9 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
|
||||
[IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
|
||||
[IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
|
||||
[IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
|
||||
[IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
|
||||
[IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
|
||||
[IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
|
||||
};
|
||||
|
||||
static struct vfsmount *uverbs_event_mnt;
|
||||
@ -125,7 +131,14 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
|
||||
kfree(uobj);
|
||||
}
|
||||
|
||||
/* XXX Free SRQs */
|
||||
list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
|
||||
struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
|
||||
idr_remove(&ib_uverbs_srq_idr, uobj->id);
|
||||
ib_destroy_srq(srq);
|
||||
list_del(&uobj->list);
|
||||
kfree(uobj);
|
||||
}
|
||||
|
||||
/* XXX Free MWs */
|
||||
|
||||
list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
|
||||
@ -344,6 +357,13 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
|
||||
event->event);
|
||||
}
|
||||
|
||||
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
|
||||
{
|
||||
ib_uverbs_async_handler(context_ptr,
|
||||
event->element.srq->uobject->user_handle,
|
||||
event->event);
|
||||
}
|
||||
|
||||
static void ib_uverbs_event_handler(struct ib_event_handler *handler,
|
||||
struct ib_event *event)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
@ -40,8 +41,8 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <ib_cache.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
/* Protection domains */
|
||||
|
||||
@ -153,6 +154,66 @@ int ib_destroy_ah(struct ib_ah *ah)
|
||||
}
|
||||
EXPORT_SYMBOL(ib_destroy_ah);
|
||||
|
||||
/* Shared receive queues */
|
||||
|
||||
struct ib_srq *ib_create_srq(struct ib_pd *pd,
|
||||
struct ib_srq_init_attr *srq_init_attr)
|
||||
{
|
||||
struct ib_srq *srq;
|
||||
|
||||
if (!pd->device->create_srq)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
||||
srq = pd->device->create_srq(pd, srq_init_attr, NULL);
|
||||
|
||||
if (!IS_ERR(srq)) {
|
||||
srq->device = pd->device;
|
||||
srq->pd = pd;
|
||||
srq->uobject = NULL;
|
||||
srq->event_handler = srq_init_attr->event_handler;
|
||||
srq->srq_context = srq_init_attr->srq_context;
|
||||
atomic_inc(&pd->usecnt);
|
||||
atomic_set(&srq->usecnt, 0);
|
||||
}
|
||||
|
||||
return srq;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_srq);
|
||||
|
||||
int ib_modify_srq(struct ib_srq *srq,
|
||||
struct ib_srq_attr *srq_attr,
|
||||
enum ib_srq_attr_mask srq_attr_mask)
|
||||
{
|
||||
return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_modify_srq);
|
||||
|
||||
int ib_query_srq(struct ib_srq *srq,
|
||||
struct ib_srq_attr *srq_attr)
|
||||
{
|
||||
return srq->device->query_srq ?
|
||||
srq->device->query_srq(srq, srq_attr) : -ENOSYS;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_query_srq);
|
||||
|
||||
int ib_destroy_srq(struct ib_srq *srq)
|
||||
{
|
||||
struct ib_pd *pd;
|
||||
int ret;
|
||||
|
||||
if (atomic_read(&srq->usecnt))
|
||||
return -EBUSY;
|
||||
|
||||
pd = srq->pd;
|
||||
|
||||
ret = srq->device->destroy_srq(srq);
|
||||
if (!ret)
|
||||
atomic_dec(&pd->usecnt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_destroy_srq);
|
||||
|
||||
/* Queue pairs */
|
||||
|
||||
struct ib_qp *ib_create_qp(struct ib_pd *pd,
|
||||
|
@ -1,5 +1,3 @@
|
||||
EXTRA_CFLAGS += -Idrivers/infiniband/include
|
||||
|
||||
ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
@ -9,4 +7,4 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
|
||||
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
|
||||
mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
|
||||
mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
|
||||
mthca_provider.o mthca_memfree.o mthca_uar.o
|
||||
mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o
|
||||
|
@ -177,3 +177,119 @@ void mthca_array_cleanup(struct mthca_array *array, int nent)
|
||||
|
||||
kfree(array->page_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handling for queue buffers -- we allocate a bunch of memory and
|
||||
* register it in a memory region at HCA virtual address 0. If the
|
||||
* requested size is > max_direct, we split the allocation into
|
||||
* multiple pages, so we don't require too much contiguous memory.
|
||||
*/
|
||||
|
||||
int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
|
||||
union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
|
||||
int hca_write, struct mthca_mr *mr)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
int npages, shift;
|
||||
u64 *dma_list = NULL;
|
||||
dma_addr_t t;
|
||||
int i;
|
||||
|
||||
if (size <= max_direct) {
|
||||
*is_direct = 1;
|
||||
npages = 1;
|
||||
shift = get_order(size) + PAGE_SHIFT;
|
||||
|
||||
buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev,
|
||||
size, &t, GFP_KERNEL);
|
||||
if (!buf->direct.buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_unmap_addr_set(&buf->direct, mapping, t);
|
||||
|
||||
memset(buf->direct.buf, 0, size);
|
||||
|
||||
while (t & ((1 << shift) - 1)) {
|
||||
--shift;
|
||||
npages *= 2;
|
||||
}
|
||||
|
||||
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
|
||||
if (!dma_list)
|
||||
goto err_free;
|
||||
|
||||
for (i = 0; i < npages; ++i)
|
||||
dma_list[i] = t + i * (1 << shift);
|
||||
} else {
|
||||
*is_direct = 0;
|
||||
npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
shift = PAGE_SHIFT;
|
||||
|
||||
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
|
||||
if (!dma_list)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->page_list = kmalloc(npages * sizeof *buf->page_list,
|
||||
GFP_KERNEL);
|
||||
if (!buf->page_list)
|
||||
goto err_out;
|
||||
|
||||
for (i = 0; i < npages; ++i)
|
||||
buf->page_list[i].buf = NULL;
|
||||
|
||||
for (i = 0; i < npages; ++i) {
|
||||
buf->page_list[i].buf =
|
||||
dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
|
||||
&t, GFP_KERNEL);
|
||||
if (!buf->page_list[i].buf)
|
||||
goto err_free;
|
||||
|
||||
dma_list[i] = t;
|
||||
pci_unmap_addr_set(&buf->page_list[i], mapping, t);
|
||||
|
||||
memset(buf->page_list[i].buf, 0, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
err = mthca_mr_alloc_phys(dev, pd->pd_num,
|
||||
dma_list, shift, npages,
|
||||
0, size,
|
||||
MTHCA_MPT_FLAG_LOCAL_READ |
|
||||
(hca_write ? MTHCA_MPT_FLAG_LOCAL_WRITE : 0),
|
||||
mr);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
kfree(dma_list);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
mthca_buf_free(dev, size, buf, *is_direct, NULL);
|
||||
|
||||
err_out:
|
||||
kfree(dma_list);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
|
||||
int is_direct, struct mthca_mr *mr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mr)
|
||||
mthca_free_mr(dev, mr);
|
||||
|
||||
if (is_direct)
|
||||
dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
|
||||
pci_unmap_addr(&buf->direct, mapping));
|
||||
else {
|
||||
for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
|
||||
dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
|
||||
buf->page_list[i].buf,
|
||||
pci_unmap_addr(&buf->page_list[i],
|
||||
mapping));
|
||||
kfree(buf->page_list);
|
||||
}
|
||||
}
|
||||
|
@ -35,22 +35,22 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <ib_cache.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
#include "mthca_dev.h"
|
||||
|
||||
struct mthca_av {
|
||||
u32 port_pd;
|
||||
u8 reserved1;
|
||||
u8 g_slid;
|
||||
u16 dlid;
|
||||
u8 reserved2;
|
||||
u8 gid_index;
|
||||
u8 msg_sr;
|
||||
u8 hop_limit;
|
||||
u32 sl_tclass_flowlabel;
|
||||
u32 dgid[4];
|
||||
__be32 port_pd;
|
||||
u8 reserved1;
|
||||
u8 g_slid;
|
||||
__be16 dlid;
|
||||
u8 reserved2;
|
||||
u8 gid_index;
|
||||
u8 msg_sr;
|
||||
u8 hop_limit;
|
||||
__be32 sl_tclass_flowlabel;
|
||||
__be32 dgid[4];
|
||||
};
|
||||
|
||||
int mthca_create_ah(struct mthca_dev *dev,
|
||||
@ -128,7 +128,7 @@ on_hca_fail:
|
||||
av, (unsigned long) ah->avdma);
|
||||
for (j = 0; j < 8; ++j)
|
||||
printk(KERN_DEBUG " [%2x] %08x\n",
|
||||
j * 4, be32_to_cpu(((u32 *) av)[j]));
|
||||
j * 4, be32_to_cpu(((__be32 *) av)[j]));
|
||||
}
|
||||
|
||||
if (ah->type == MTHCA_AH_ON_HCA) {
|
||||
@ -169,7 +169,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
|
||||
|
||||
header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
|
||||
header->lrh.destination_lid = ah->av->dlid;
|
||||
header->lrh.source_lid = ah->av->g_slid & 0x7f;
|
||||
header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f);
|
||||
if (ah->av->g_slid & 0x80) {
|
||||
header->grh_present = 1;
|
||||
header->grh.traffic_class =
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -36,7 +37,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <ib_mad.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
|
||||
#include "mthca_dev.h"
|
||||
#include "mthca_config_reg.h"
|
||||
@ -108,6 +109,7 @@ enum {
|
||||
CMD_SW2HW_SRQ = 0x35,
|
||||
CMD_HW2SW_SRQ = 0x36,
|
||||
CMD_QUERY_SRQ = 0x37,
|
||||
CMD_ARM_SRQ = 0x40,
|
||||
|
||||
/* QP/EE commands */
|
||||
CMD_RST2INIT_QPEE = 0x19,
|
||||
@ -219,20 +221,20 @@ static int mthca_cmd_post(struct mthca_dev *dev,
|
||||
* (and some architectures such as ia64 implement memcpy_toio
|
||||
* in terms of writeb).
|
||||
*/
|
||||
__raw_writel(cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
|
||||
__raw_writel(cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
|
||||
__raw_writel(cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
|
||||
__raw_writel(cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
|
||||
__raw_writel(cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
|
||||
__raw_writel(cpu_to_be32(token << 16), dev->hcr + 5 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(in_param >> 32), dev->hcr + 0 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), dev->hcr + 1 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(in_modifier), dev->hcr + 2 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(out_param >> 32), dev->hcr + 3 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32(token << 16), dev->hcr + 5 * 4);
|
||||
|
||||
/* __raw_writel may not order writes. */
|
||||
wmb();
|
||||
|
||||
__raw_writel(cpu_to_be32((1 << HCR_GO_BIT) |
|
||||
(event ? (1 << HCA_E_BIT) : 0) |
|
||||
(op_modifier << HCR_OPMOD_SHIFT) |
|
||||
op), dev->hcr + 6 * 4);
|
||||
__raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
|
||||
(event ? (1 << HCA_E_BIT) : 0) |
|
||||
(op_modifier << HCR_OPMOD_SHIFT) |
|
||||
op), dev->hcr + 6 * 4);
|
||||
|
||||
out:
|
||||
up(&dev->cmd.hcr_sem);
|
||||
@ -273,12 +275,14 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (out_is_imm) {
|
||||
memcpy_fromio(out_param, dev->hcr + HCR_OUT_PARAM_OFFSET, sizeof (u64));
|
||||
be64_to_cpus(out_param);
|
||||
}
|
||||
if (out_is_imm)
|
||||
*out_param =
|
||||
(u64) be32_to_cpu((__force __be32)
|
||||
__raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
|
||||
(u64) be32_to_cpu((__force __be32)
|
||||
__raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
|
||||
|
||||
*status = be32_to_cpu(__raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
|
||||
*status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
|
||||
|
||||
out:
|
||||
up(&dev->cmd.poll_sem);
|
||||
@ -1029,6 +1033,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
|
||||
|
||||
mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
|
||||
dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz);
|
||||
mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
|
||||
dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz);
|
||||
mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
|
||||
dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz);
|
||||
mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
|
||||
@ -1082,6 +1088,34 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void get_board_id(void *vsd, char *board_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
#define VSD_OFFSET_SIG1 0x00
|
||||
#define VSD_OFFSET_SIG2 0xde
|
||||
#define VSD_OFFSET_MLX_BOARD_ID 0xd0
|
||||
#define VSD_OFFSET_TS_BOARD_ID 0x20
|
||||
|
||||
#define VSD_SIGNATURE_TOPSPIN 0x5ad
|
||||
|
||||
memset(board_id, 0, MTHCA_BOARD_ID_LEN);
|
||||
|
||||
if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
|
||||
be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
|
||||
strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MTHCA_BOARD_ID_LEN);
|
||||
} else {
|
||||
/*
|
||||
* The board ID is a string but the firmware byte
|
||||
* swaps each 4-byte word before passing it back to
|
||||
* us. Therefore we need to swab it before printing.
|
||||
*/
|
||||
for (i = 0; i < 4; ++i)
|
||||
((u32 *) board_id)[i] =
|
||||
swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
|
||||
struct mthca_adapter *adapter, u8 *status)
|
||||
{
|
||||
@ -1094,6 +1128,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
|
||||
#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04
|
||||
#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
|
||||
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
|
||||
#define QUERY_ADAPTER_VSD_OFFSET 0x20
|
||||
|
||||
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
|
||||
if (IS_ERR(mailbox))
|
||||
@ -1111,6 +1146,9 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
|
||||
MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
|
||||
MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
|
||||
|
||||
get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
|
||||
adapter->board_id);
|
||||
|
||||
out:
|
||||
mthca_free_mailbox(dev, mailbox);
|
||||
return err;
|
||||
@ -1121,7 +1159,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
|
||||
u8 *status)
|
||||
{
|
||||
struct mthca_mailbox *mailbox;
|
||||
u32 *inbox;
|
||||
__be32 *inbox;
|
||||
int err;
|
||||
|
||||
#define INIT_HCA_IN_SIZE 0x200
|
||||
@ -1247,10 +1285,8 @@ int mthca_INIT_IB(struct mthca_dev *dev,
|
||||
#define INIT_IB_FLAG_SIG (1 << 18)
|
||||
#define INIT_IB_FLAG_NG (1 << 17)
|
||||
#define INIT_IB_FLAG_G0 (1 << 16)
|
||||
#define INIT_IB_FLAG_1X (1 << 8)
|
||||
#define INIT_IB_FLAG_4X (1 << 9)
|
||||
#define INIT_IB_FLAG_12X (1 << 11)
|
||||
#define INIT_IB_VL_SHIFT 4
|
||||
#define INIT_IB_PORT_WIDTH_SHIFT 8
|
||||
#define INIT_IB_MTU_SHIFT 12
|
||||
#define INIT_IB_MAX_GID_OFFSET 0x06
|
||||
#define INIT_IB_MAX_PKEY_OFFSET 0x0a
|
||||
@ -1266,12 +1302,11 @@ int mthca_INIT_IB(struct mthca_dev *dev,
|
||||
memset(inbox, 0, INIT_IB_IN_SIZE);
|
||||
|
||||
flags = 0;
|
||||
flags |= param->enable_1x ? INIT_IB_FLAG_1X : 0;
|
||||
flags |= param->enable_4x ? INIT_IB_FLAG_4X : 0;
|
||||
flags |= param->set_guid0 ? INIT_IB_FLAG_G0 : 0;
|
||||
flags |= param->set_node_guid ? INIT_IB_FLAG_NG : 0;
|
||||
flags |= param->set_si_guid ? INIT_IB_FLAG_SIG : 0;
|
||||
flags |= param->vl_cap << INIT_IB_VL_SHIFT;
|
||||
flags |= param->port_width << INIT_IB_PORT_WIDTH_SHIFT;
|
||||
flags |= param->mtu_cap << INIT_IB_MTU_SHIFT;
|
||||
MTHCA_PUT(inbox, flags, INIT_IB_FLAGS_OFFSET);
|
||||
|
||||
@ -1342,7 +1377,7 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st
|
||||
int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
|
||||
{
|
||||
struct mthca_mailbox *mailbox;
|
||||
u64 *inbox;
|
||||
__be64 *inbox;
|
||||
int err;
|
||||
|
||||
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
|
||||
@ -1468,6 +1503,27 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
CMD_TIME_CLASS_A, status);
|
||||
}
|
||||
|
||||
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int srq_num, u8 *status)
|
||||
{
|
||||
return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
|
||||
CMD_TIME_CLASS_A, status);
|
||||
}
|
||||
|
||||
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int srq_num, u8 *status)
|
||||
{
|
||||
return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
|
||||
CMD_HW2SW_SRQ,
|
||||
CMD_TIME_CLASS_A, status);
|
||||
}
|
||||
|
||||
int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
|
||||
{
|
||||
return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
|
||||
CMD_TIME_CLASS_B, status);
|
||||
}
|
||||
|
||||
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
|
||||
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
|
||||
u8 *status)
|
||||
@ -1513,7 +1569,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
|
||||
if (i % 8 == 0)
|
||||
printk(" [%02x] ", i * 4);
|
||||
printk(" %08x",
|
||||
be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
|
||||
be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
|
||||
if ((i + 1) % 8 == 0)
|
||||
printk("\n");
|
||||
}
|
||||
@ -1533,7 +1589,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
|
||||
if (i % 8 == 0)
|
||||
printk("[%02x] ", i * 4);
|
||||
printk(" %08x",
|
||||
be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
|
||||
be32_to_cpu(((__be32 *) mailbox->buf)[i + 2]));
|
||||
if ((i + 1) % 8 == 0)
|
||||
printk("\n");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -35,7 +36,7 @@
|
||||
#ifndef MTHCA_CMD_H
|
||||
#define MTHCA_CMD_H
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
#define MTHCA_MAILBOX_SIZE 4096
|
||||
|
||||
@ -183,10 +184,11 @@ struct mthca_dev_lim {
|
||||
};
|
||||
|
||||
struct mthca_adapter {
|
||||
u32 vendor_id;
|
||||
u32 device_id;
|
||||
u32 revision_id;
|
||||
u8 inta_pin;
|
||||
u32 vendor_id;
|
||||
u32 device_id;
|
||||
u32 revision_id;
|
||||
char board_id[MTHCA_BOARD_ID_LEN];
|
||||
u8 inta_pin;
|
||||
};
|
||||
|
||||
struct mthca_init_hca_param {
|
||||
@ -218,8 +220,7 @@ struct mthca_init_hca_param {
|
||||
};
|
||||
|
||||
struct mthca_init_ib_param {
|
||||
int enable_1x;
|
||||
int enable_4x;
|
||||
int port_width;
|
||||
int vl_cap;
|
||||
int mtu_cap;
|
||||
u16 gid_cap;
|
||||
@ -297,6 +298,11 @@ int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int cq_num, u8 *status);
|
||||
int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int cq_num, u8 *status);
|
||||
int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int srq_num, u8 *status);
|
||||
int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
|
||||
int srq_num, u8 *status);
|
||||
int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
|
||||
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
|
||||
int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
|
||||
u8 *status);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
|
@ -2,6 +2,8 @@
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -37,7 +39,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#include <ib_pack.h>
|
||||
#include <rdma/ib_pack.h>
|
||||
|
||||
#include "mthca_dev.h"
|
||||
#include "mthca_cmd.h"
|
||||
@ -55,21 +57,21 @@ enum {
|
||||
* Must be packed because start is 64 bits but only aligned to 32 bits.
|
||||
*/
|
||||
struct mthca_cq_context {
|
||||
u32 flags;
|
||||
u64 start;
|
||||
u32 logsize_usrpage;
|
||||
u32 error_eqn; /* Tavor only */
|
||||
u32 comp_eqn;
|
||||
u32 pd;
|
||||
u32 lkey;
|
||||
u32 last_notified_index;
|
||||
u32 solicit_producer_index;
|
||||
u32 consumer_index;
|
||||
u32 producer_index;
|
||||
u32 cqn;
|
||||
u32 ci_db; /* Arbel only */
|
||||
u32 state_db; /* Arbel only */
|
||||
u32 reserved;
|
||||
__be32 flags;
|
||||
__be64 start;
|
||||
__be32 logsize_usrpage;
|
||||
__be32 error_eqn; /* Tavor only */
|
||||
__be32 comp_eqn;
|
||||
__be32 pd;
|
||||
__be32 lkey;
|
||||
__be32 last_notified_index;
|
||||
__be32 solicit_producer_index;
|
||||
__be32 consumer_index;
|
||||
__be32 producer_index;
|
||||
__be32 cqn;
|
||||
__be32 ci_db; /* Arbel only */
|
||||
__be32 state_db; /* Arbel only */
|
||||
u32 reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MTHCA_CQ_STATUS_OK ( 0 << 28)
|
||||
@ -108,31 +110,31 @@ enum {
|
||||
};
|
||||
|
||||
struct mthca_cqe {
|
||||
u32 my_qpn;
|
||||
u32 my_ee;
|
||||
u32 rqpn;
|
||||
u16 sl_g_mlpath;
|
||||
u16 rlid;
|
||||
u32 imm_etype_pkey_eec;
|
||||
u32 byte_cnt;
|
||||
u32 wqe;
|
||||
u8 opcode;
|
||||
u8 is_send;
|
||||
u8 reserved;
|
||||
u8 owner;
|
||||
__be32 my_qpn;
|
||||
__be32 my_ee;
|
||||
__be32 rqpn;
|
||||
__be16 sl_g_mlpath;
|
||||
__be16 rlid;
|
||||
__be32 imm_etype_pkey_eec;
|
||||
__be32 byte_cnt;
|
||||
__be32 wqe;
|
||||
u8 opcode;
|
||||
u8 is_send;
|
||||
u8 reserved;
|
||||
u8 owner;
|
||||
};
|
||||
|
||||
struct mthca_err_cqe {
|
||||
u32 my_qpn;
|
||||
u32 reserved1[3];
|
||||
u8 syndrome;
|
||||
u8 reserved2;
|
||||
u16 db_cnt;
|
||||
u32 reserved3;
|
||||
u32 wqe;
|
||||
u8 opcode;
|
||||
u8 reserved4[2];
|
||||
u8 owner;
|
||||
__be32 my_qpn;
|
||||
u32 reserved1[3];
|
||||
u8 syndrome;
|
||||
u8 reserved2;
|
||||
__be16 db_cnt;
|
||||
u32 reserved3;
|
||||
__be32 wqe;
|
||||
u8 opcode;
|
||||
u8 reserved4[2];
|
||||
u8 owner;
|
||||
};
|
||||
|
||||
#define MTHCA_CQ_ENTRY_OWNER_SW (0 << 7)
|
||||
@ -191,7 +193,7 @@ static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
|
||||
static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
|
||||
int incr)
|
||||
{
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
|
||||
if (mthca_is_memfree(dev)) {
|
||||
*cq->set_ci_db = cpu_to_be32(cq->cons_index);
|
||||
@ -222,7 +224,8 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
|
||||
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
|
||||
}
|
||||
|
||||
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
|
||||
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
|
||||
struct mthca_srq *srq)
|
||||
{
|
||||
struct mthca_cq *cq;
|
||||
struct mthca_cqe *cqe;
|
||||
@ -263,8 +266,11 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
|
||||
*/
|
||||
while (prod_index > cq->cons_index) {
|
||||
cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe);
|
||||
if (cqe->my_qpn == cpu_to_be32(qpn))
|
||||
if (cqe->my_qpn == cpu_to_be32(qpn)) {
|
||||
if (srq)
|
||||
mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
|
||||
++nfreed;
|
||||
}
|
||||
else if (nfreed)
|
||||
memcpy(get_cqe(cq, (prod_index - 1 + nfreed) &
|
||||
cq->ibcq.cqe),
|
||||
@ -291,7 +297,7 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
|
||||
{
|
||||
int err;
|
||||
int dbd;
|
||||
u32 new_wqe;
|
||||
__be32 new_wqe;
|
||||
|
||||
if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
|
||||
mthca_dbg(dev, "local QP operation err "
|
||||
@ -365,6 +371,13 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mem-free HCAs always generate one CQE per WQE, even in the
|
||||
* error case, so we don't have to check the doorbell count, etc.
|
||||
*/
|
||||
if (mthca_is_memfree(dev))
|
||||
return 0;
|
||||
|
||||
err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
|
||||
if (err)
|
||||
return err;
|
||||
@ -373,12 +386,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
|
||||
* If we're at the end of the WQE chain, or we've used up our
|
||||
* doorbell count, free the CQE. Otherwise just update it for
|
||||
* the next poll operation.
|
||||
*
|
||||
* This does not apply to mem-free HCAs: they don't use the
|
||||
* doorbell count field, and so we should always free the CQE.
|
||||
*/
|
||||
if (mthca_is_memfree(dev) ||
|
||||
!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
|
||||
if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd))
|
||||
return 0;
|
||||
|
||||
cqe->db_cnt = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd);
|
||||
@ -450,23 +459,27 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
|
||||
>> wq->wqe_shift);
|
||||
entry->wr_id = (*cur_qp)->wrid[wqe_index +
|
||||
(*cur_qp)->rq.max];
|
||||
} else if ((*cur_qp)->ibqp.srq) {
|
||||
struct mthca_srq *srq = to_msrq((*cur_qp)->ibqp.srq);
|
||||
u32 wqe = be32_to_cpu(cqe->wqe);
|
||||
wq = NULL;
|
||||
wqe_index = wqe >> srq->wqe_shift;
|
||||
entry->wr_id = srq->wrid[wqe_index];
|
||||
mthca_free_srq_wqe(srq, wqe);
|
||||
} else {
|
||||
wq = &(*cur_qp)->rq;
|
||||
wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
|
||||
entry->wr_id = (*cur_qp)->wrid[wqe_index];
|
||||
}
|
||||
|
||||
if (wq->last_comp < wqe_index)
|
||||
wq->tail += wqe_index - wq->last_comp;
|
||||
else
|
||||
wq->tail += wqe_index + wq->max - wq->last_comp;
|
||||
if (wq) {
|
||||
if (wq->last_comp < wqe_index)
|
||||
wq->tail += wqe_index - wq->last_comp;
|
||||
else
|
||||
wq->tail += wqe_index + wq->max - wq->last_comp;
|
||||
|
||||
wq->last_comp = wqe_index;
|
||||
|
||||
if (0)
|
||||
mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
|
||||
is_send ? "Send" : "Receive",
|
||||
(*cur_qp)->qpn, wqe_index, wq->max);
|
||||
wq->last_comp = wqe_index;
|
||||
}
|
||||
|
||||
if (is_error) {
|
||||
err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
|
||||
@ -584,13 +597,13 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
|
||||
|
||||
int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
|
||||
{
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
|
||||
doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
|
||||
MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
|
||||
MTHCA_TAVOR_CQ_DB_REQ_NOT) |
|
||||
to_mcq(cq)->cqn);
|
||||
doorbell[1] = 0xffffffff;
|
||||
doorbell[1] = (__force __be32) 0xffffffff;
|
||||
|
||||
mthca_write64(doorbell,
|
||||
to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
|
||||
@ -602,9 +615,9 @@ int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
|
||||
int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
|
||||
{
|
||||
struct mthca_cq *cq = to_mcq(ibcq);
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
u32 sn;
|
||||
u32 ci;
|
||||
__be32 ci;
|
||||
|
||||
sn = cq->arm_sn & 3;
|
||||
ci = cpu_to_be32(cq->cons_index);
|
||||
@ -637,113 +650,8 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
|
||||
|
||||
static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
|
||||
if (cq->is_direct)
|
||||
dma_free_coherent(&dev->pdev->dev,
|
||||
(cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
|
||||
cq->queue.direct.buf,
|
||||
pci_unmap_addr(&cq->queue.direct,
|
||||
mapping));
|
||||
else {
|
||||
size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
|
||||
for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
|
||||
if (cq->queue.page_list[i].buf)
|
||||
dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
|
||||
cq->queue.page_list[i].buf,
|
||||
pci_unmap_addr(&cq->queue.page_list[i],
|
||||
mapping));
|
||||
|
||||
kfree(cq->queue.page_list);
|
||||
}
|
||||
}
|
||||
|
||||
static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
|
||||
struct mthca_cq *cq)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
int npages, shift;
|
||||
u64 *dma_list = NULL;
|
||||
dma_addr_t t;
|
||||
int i;
|
||||
|
||||
if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
|
||||
cq->is_direct = 1;
|
||||
npages = 1;
|
||||
shift = get_order(size) + PAGE_SHIFT;
|
||||
|
||||
cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev,
|
||||
size, &t, GFP_KERNEL);
|
||||
if (!cq->queue.direct.buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_unmap_addr_set(&cq->queue.direct, mapping, t);
|
||||
|
||||
memset(cq->queue.direct.buf, 0, size);
|
||||
|
||||
while (t & ((1 << shift) - 1)) {
|
||||
--shift;
|
||||
npages *= 2;
|
||||
}
|
||||
|
||||
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
|
||||
if (!dma_list)
|
||||
goto err_free;
|
||||
|
||||
for (i = 0; i < npages; ++i)
|
||||
dma_list[i] = t + i * (1 << shift);
|
||||
} else {
|
||||
cq->is_direct = 0;
|
||||
npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
shift = PAGE_SHIFT;
|
||||
|
||||
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
|
||||
if (!dma_list)
|
||||
return -ENOMEM;
|
||||
|
||||
cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
|
||||
GFP_KERNEL);
|
||||
if (!cq->queue.page_list)
|
||||
goto err_out;
|
||||
|
||||
for (i = 0; i < npages; ++i)
|
||||
cq->queue.page_list[i].buf = NULL;
|
||||
|
||||
for (i = 0; i < npages; ++i) {
|
||||
cq->queue.page_list[i].buf =
|
||||
dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
|
||||
&t, GFP_KERNEL);
|
||||
if (!cq->queue.page_list[i].buf)
|
||||
goto err_free;
|
||||
|
||||
dma_list[i] = t;
|
||||
pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
|
||||
|
||||
memset(cq->queue.page_list[i].buf, 0, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
|
||||
dma_list, shift, npages,
|
||||
0, size,
|
||||
MTHCA_MPT_FLAG_LOCAL_WRITE |
|
||||
MTHCA_MPT_FLAG_LOCAL_READ,
|
||||
&cq->mr);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
kfree(dma_list);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
mthca_free_cq_buf(dev, cq);
|
||||
|
||||
err_out:
|
||||
kfree(dma_list);
|
||||
|
||||
return err;
|
||||
mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
|
||||
&cq->queue, cq->is_direct, &cq->mr);
|
||||
}
|
||||
|
||||
int mthca_init_cq(struct mthca_dev *dev, int nent,
|
||||
@ -795,7 +703,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
|
||||
cq_context = mailbox->buf;
|
||||
|
||||
if (cq->is_kernel) {
|
||||
err = mthca_alloc_cq_buf(dev, size, cq);
|
||||
err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE,
|
||||
&cq->queue, &cq->is_direct,
|
||||
&dev->driver_pd, 1, &cq->mr);
|
||||
if (err)
|
||||
goto err_out_mailbox;
|
||||
|
||||
@ -811,7 +721,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
|
||||
cq_context->flags = cpu_to_be32(MTHCA_CQ_STATUS_OK |
|
||||
MTHCA_CQ_STATE_DISARMED |
|
||||
MTHCA_CQ_FLAG_TR);
|
||||
cq_context->start = cpu_to_be64(0);
|
||||
cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
|
||||
if (ctx)
|
||||
cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
|
||||
@ -857,10 +766,8 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
|
||||
return 0;
|
||||
|
||||
err_out_free_mr:
|
||||
if (cq->is_kernel) {
|
||||
mthca_free_mr(dev, &cq->mr);
|
||||
if (cq->is_kernel)
|
||||
mthca_free_cq_buf(dev, cq);
|
||||
}
|
||||
|
||||
err_out_mailbox:
|
||||
mthca_free_mailbox(dev, mailbox);
|
||||
@ -904,7 +811,7 @@ void mthca_free_cq(struct mthca_dev *dev,
|
||||
mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
|
||||
|
||||
if (0) {
|
||||
u32 *ctx = mailbox->buf;
|
||||
__be32 *ctx = mailbox->buf;
|
||||
int j;
|
||||
|
||||
printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
|
||||
@ -928,7 +835,6 @@ void mthca_free_cq(struct mthca_dev *dev,
|
||||
wait_event(cq->wait, !atomic_read(&cq->refcount));
|
||||
|
||||
if (cq->is_kernel) {
|
||||
mthca_free_mr(dev, &cq->mr);
|
||||
mthca_free_cq_buf(dev, cq);
|
||||
if (mthca_is_memfree(dev)) {
|
||||
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
|
||||
|
@ -2,6 +2,8 @@
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -66,6 +68,10 @@ enum {
|
||||
MTHCA_MAX_PORTS = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
MTHCA_BOARD_ID_LEN = 64
|
||||
};
|
||||
|
||||
enum {
|
||||
MTHCA_EQ_CONTEXT_SIZE = 0x40,
|
||||
MTHCA_CQ_CONTEXT_SIZE = 0x40,
|
||||
@ -142,6 +148,7 @@ struct mthca_limits {
|
||||
int reserved_mcgs;
|
||||
int num_pds;
|
||||
int reserved_pds;
|
||||
u8 port_width_cap;
|
||||
};
|
||||
|
||||
struct mthca_alloc {
|
||||
@ -211,6 +218,13 @@ struct mthca_cq_table {
|
||||
struct mthca_icm_table *table;
|
||||
};
|
||||
|
||||
struct mthca_srq_table {
|
||||
struct mthca_alloc alloc;
|
||||
spinlock_t lock;
|
||||
struct mthca_array srq;
|
||||
struct mthca_icm_table *table;
|
||||
};
|
||||
|
||||
struct mthca_qp_table {
|
||||
struct mthca_alloc alloc;
|
||||
u32 rdb_base;
|
||||
@ -246,6 +260,7 @@ struct mthca_dev {
|
||||
unsigned long device_cap_flags;
|
||||
|
||||
u32 rev_id;
|
||||
char board_id[MTHCA_BOARD_ID_LEN];
|
||||
|
||||
/* firmware info */
|
||||
u64 fw_ver;
|
||||
@ -291,6 +306,7 @@ struct mthca_dev {
|
||||
struct mthca_mr_table mr_table;
|
||||
struct mthca_eq_table eq_table;
|
||||
struct mthca_cq_table cq_table;
|
||||
struct mthca_srq_table srq_table;
|
||||
struct mthca_qp_table qp_table;
|
||||
struct mthca_av_table av_table;
|
||||
struct mthca_mcg_table mcg_table;
|
||||
@ -331,14 +347,13 @@ extern void __buggy_use_of_MTHCA_PUT(void);
|
||||
|
||||
#define MTHCA_PUT(dest, source, offset) \
|
||||
do { \
|
||||
__typeof__(source) *__p = \
|
||||
(__typeof__(source) *) ((char *) (dest) + (offset)); \
|
||||
void *__d = ((char *) (dest) + (offset)); \
|
||||
switch (sizeof(source)) { \
|
||||
case 1: *__p = (source); break; \
|
||||
case 2: *__p = cpu_to_be16(source); break; \
|
||||
case 4: *__p = cpu_to_be32(source); break; \
|
||||
case 8: *__p = cpu_to_be64(source); break; \
|
||||
default: __buggy_use_of_MTHCA_PUT(); \
|
||||
case 1: *(u8 *) __d = (source); break; \
|
||||
case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
|
||||
case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
|
||||
case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
|
||||
default: __buggy_use_of_MTHCA_PUT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -354,12 +369,18 @@ int mthca_array_set(struct mthca_array *array, int index, void *value);
|
||||
void mthca_array_clear(struct mthca_array *array, int index);
|
||||
int mthca_array_init(struct mthca_array *array, int nent);
|
||||
void mthca_array_cleanup(struct mthca_array *array, int nent);
|
||||
int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
|
||||
union mthca_buf *buf, int *is_direct, struct mthca_pd *pd,
|
||||
int hca_write, struct mthca_mr *mr);
|
||||
void mthca_buf_free(struct mthca_dev *dev, int size, union mthca_buf *buf,
|
||||
int is_direct, struct mthca_mr *mr);
|
||||
|
||||
int mthca_init_uar_table(struct mthca_dev *dev);
|
||||
int mthca_init_pd_table(struct mthca_dev *dev);
|
||||
int mthca_init_mr_table(struct mthca_dev *dev);
|
||||
int mthca_init_eq_table(struct mthca_dev *dev);
|
||||
int mthca_init_cq_table(struct mthca_dev *dev);
|
||||
int mthca_init_srq_table(struct mthca_dev *dev);
|
||||
int mthca_init_qp_table(struct mthca_dev *dev);
|
||||
int mthca_init_av_table(struct mthca_dev *dev);
|
||||
int mthca_init_mcg_table(struct mthca_dev *dev);
|
||||
@ -369,6 +390,7 @@ void mthca_cleanup_pd_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_mr_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_eq_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_cq_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_srq_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_qp_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_av_table(struct mthca_dev *dev);
|
||||
void mthca_cleanup_mcg_table(struct mthca_dev *dev);
|
||||
@ -419,7 +441,19 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
|
||||
void mthca_free_cq(struct mthca_dev *dev,
|
||||
struct mthca_cq *cq);
|
||||
void mthca_cq_event(struct mthca_dev *dev, u32 cqn);
|
||||
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn);
|
||||
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
|
||||
struct mthca_srq *srq);
|
||||
|
||||
int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
|
||||
struct ib_srq_attr *attr, struct mthca_srq *srq);
|
||||
void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
|
||||
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);
|
||||
int mthca_tavor_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
|
||||
struct ib_recv_wr **bad_wr);
|
||||
int mthca_arbel_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr,
|
||||
struct ib_recv_wr **bad_wr);
|
||||
|
||||
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
|
||||
enum ib_event_type event_type);
|
||||
@ -433,7 +467,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
|
||||
struct ib_recv_wr **bad_wr);
|
||||
int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
|
||||
int index, int *dbd, u32 *new_wqe);
|
||||
int index, int *dbd, __be32 *new_wqe);
|
||||
int mthca_alloc_qp(struct mthca_dev *dev,
|
||||
struct mthca_pd *pd,
|
||||
struct mthca_cq *send_cq,
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -57,13 +58,13 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
|
||||
__raw_writeq((__force u64) val, dest);
|
||||
}
|
||||
|
||||
static inline void mthca_write64(u32 val[2], void __iomem *dest,
|
||||
static inline void mthca_write64(__be32 val[2], void __iomem *dest,
|
||||
spinlock_t *doorbell_lock)
|
||||
{
|
||||
__raw_writeq(*(u64 *) val, dest);
|
||||
}
|
||||
|
||||
static inline void mthca_write_db_rec(u32 val[2], u32 *db)
|
||||
static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
|
||||
{
|
||||
*(u64 *) db = *(u64 *) val;
|
||||
}
|
||||
@ -86,18 +87,18 @@ static inline void mthca_write64_raw(__be64 val, void __iomem *dest)
|
||||
__raw_writel(((__force u32 *) &val)[1], dest + 4);
|
||||
}
|
||||
|
||||
static inline void mthca_write64(u32 val[2], void __iomem *dest,
|
||||
static inline void mthca_write64(__be32 val[2], void __iomem *dest,
|
||||
spinlock_t *doorbell_lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(doorbell_lock, flags);
|
||||
__raw_writel(val[0], dest);
|
||||
__raw_writel(val[1], dest + 4);
|
||||
__raw_writel((__force u32) val[0], dest);
|
||||
__raw_writel((__force u32) val[1], dest + 4);
|
||||
spin_unlock_irqrestore(doorbell_lock, flags);
|
||||
}
|
||||
|
||||
static inline void mthca_write_db_rec(u32 val[2], u32 *db)
|
||||
static inline void mthca_write_db_rec(__be32 val[2], __be32 *db)
|
||||
{
|
||||
db[0] = val[0];
|
||||
wmb();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -51,18 +52,18 @@ enum {
|
||||
* Must be packed because start is 64 bits but only aligned to 32 bits.
|
||||
*/
|
||||
struct mthca_eq_context {
|
||||
u32 flags;
|
||||
u64 start;
|
||||
u32 logsize_usrpage;
|
||||
u32 tavor_pd; /* reserved for Arbel */
|
||||
u8 reserved1[3];
|
||||
u8 intr;
|
||||
u32 arbel_pd; /* lost_count for Tavor */
|
||||
u32 lkey;
|
||||
u32 reserved2[2];
|
||||
u32 consumer_index;
|
||||
u32 producer_index;
|
||||
u32 reserved3[4];
|
||||
__be32 flags;
|
||||
__be64 start;
|
||||
__be32 logsize_usrpage;
|
||||
__be32 tavor_pd; /* reserved for Arbel */
|
||||
u8 reserved1[3];
|
||||
u8 intr;
|
||||
__be32 arbel_pd; /* lost_count for Tavor */
|
||||
__be32 lkey;
|
||||
u32 reserved2[2];
|
||||
__be32 consumer_index;
|
||||
__be32 producer_index;
|
||||
u32 reserved3[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MTHCA_EQ_STATUS_OK ( 0 << 28)
|
||||
@ -127,28 +128,28 @@ struct mthca_eqe {
|
||||
union {
|
||||
u32 raw[6];
|
||||
struct {
|
||||
u32 cqn;
|
||||
__be32 cqn;
|
||||
} __attribute__((packed)) comp;
|
||||
struct {
|
||||
u16 reserved1;
|
||||
u16 token;
|
||||
u32 reserved2;
|
||||
u8 reserved3[3];
|
||||
u8 status;
|
||||
u64 out_param;
|
||||
u16 reserved1;
|
||||
__be16 token;
|
||||
u32 reserved2;
|
||||
u8 reserved3[3];
|
||||
u8 status;
|
||||
__be64 out_param;
|
||||
} __attribute__((packed)) cmd;
|
||||
struct {
|
||||
u32 qpn;
|
||||
__be32 qpn;
|
||||
} __attribute__((packed)) qp;
|
||||
struct {
|
||||
u32 cqn;
|
||||
u32 reserved1;
|
||||
u8 reserved2[3];
|
||||
u8 syndrome;
|
||||
__be32 cqn;
|
||||
u32 reserved1;
|
||||
u8 reserved2[3];
|
||||
u8 syndrome;
|
||||
} __attribute__((packed)) cq_err;
|
||||
struct {
|
||||
u32 reserved1[2];
|
||||
u32 port;
|
||||
u32 reserved1[2];
|
||||
__be32 port;
|
||||
} __attribute__((packed)) port_change;
|
||||
} event;
|
||||
u8 reserved3[3];
|
||||
@ -167,7 +168,7 @@ static inline u64 async_mask(struct mthca_dev *dev)
|
||||
|
||||
static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
|
||||
{
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
|
||||
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
|
||||
doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
|
||||
@ -190,8 +191,8 @@ static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u
|
||||
{
|
||||
/* See comment in tavor_set_eq_ci() above. */
|
||||
wmb();
|
||||
__raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
|
||||
eq->eqn * 8);
|
||||
__raw_writel((__force u32) cpu_to_be32(ci),
|
||||
dev->eq_regs.arbel.eq_set_ci_base + eq->eqn * 8);
|
||||
/* We still want ordering, just not swabbing, so add a barrier */
|
||||
mb();
|
||||
}
|
||||
@ -206,7 +207,7 @@ static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
|
||||
|
||||
static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
|
||||
{
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
|
||||
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_REQ_NOT | eqn);
|
||||
doorbell[1] = 0;
|
||||
@ -224,7 +225,7 @@ static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
|
||||
static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
|
||||
{
|
||||
if (!mthca_is_memfree(dev)) {
|
||||
u32 doorbell[2];
|
||||
__be32 doorbell[2];
|
||||
|
||||
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
|
||||
doorbell[1] = cpu_to_be32(cqn);
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
@ -32,9 +34,9 @@
|
||||
* $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $
|
||||
*/
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <ib_mad.h>
|
||||
#include <ib_smi.h>
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <rdma/ib_mad.h>
|
||||
#include <rdma/ib_smi.h>
|
||||
|
||||
#include "mthca_dev.h"
|
||||
#include "mthca_cmd.h"
|
||||
@ -192,7 +194,7 @@ int mthca_process_mad(struct ib_device *ibdev,
|
||||
{
|
||||
int err;
|
||||
u8 status;
|
||||
u16 slid = in_wc ? in_wc->slid : IB_LID_PERMISSIVE;
|
||||
u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
|
||||
|
||||
/* Forward locally generated traps to the SM */
|
||||
if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP &&
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user