Merge commit 'v2.6.27-rc1' into x86/urgent
This commit is contained in:
commit
35780c8ea7
|
@ -528,7 +528,33 @@ See more details on the proper patch format in the following
|
||||||
references.
|
references.
|
||||||
|
|
||||||
|
|
||||||
|
16) Sending "git pull" requests (from Linus emails)
|
||||||
|
|
||||||
|
Please write the git repo address and branch name alone on the same line
|
||||||
|
so that I can't even by mistake pull from the wrong branch, and so
|
||||||
|
that a triple-click just selects the whole thing.
|
||||||
|
|
||||||
|
So the proper format is something along the lines of:
|
||||||
|
|
||||||
|
"Please pull from
|
||||||
|
|
||||||
|
git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
|
||||||
|
|
||||||
|
to get these changes:"
|
||||||
|
|
||||||
|
so that I don't have to hunt-and-peck for the address and inevitably
|
||||||
|
get it wrong (actually, I've only gotten it wrong a few times, and
|
||||||
|
checking against the diffstat tells me when I get it wrong, but I'm
|
||||||
|
just a lot more comfortable when I don't have to "look for" the right
|
||||||
|
thing to pull, and double-check that I have the right branch-name).
|
||||||
|
|
||||||
|
|
||||||
|
Please use "git diff -M --stat --summary" to generate the diffstat:
|
||||||
|
the -M enables rename detection, and the summary enables a summary of
|
||||||
|
new/deleted or renamed files.
|
||||||
|
|
||||||
|
With rename detection, the statistics are rather different [...]
|
||||||
|
because git will notice that a fair number of the changes are renames.
|
||||||
|
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
SECTION 2 - HINTS, TIPS, AND TRICKS
|
SECTION 2 - HINTS, TIPS, AND TRICKS
|
||||||
|
|
|
@ -138,14 +138,8 @@ So, what's changed?
|
||||||
|
|
||||||
Set active the IRQ edge(s)/level. This replaces the
|
Set active the IRQ edge(s)/level. This replaces the
|
||||||
SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
|
SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
|
||||||
function. Type should be one of the following:
|
function. Type should be one of IRQ_TYPE_xxx defined in
|
||||||
|
<linux/irq.h>
|
||||||
#define IRQT_NOEDGE (0)
|
|
||||||
#define IRQT_RISING (__IRQT_RISEDGE)
|
|
||||||
#define IRQT_FALLING (__IRQT_FALEDGE)
|
|
||||||
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
|
|
||||||
#define IRQT_LOW (__IRQT_LOWLVL)
|
|
||||||
#define IRQT_HIGH (__IRQT_HIGHLVL)
|
|
||||||
|
|
||||||
3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
|
3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,30 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: old tuner-3036 i2c driver
|
||||||
|
When: 2.6.28
|
||||||
|
Why: This driver is for VERY old i2c-over-parallel port teletext receiver
|
||||||
|
boxes. Rather then spending effort on converting this driver to V4L2,
|
||||||
|
and since it is extremely unlikely that anyone still uses one of these
|
||||||
|
devices, it was decided to drop it.
|
||||||
|
Who: Hans Verkuil <hverkuil@xs4all.nl>
|
||||||
|
Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: V4L2 dpc7146 driver
|
||||||
|
When: 2.6.28
|
||||||
|
Why: Old driver for the dpc7146 demonstration board that is no longer
|
||||||
|
relevant. The last time this was tested on actual hardware was
|
||||||
|
probably around 2002. Since this is a driver for a demonstration
|
||||||
|
board the decision was made to remove it rather than spending a
|
||||||
|
lot of effort continually updating this driver to stay in sync
|
||||||
|
with the latest internal V4L2 or I2C API.
|
||||||
|
Who: Hans Verkuil <hverkuil@xs4all.nl>
|
||||||
|
Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
|
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
|
||||||
When: November 2005
|
When: November 2005
|
||||||
Files: drivers/pcmcia/: pcmcia_ioctl.c
|
Files: drivers/pcmcia/: pcmcia_ioctl.c
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
Upgrading I2C Drivers to the new 2.6 Driver Model
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
Ben Dooks <ben-linux@fluff.org>
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This guide outlines how to alter existing Linux 2.6 client drivers from
|
||||||
|
the old to the new new binding methods.
|
||||||
|
|
||||||
|
|
||||||
|
Example old-style driver
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
struct i2c_client client;
|
||||||
|
....
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver;
|
||||||
|
|
||||||
|
static unsigned short ignore[] = { I2C_CLIENT_END };
|
||||||
|
static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
I2C_CLIENT_INSMOD;
|
||||||
|
|
||||||
|
static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &adap->dev; /* to use for dev_ reports */
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
example->client.addr = addr;
|
||||||
|
example->client.flags = 0;
|
||||||
|
example->client.adapter = adap;
|
||||||
|
|
||||||
|
i2c_set_clientdata(&state->i2c_client, state);
|
||||||
|
strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
|
||||||
|
|
||||||
|
ret = i2c_attach_client(&state->i2c_client);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "failed to attach client\n");
|
||||||
|
kfree(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &state->i2c_client.dev;
|
||||||
|
|
||||||
|
/* rest of the initialisation goes here. */
|
||||||
|
|
||||||
|
dev_info(dev, "example client created\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit example_detach(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
i2c_detach_client(client);
|
||||||
|
kfree(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int example_attach_adapter(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
return i2c_probe(adap, &addr_data, example_attach);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
.attach_adapter = example_attach_adapter,
|
||||||
|
.detach_client = __devexit_p(example_detach),
|
||||||
|
.suspend = example_suspend,
|
||||||
|
.resume = example_resume,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Updating the client
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The new style binding model will check against a list of supported
|
||||||
|
devices and their associated address supplied by the code registering
|
||||||
|
the busses. This means that the driver .attach_adapter and
|
||||||
|
.detach_adapter methods can be removed, along with the addr_data,
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
- static struct i2c_driver example_driver;
|
||||||
|
|
||||||
|
- static unsigned short ignore[] = { I2C_CLIENT_END };
|
||||||
|
- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
- I2C_CLIENT_INSMOD;
|
||||||
|
|
||||||
|
- static int example_attach_adapter(struct i2c_adapter *adap)
|
||||||
|
- {
|
||||||
|
- return i2c_probe(adap, &addr_data, example_attach);
|
||||||
|
- }
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
- .attach_adapter = example_attach_adapter,
|
||||||
|
- .detach_client = __devexit_p(example_detach),
|
||||||
|
}
|
||||||
|
|
||||||
|
Add the probe and remove methods to the i2c_driver, as so:
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
+ .probe = example_probe,
|
||||||
|
+ .remove = __devexit_p(example_remove),
|
||||||
|
}
|
||||||
|
|
||||||
|
Change the example_attach method to accept the new parameters
|
||||||
|
which include the i2c_client that it will be working with:
|
||||||
|
|
||||||
|
- static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
||||||
|
+ static int example_probe(struct i2c_client *client,
|
||||||
|
+ const struct i2c_device_id *id)
|
||||||
|
|
||||||
|
Change the name of example_attach to example_probe to align it with the
|
||||||
|
i2c_driver entry names. The rest of the probe routine will now need to be
|
||||||
|
changed as the i2c_client has already been setup for use.
|
||||||
|
|
||||||
|
The necessary client fields have already been setup before
|
||||||
|
the probe function is called, so the following client setup
|
||||||
|
can be removed:
|
||||||
|
|
||||||
|
- example->client.addr = addr;
|
||||||
|
- example->client.flags = 0;
|
||||||
|
- example->client.adapter = adap;
|
||||||
|
-
|
||||||
|
- strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
|
||||||
|
|
||||||
|
The i2c_set_clientdata is now:
|
||||||
|
|
||||||
|
- i2c_set_clientdata(&state->client, state);
|
||||||
|
+ i2c_set_clientdata(client, state);
|
||||||
|
|
||||||
|
The call to i2c_attach_client is no longer needed, if the probe
|
||||||
|
routine exits successfully, then the driver will be automatically
|
||||||
|
attached by the core. Change the probe routine as so:
|
||||||
|
|
||||||
|
- ret = i2c_attach_client(&state->i2c_client);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "failed to attach client\n");
|
||||||
|
- kfree(state);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
|
||||||
|
|
||||||
|
Remove the storage of 'struct i2c_client' from the 'struct example_state'
|
||||||
|
as we are provided with the i2c_client in our example_probe. Instead we
|
||||||
|
store a pointer to it for when it is needed.
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
- struct i2c_client client;
|
||||||
|
+ struct i2c_client *client;
|
||||||
|
|
||||||
|
the new i2c client as so:
|
||||||
|
|
||||||
|
- struct device *dev = &adap->dev; /* to use for dev_ reports */
|
||||||
|
+ struct device *dev = &i2c_client->dev; /* to use for dev_ reports */
|
||||||
|
|
||||||
|
And remove the change after our client is attached, as the driver no
|
||||||
|
longer needs to register a new client structure with the core:
|
||||||
|
|
||||||
|
- dev = &state->i2c_client.dev;
|
||||||
|
|
||||||
|
In the probe routine, ensure that the new state has the client stored
|
||||||
|
in it:
|
||||||
|
|
||||||
|
static int example_probe(struct i2c_client *i2c_client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &i2c_client->dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ state->client = i2c_client;
|
||||||
|
|
||||||
|
Update the detach method, by changing the name to _remove and
|
||||||
|
to delete the i2c_detach_client call. It is possible that you
|
||||||
|
can also remove the ret variable as it is not not needed for
|
||||||
|
any of the core functions.
|
||||||
|
|
||||||
|
- static int __devexit example_detach(struct i2c_client *client)
|
||||||
|
+ static int __devexit example_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
- i2c_detach_client(client);
|
||||||
|
|
||||||
|
And finally ensure that we have the correct ID table for the i2c-core
|
||||||
|
and other utilities:
|
||||||
|
|
||||||
|
+ struct i2c_device_id example_idtable[] = {
|
||||||
|
+ { "example", 0 },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(i2c, example_idtable);
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
+ .id_table = example_ids,
|
||||||
|
|
||||||
|
|
||||||
|
Our driver should now look like this:
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
struct i2c_client *client;
|
||||||
|
....
|
||||||
|
};
|
||||||
|
|
||||||
|
static int example_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &client->dev;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->client = client;
|
||||||
|
i2c_set_clientdata(client, state);
|
||||||
|
|
||||||
|
/* rest of the initialisation goes here. */
|
||||||
|
|
||||||
|
dev_info(dev, "example client created\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit example_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
kfree(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_device_id example_idtable[] = {
|
||||||
|
{ "example", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(i2c, example_idtable);
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
.id_table = example_idtable,
|
||||||
|
.probe = example_probe,
|
||||||
|
.remove = __devexit_p(example_remove),
|
||||||
|
.suspend = example_suspend,
|
||||||
|
.resume = example_resume,
|
||||||
|
};
|
|
@ -65,26 +65,26 @@ Install kexec-tools
|
||||||
|
|
||||||
2) Download the kexec-tools user-space package from the following URL:
|
2) Download the kexec-tools user-space package from the following URL:
|
||||||
|
|
||||||
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-testing.tar.gz
|
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools.tar.gz
|
||||||
|
|
||||||
This is a symlink to the latest version, which at the time of writing is
|
This is a symlink to the latest version.
|
||||||
20061214, the only release of kexec-tools-testing so far. As other versions
|
|
||||||
are released, the older ones will remain available at
|
|
||||||
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
|
|
||||||
|
|
||||||
Note: Latest kexec-tools-testing git tree is available at
|
The latest kexec-tools git tree is available at:
|
||||||
|
|
||||||
git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools-testing.git
|
git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools.git
|
||||||
or
|
or
|
||||||
http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools-testing.git;a=summary
|
http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools.git
|
||||||
|
|
||||||
|
More information about kexec-tools can be found at
|
||||||
|
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/README.html
|
||||||
|
|
||||||
3) Unpack the tarball with the tar command, as follows:
|
3) Unpack the tarball with the tar command, as follows:
|
||||||
|
|
||||||
tar xvpzf kexec-tools-testing.tar.gz
|
tar xvpzf kexec-tools.tar.gz
|
||||||
|
|
||||||
4) Change to the kexec-tools directory, as follows:
|
4) Change to the kexec-tools directory, as follows:
|
||||||
|
|
||||||
cd kexec-tools-testing-VERSION
|
cd kexec-tools-VERSION
|
||||||
|
|
||||||
5) Configure the package, as follows:
|
5) Configure the package, as follows:
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,13 @@
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <signal.h>
|
||||||
#include "linux/lguest_launcher.h"
|
#include "linux/lguest_launcher.h"
|
||||||
#include "linux/virtio_config.h"
|
#include "linux/virtio_config.h"
|
||||||
#include "linux/virtio_net.h"
|
#include "linux/virtio_net.h"
|
||||||
#include "linux/virtio_blk.h"
|
#include "linux/virtio_blk.h"
|
||||||
#include "linux/virtio_console.h"
|
#include "linux/virtio_console.h"
|
||||||
|
#include "linux/virtio_rng.h"
|
||||||
#include "linux/virtio_ring.h"
|
#include "linux/virtio_ring.h"
|
||||||
#include "asm-x86/bootparam.h"
|
#include "asm-x86/bootparam.h"
|
||||||
/*L:110 We can ignore the 39 include files we need for this program, but I do
|
/*L:110 We can ignore the 39 include files we need for this program, but I do
|
||||||
|
@ -64,8 +66,8 @@ typedef uint8_t u8;
|
||||||
#endif
|
#endif
|
||||||
/* We can have up to 256 pages for devices. */
|
/* We can have up to 256 pages for devices. */
|
||||||
#define DEVICE_PAGES 256
|
#define DEVICE_PAGES 256
|
||||||
/* This will occupy 2 pages: it must be a power of 2. */
|
/* This will occupy 3 pages: it must be a power of 2. */
|
||||||
#define VIRTQUEUE_NUM 128
|
#define VIRTQUEUE_NUM 256
|
||||||
|
|
||||||
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
|
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
|
||||||
* this, and although I wouldn't recommend it, it works quite nicely here. */
|
* this, and although I wouldn't recommend it, it works quite nicely here. */
|
||||||
|
@ -74,12 +76,19 @@ static bool verbose;
|
||||||
do { if (verbose) printf(args); } while(0)
|
do { if (verbose) printf(args); } while(0)
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
/* The pipe to send commands to the waker process */
|
/* File descriptors for the Waker. */
|
||||||
static int waker_fd;
|
struct {
|
||||||
|
int pipe[2];
|
||||||
|
int lguest_fd;
|
||||||
|
} waker_fds;
|
||||||
|
|
||||||
/* The pointer to the start of guest memory. */
|
/* The pointer to the start of guest memory. */
|
||||||
static void *guest_base;
|
static void *guest_base;
|
||||||
/* The maximum guest physical address allowed, and maximum possible. */
|
/* The maximum guest physical address allowed, and maximum possible. */
|
||||||
static unsigned long guest_limit, guest_max;
|
static unsigned long guest_limit, guest_max;
|
||||||
|
/* The pipe for signal hander to write to. */
|
||||||
|
static int timeoutpipe[2];
|
||||||
|
static unsigned int timeout_usec = 500;
|
||||||
|
|
||||||
/* a per-cpu variable indicating whose vcpu is currently running */
|
/* a per-cpu variable indicating whose vcpu is currently running */
|
||||||
static unsigned int __thread cpu_id;
|
static unsigned int __thread cpu_id;
|
||||||
|
@ -155,11 +164,14 @@ struct virtqueue
|
||||||
/* Last available index we saw. */
|
/* Last available index we saw. */
|
||||||
u16 last_avail_idx;
|
u16 last_avail_idx;
|
||||||
|
|
||||||
/* The routine to call when the Guest pings us. */
|
/* The routine to call when the Guest pings us, or timeout. */
|
||||||
void (*handle_output)(int fd, struct virtqueue *me);
|
void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
|
||||||
|
|
||||||
/* Outstanding buffers */
|
/* Outstanding buffers */
|
||||||
unsigned int inflight;
|
unsigned int inflight;
|
||||||
|
|
||||||
|
/* Is this blocked awaiting a timer? */
|
||||||
|
bool blocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Remember the arguments to the program so we can "reboot" */
|
/* Remember the arguments to the program so we can "reboot" */
|
||||||
|
@ -190,6 +202,9 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
|
||||||
return iov->iov_base;
|
return iov->iov_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrapper for the last available index. Makes it easier to change. */
|
||||||
|
#define lg_last_avail(vq) ((vq)->last_avail_idx)
|
||||||
|
|
||||||
/* The virtio configuration space is defined to be little-endian. x86 is
|
/* The virtio configuration space is defined to be little-endian. x86 is
|
||||||
* little-endian too, but it's nice to be explicit so we have these helpers. */
|
* little-endian too, but it's nice to be explicit so we have these helpers. */
|
||||||
#define cpu_to_le16(v16) (v16)
|
#define cpu_to_le16(v16) (v16)
|
||||||
|
@ -199,6 +214,33 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
|
||||||
#define le32_to_cpu(v32) (v32)
|
#define le32_to_cpu(v32) (v32)
|
||||||
#define le64_to_cpu(v64) (v64)
|
#define le64_to_cpu(v64) (v64)
|
||||||
|
|
||||||
|
/* Is this iovec empty? */
|
||||||
|
static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_iov; i++)
|
||||||
|
if (iov[i].iov_len)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take len bytes from the front of this iovec. */
|
||||||
|
static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_iov; i++) {
|
||||||
|
unsigned int used;
|
||||||
|
|
||||||
|
used = iov[i].iov_len < len ? iov[i].iov_len : len;
|
||||||
|
iov[i].iov_base += used;
|
||||||
|
iov[i].iov_len -= used;
|
||||||
|
len -= used;
|
||||||
|
}
|
||||||
|
assert(len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* The device virtqueue descriptors are followed by feature bitmasks. */
|
/* The device virtqueue descriptors are followed by feature bitmasks. */
|
||||||
static u8 *get_feature_bits(struct device *dev)
|
static u8 *get_feature_bits(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -254,6 +296,7 @@ static void *map_zeroed_pages(unsigned int num)
|
||||||
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
|
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
if (addr == MAP_FAILED)
|
if (addr == MAP_FAILED)
|
||||||
err(1, "Mmaping %u pages of /dev/zero", num);
|
err(1, "Mmaping %u pages of /dev/zero", num);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
@ -540,69 +583,64 @@ static void add_device_fd(int fd)
|
||||||
* watch, but handing a file descriptor mask through to the kernel is fairly
|
* watch, but handing a file descriptor mask through to the kernel is fairly
|
||||||
* icky.
|
* icky.
|
||||||
*
|
*
|
||||||
* Instead, we fork off a process which watches the file descriptors and writes
|
* Instead, we clone off a thread which watches the file descriptors and writes
|
||||||
* the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
|
* the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
|
||||||
* stop running the Guest. This causes the Launcher to return from the
|
* stop running the Guest. This causes the Launcher to return from the
|
||||||
* /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
|
* /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
|
||||||
* the LHREQ_BREAK and wake us up again.
|
* the LHREQ_BREAK and wake us up again.
|
||||||
*
|
*
|
||||||
* This, of course, is merely a different *kind* of icky.
|
* This, of course, is merely a different *kind* of icky.
|
||||||
|
*
|
||||||
|
* Given my well-known antipathy to threads, I'd prefer to use processes. But
|
||||||
|
* it's easier to share Guest memory with threads, and trivial to share the
|
||||||
|
* devices.infds as the Launcher changes it.
|
||||||
*/
|
*/
|
||||||
static void wake_parent(int pipefd, int lguest_fd)
|
static int waker(void *unused)
|
||||||
{
|
{
|
||||||
/* Add the pipe from the Launcher to the fdset in the device_list, so
|
/* Close the write end of the pipe: only the Launcher has it open. */
|
||||||
* we watch it, too. */
|
close(waker_fds.pipe[1]);
|
||||||
add_device_fd(pipefd);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set rfds = devices.infds;
|
fd_set rfds = devices.infds;
|
||||||
unsigned long args[] = { LHREQ_BREAK, 1 };
|
unsigned long args[] = { LHREQ_BREAK, 1 };
|
||||||
|
unsigned int maxfd = devices.max_infd;
|
||||||
|
|
||||||
|
/* We also listen to the pipe from the Launcher. */
|
||||||
|
FD_SET(waker_fds.pipe[0], &rfds);
|
||||||
|
if (waker_fds.pipe[0] > maxfd)
|
||||||
|
maxfd = waker_fds.pipe[0];
|
||||||
|
|
||||||
/* Wait until input is ready from one of the devices. */
|
/* Wait until input is ready from one of the devices. */
|
||||||
select(devices.max_infd+1, &rfds, NULL, NULL, NULL);
|
select(maxfd+1, &rfds, NULL, NULL, NULL);
|
||||||
/* Is it a message from the Launcher? */
|
|
||||||
if (FD_ISSET(pipefd, &rfds)) {
|
/* Message from Launcher? */
|
||||||
int fd;
|
if (FD_ISSET(waker_fds.pipe[0], &rfds)) {
|
||||||
/* If read() returns 0, it means the Launcher has
|
char c;
|
||||||
* exited. We silently follow. */
|
/* If this fails, then assume Launcher has exited.
|
||||||
if (read(pipefd, &fd, sizeof(fd)) == 0)
|
* Don't do anything on exit: we're just a thread! */
|
||||||
exit(0);
|
if (read(waker_fds.pipe[0], &c, 1) != 1)
|
||||||
/* Otherwise it's telling us to change what file
|
_exit(0);
|
||||||
* descriptors we're to listen to. Positive means
|
continue;
|
||||||
* listen to a new one, negative means stop
|
}
|
||||||
* listening. */
|
|
||||||
if (fd >= 0)
|
/* Send LHREQ_BREAK command to snap the Launcher out of it. */
|
||||||
FD_SET(fd, &devices.infds);
|
pwrite(waker_fds.lguest_fd, args, sizeof(args), cpu_id);
|
||||||
else
|
|
||||||
FD_CLR(-fd - 1, &devices.infds);
|
|
||||||
} else /* Send LHREQ_BREAK command. */
|
|
||||||
pwrite(lguest_fd, args, sizeof(args), cpu_id);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This routine just sets up a pipe to the Waker process. */
|
/* This routine just sets up a pipe to the Waker process. */
|
||||||
static int setup_waker(int lguest_fd)
|
static void setup_waker(int lguest_fd)
|
||||||
{
|
{
|
||||||
int pipefd[2], child;
|
/* This pipe is closed when Launcher dies, telling Waker. */
|
||||||
|
if (pipe(waker_fds.pipe) != 0)
|
||||||
|
err(1, "Creating pipe for Waker");
|
||||||
|
|
||||||
/* We create a pipe to talk to the Waker, and also so it knows when the
|
/* Waker also needs to know the lguest fd */
|
||||||
* Launcher dies (and closes pipe). */
|
waker_fds.lguest_fd = lguest_fd;
|
||||||
pipe(pipefd);
|
|
||||||
child = fork();
|
|
||||||
if (child == -1)
|
|
||||||
err(1, "forking");
|
|
||||||
|
|
||||||
if (child == 0) {
|
if (clone(waker, malloc(4096) + 4096, CLONE_VM | SIGCHLD, NULL) == -1)
|
||||||
/* We are the Waker: close the "writing" end of our copy of the
|
err(1, "Creating Waker");
|
||||||
* pipe and start waiting for input. */
|
|
||||||
close(pipefd[1]);
|
|
||||||
wake_parent(pipefd[0], lguest_fd);
|
|
||||||
}
|
|
||||||
/* Close the reading end of our copy of the pipe. */
|
|
||||||
close(pipefd[0]);
|
|
||||||
|
|
||||||
/* Here is the fd used to talk to the waker. */
|
|
||||||
return pipefd[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -661,19 +699,22 @@ static unsigned get_vq_desc(struct virtqueue *vq,
|
||||||
unsigned int *out_num, unsigned int *in_num)
|
unsigned int *out_num, unsigned int *in_num)
|
||||||
{
|
{
|
||||||
unsigned int i, head;
|
unsigned int i, head;
|
||||||
|
u16 last_avail;
|
||||||
|
|
||||||
/* Check it isn't doing very strange things with descriptor numbers. */
|
/* Check it isn't doing very strange things with descriptor numbers. */
|
||||||
if ((u16)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
|
last_avail = lg_last_avail(vq);
|
||||||
|
if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
|
||||||
errx(1, "Guest moved used index from %u to %u",
|
errx(1, "Guest moved used index from %u to %u",
|
||||||
vq->last_avail_idx, vq->vring.avail->idx);
|
last_avail, vq->vring.avail->idx);
|
||||||
|
|
||||||
/* If there's nothing new since last we looked, return invalid. */
|
/* If there's nothing new since last we looked, return invalid. */
|
||||||
if (vq->vring.avail->idx == vq->last_avail_idx)
|
if (vq->vring.avail->idx == last_avail)
|
||||||
return vq->vring.num;
|
return vq->vring.num;
|
||||||
|
|
||||||
/* Grab the next descriptor number they're advertising, and increment
|
/* Grab the next descriptor number they're advertising, and increment
|
||||||
* the index we've seen. */
|
* the index we've seen. */
|
||||||
head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
|
head = vq->vring.avail->ring[last_avail % vq->vring.num];
|
||||||
|
lg_last_avail(vq)++;
|
||||||
|
|
||||||
/* If their number is silly, that's a fatal mistake. */
|
/* If their number is silly, that's a fatal mistake. */
|
||||||
if (head >= vq->vring.num)
|
if (head >= vq->vring.num)
|
||||||
|
@ -821,8 +862,8 @@ static bool handle_console_input(int fd, struct device *dev)
|
||||||
unsigned long args[] = { LHREQ_BREAK, 0 };
|
unsigned long args[] = { LHREQ_BREAK, 0 };
|
||||||
/* Close the fd so Waker will know it has to
|
/* Close the fd so Waker will know it has to
|
||||||
* exit. */
|
* exit. */
|
||||||
close(waker_fd);
|
close(waker_fds.pipe[1]);
|
||||||
/* Just in case waker is blocked in BREAK, send
|
/* Just in case Waker is blocked in BREAK, send
|
||||||
* unbreak now. */
|
* unbreak now. */
|
||||||
write(fd, args, sizeof(args));
|
write(fd, args, sizeof(args));
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -839,7 +880,7 @@ static bool handle_console_input(int fd, struct device *dev)
|
||||||
|
|
||||||
/* Handling output for console is simple: we just get all the output buffers
|
/* Handling output for console is simple: we just get all the output buffers
|
||||||
* and write them to stdout. */
|
* and write them to stdout. */
|
||||||
static void handle_console_output(int fd, struct virtqueue *vq)
|
static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
unsigned int head, out, in;
|
unsigned int head, out, in;
|
||||||
int len;
|
int len;
|
||||||
|
@ -854,6 +895,21 @@ static void handle_console_output(int fd, struct virtqueue *vq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void block_vq(struct virtqueue *vq)
|
||||||
|
{
|
||||||
|
struct itimerval itm;
|
||||||
|
|
||||||
|
vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
|
vq->blocked = true;
|
||||||
|
|
||||||
|
itm.it_interval.tv_sec = 0;
|
||||||
|
itm.it_interval.tv_usec = 0;
|
||||||
|
itm.it_value.tv_sec = 0;
|
||||||
|
itm.it_value.tv_usec = timeout_usec;
|
||||||
|
|
||||||
|
setitimer(ITIMER_REAL, &itm, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Network
|
* The Network
|
||||||
*
|
*
|
||||||
|
@ -861,22 +917,34 @@ static void handle_console_output(int fd, struct virtqueue *vq)
|
||||||
* and write them (ignoring the first element) to this device's file descriptor
|
* and write them (ignoring the first element) to this device's file descriptor
|
||||||
* (/dev/net/tun).
|
* (/dev/net/tun).
|
||||||
*/
|
*/
|
||||||
static void handle_net_output(int fd, struct virtqueue *vq)
|
static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
unsigned int head, out, in;
|
unsigned int head, out, in, num = 0;
|
||||||
int len;
|
int len;
|
||||||
struct iovec iov[vq->vring.num];
|
struct iovec iov[vq->vring.num];
|
||||||
|
static int last_timeout_num;
|
||||||
|
|
||||||
/* Keep getting output buffers from the Guest until we run out. */
|
/* Keep getting output buffers from the Guest until we run out. */
|
||||||
while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
|
while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
|
||||||
if (in)
|
if (in)
|
||||||
errx(1, "Input buffers in output queue?");
|
errx(1, "Input buffers in output queue?");
|
||||||
/* Check header, but otherwise ignore it (we told the Guest we
|
len = writev(vq->dev->fd, iov, out);
|
||||||
* supported no features, so it shouldn't have anything
|
if (len < 0)
|
||||||
* interesting). */
|
err(1, "Writing network packet to tun");
|
||||||
(void)convert(&iov[0], struct virtio_net_hdr);
|
|
||||||
len = writev(vq->dev->fd, iov+1, out-1);
|
|
||||||
add_used_and_trigger(fd, vq, head, len);
|
add_used_and_trigger(fd, vq, head, len);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block further kicks and set up a timer if we saw anything. */
|
||||||
|
if (!timeout && num)
|
||||||
|
block_vq(vq);
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
if (num < last_timeout_num)
|
||||||
|
timeout_usec += 10;
|
||||||
|
else if (timeout_usec > 1)
|
||||||
|
timeout_usec--;
|
||||||
|
last_timeout_num = num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +955,6 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
unsigned int head, in_num, out_num;
|
unsigned int head, in_num, out_num;
|
||||||
int len;
|
int len;
|
||||||
struct iovec iov[dev->vq->vring.num];
|
struct iovec iov[dev->vq->vring.num];
|
||||||
struct virtio_net_hdr *hdr;
|
|
||||||
|
|
||||||
/* First we need a network buffer from the Guests's recv virtqueue. */
|
/* First we need a network buffer from the Guests's recv virtqueue. */
|
||||||
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
||||||
|
@ -896,25 +963,23 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
* early, the Guest won't be ready yet. Wait until the device
|
* early, the Guest won't be ready yet. Wait until the device
|
||||||
* status says it's ready. */
|
* status says it's ready. */
|
||||||
/* FIXME: Actually want DRIVER_ACTIVE here. */
|
/* FIXME: Actually want DRIVER_ACTIVE here. */
|
||||||
if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK)
|
|
||||||
warn("network: no dma buffer!");
|
/* Now tell it we want to know if new things appear. */
|
||||||
|
dev->vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||||
|
wmb();
|
||||||
|
|
||||||
/* We'll turn this back on if input buffers are registered. */
|
/* We'll turn this back on if input buffers are registered. */
|
||||||
return false;
|
return false;
|
||||||
} else if (out_num)
|
} else if (out_num)
|
||||||
errx(1, "Output buffers in network recv queue?");
|
errx(1, "Output buffers in network recv queue?");
|
||||||
|
|
||||||
/* First element is the header: we set it to 0 (no features). */
|
|
||||||
hdr = convert(&iov[0], struct virtio_net_hdr);
|
|
||||||
hdr->flags = 0;
|
|
||||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
|
|
||||||
|
|
||||||
/* Read the packet from the device directly into the Guest's buffer. */
|
/* Read the packet from the device directly into the Guest's buffer. */
|
||||||
len = readv(dev->fd, iov+1, in_num-1);
|
len = readv(dev->fd, iov, in_num);
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
err(1, "reading network");
|
err(1, "reading network");
|
||||||
|
|
||||||
/* Tell the Guest about the new packet. */
|
/* Tell the Guest about the new packet. */
|
||||||
add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len);
|
add_used_and_trigger(fd, dev->vq, head, len);
|
||||||
|
|
||||||
verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
|
verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
|
||||||
((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
|
((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
|
||||||
|
@ -927,11 +992,18 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
/*L:215 This is the callback attached to the network and console input
|
/*L:215 This is the callback attached to the network and console input
|
||||||
* virtqueues: it ensures we try again, in case we stopped console or net
|
* virtqueues: it ensures we try again, in case we stopped console or net
|
||||||
* delivery because Guest didn't have any buffers. */
|
* delivery because Guest didn't have any buffers. */
|
||||||
static void enable_fd(int fd, struct virtqueue *vq)
|
static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
add_device_fd(vq->dev->fd);
|
add_device_fd(vq->dev->fd);
|
||||||
/* Tell waker to listen to it again */
|
/* Snap the Waker out of its select loop. */
|
||||||
write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
|
write(waker_fds.pipe[1], "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
|
||||||
|
{
|
||||||
|
/* We don't need to know again when Guest refills receive buffer. */
|
||||||
|
vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
|
enable_fd(fd, vq, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the Guest tells us they updated the status field, we handle it. */
|
/* When the Guest tells us they updated the status field, we handle it. */
|
||||||
|
@ -951,7 +1023,7 @@ static void update_device_status(struct device *dev)
|
||||||
for (vq = dev->vq; vq; vq = vq->next) {
|
for (vq = dev->vq; vq; vq = vq->next) {
|
||||||
memset(vq->vring.desc, 0,
|
memset(vq->vring.desc, 0,
|
||||||
vring_size(vq->config.num, getpagesize()));
|
vring_size(vq->config.num, getpagesize()));
|
||||||
vq->last_avail_idx = 0;
|
lg_last_avail(vq) = 0;
|
||||||
}
|
}
|
||||||
} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
|
} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
|
||||||
warnx("Device %s configuration FAILED", dev->name);
|
warnx("Device %s configuration FAILED", dev->name);
|
||||||
|
@ -960,10 +1032,10 @@ static void update_device_status(struct device *dev)
|
||||||
|
|
||||||
verbose("Device %s OK: offered", dev->name);
|
verbose("Device %s OK: offered", dev->name);
|
||||||
for (i = 0; i < dev->desc->feature_len; i++)
|
for (i = 0; i < dev->desc->feature_len; i++)
|
||||||
verbose(" %08x", get_feature_bits(dev)[i]);
|
verbose(" %02x", get_feature_bits(dev)[i]);
|
||||||
verbose(", accepted");
|
verbose(", accepted");
|
||||||
for (i = 0; i < dev->desc->feature_len; i++)
|
for (i = 0; i < dev->desc->feature_len; i++)
|
||||||
verbose(" %08x", get_feature_bits(dev)
|
verbose(" %02x", get_feature_bits(dev)
|
||||||
[dev->desc->feature_len+i]);
|
[dev->desc->feature_len+i]);
|
||||||
|
|
||||||
if (dev->ready)
|
if (dev->ready)
|
||||||
|
@ -1000,7 +1072,7 @@ static void handle_output(int fd, unsigned long addr)
|
||||||
if (strcmp(vq->dev->name, "console") != 0)
|
if (strcmp(vq->dev->name, "console") != 0)
|
||||||
verbose("Output to %s\n", vq->dev->name);
|
verbose("Output to %s\n", vq->dev->name);
|
||||||
if (vq->handle_output)
|
if (vq->handle_output)
|
||||||
vq->handle_output(fd, vq);
|
vq->handle_output(fd, vq, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1014,6 +1086,29 @@ static void handle_output(int fd, unsigned long addr)
|
||||||
strnlen(from_guest_phys(addr), guest_limit - addr));
|
strnlen(from_guest_phys(addr), guest_limit - addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_timeout(int fd)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
struct device *i;
|
||||||
|
struct virtqueue *vq;
|
||||||
|
|
||||||
|
/* Clear the pipe */
|
||||||
|
read(timeoutpipe[0], buf, sizeof(buf));
|
||||||
|
|
||||||
|
/* Check each device and virtqueue: flush blocked ones. */
|
||||||
|
for (i = devices.dev; i; i = i->next) {
|
||||||
|
for (vq = i->vq; vq; vq = vq->next) {
|
||||||
|
if (!vq->blocked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||||
|
vq->blocked = false;
|
||||||
|
if (vq->handle_output)
|
||||||
|
vq->handle_output(fd, vq, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This is called when the Waker wakes us up: check for incoming file
|
/* This is called when the Waker wakes us up: check for incoming file
|
||||||
* descriptors. */
|
* descriptors. */
|
||||||
static void handle_input(int fd)
|
static void handle_input(int fd)
|
||||||
|
@ -1024,16 +1119,20 @@ static void handle_input(int fd)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct device *i;
|
struct device *i;
|
||||||
fd_set fds = devices.infds;
|
fd_set fds = devices.infds;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
num = select(devices.max_infd+1, &fds, NULL, NULL, &poll);
|
||||||
|
/* Could get interrupted */
|
||||||
|
if (num < 0)
|
||||||
|
continue;
|
||||||
/* If nothing is ready, we're done. */
|
/* If nothing is ready, we're done. */
|
||||||
if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0)
|
if (num == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Otherwise, call the device(s) which have readable file
|
/* Otherwise, call the device(s) which have readable file
|
||||||
* descriptors and a method of handling them. */
|
* descriptors and a method of handling them. */
|
||||||
for (i = devices.dev; i; i = i->next) {
|
for (i = devices.dev; i; i = i->next) {
|
||||||
if (i->handle_input && FD_ISSET(i->fd, &fds)) {
|
if (i->handle_input && FD_ISSET(i->fd, &fds)) {
|
||||||
int dev_fd;
|
|
||||||
if (i->handle_input(fd, i))
|
if (i->handle_input(fd, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1043,13 +1142,12 @@ static void handle_input(int fd)
|
||||||
* buffers to deliver into. Console also uses
|
* buffers to deliver into. Console also uses
|
||||||
* it when it discovers that stdin is closed. */
|
* it when it discovers that stdin is closed. */
|
||||||
FD_CLR(i->fd, &devices.infds);
|
FD_CLR(i->fd, &devices.infds);
|
||||||
/* Tell waker to ignore it too, by sending a
|
|
||||||
* negative fd number (-1, since 0 is a valid
|
|
||||||
* FD number). */
|
|
||||||
dev_fd = -i->fd - 1;
|
|
||||||
write(waker_fd, &dev_fd, sizeof(dev_fd));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this the timeout fd? */
|
||||||
|
if (FD_ISSET(timeoutpipe[0], &fds))
|
||||||
|
handle_timeout(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,7 +1196,7 @@ static struct lguest_device_desc *new_dev_desc(u16 type)
|
||||||
/* Each device descriptor is followed by the description of its virtqueues. We
|
/* Each device descriptor is followed by the description of its virtqueues. We
|
||||||
* specify how many descriptors the virtqueue is to have. */
|
* specify how many descriptors the virtqueue is to have. */
|
||||||
static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
||||||
void (*handle_output)(int fd, struct virtqueue *me))
|
void (*handle_output)(int, struct virtqueue *, bool))
|
||||||
{
|
{
|
||||||
unsigned int pages;
|
unsigned int pages;
|
||||||
struct virtqueue **i, *vq = malloc(sizeof(*vq));
|
struct virtqueue **i, *vq = malloc(sizeof(*vq));
|
||||||
|
@ -1114,6 +1212,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
||||||
vq->last_avail_idx = 0;
|
vq->last_avail_idx = 0;
|
||||||
vq->dev = dev;
|
vq->dev = dev;
|
||||||
vq->inflight = 0;
|
vq->inflight = 0;
|
||||||
|
vq->blocked = false;
|
||||||
|
|
||||||
/* Initialize the configuration. */
|
/* Initialize the configuration. */
|
||||||
vq->config.num = num_descs;
|
vq->config.num = num_descs;
|
||||||
|
@ -1246,6 +1345,24 @@ static void setup_console(void)
|
||||||
}
|
}
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
|
static void timeout_alarm(int sig)
|
||||||
|
{
|
||||||
|
write(timeoutpipe[1], "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_timeout(void)
|
||||||
|
{
|
||||||
|
if (pipe(timeoutpipe) != 0)
|
||||||
|
err(1, "Creating timeout pipe");
|
||||||
|
|
||||||
|
if (fcntl(timeoutpipe[1], F_SETFL,
|
||||||
|
fcntl(timeoutpipe[1], F_GETFL) | O_NONBLOCK) != 0)
|
||||||
|
err(1, "Making timeout pipe nonblocking");
|
||||||
|
|
||||||
|
add_device_fd(timeoutpipe[0]);
|
||||||
|
signal(SIGALRM, timeout_alarm);
|
||||||
|
}
|
||||||
|
|
||||||
/*M:010 Inter-guest networking is an interesting area. Simplest is to have a
|
/*M:010 Inter-guest networking is an interesting area. Simplest is to have a
|
||||||
* --sharenet=<name> option which opens or creates a named pipe. This can be
|
* --sharenet=<name> option which opens or creates a named pipe. This can be
|
||||||
* used to send packets to another guest in a 1:1 manner.
|
* used to send packets to another guest in a 1:1 manner.
|
||||||
|
@ -1264,10 +1381,25 @@ static void setup_console(void)
|
||||||
|
|
||||||
static u32 str2ip(const char *ipaddr)
|
static u32 str2ip(const char *ipaddr)
|
||||||
{
|
{
|
||||||
unsigned int byte[4];
|
unsigned int b[4];
|
||||||
|
|
||||||
sscanf(ipaddr, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]);
|
if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
|
||||||
return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3];
|
errx(1, "Failed to parse IP address '%s'", ipaddr);
|
||||||
|
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void str2mac(const char *macaddr, unsigned char mac[6])
|
||||||
|
{
|
||||||
|
unsigned int m[6];
|
||||||
|
if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
&m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
|
||||||
|
errx(1, "Failed to parse mac address '%s'", macaddr);
|
||||||
|
mac[0] = m[0];
|
||||||
|
mac[1] = m[1];
|
||||||
|
mac[2] = m[2];
|
||||||
|
mac[3] = m[3];
|
||||||
|
mac[4] = m[4];
|
||||||
|
mac[5] = m[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is "adapted" from libbridge: it attaches the Host end of the
|
/* This code is "adapted" from libbridge: it attaches the Host end of the
|
||||||
|
@ -1288,6 +1420,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
|
||||||
errx(1, "interface %s does not exist!", if_name);
|
errx(1, "interface %s does not exist!", if_name);
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
|
strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
|
||||||
|
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
||||||
ifr.ifr_ifindex = ifidx;
|
ifr.ifr_ifindex = ifidx;
|
||||||
if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
|
if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
|
||||||
err(1, "can't add %s to bridge %s", if_name, br_name);
|
err(1, "can't add %s to bridge %s", if_name, br_name);
|
||||||
|
@ -1296,64 +1429,90 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
|
||||||
/* This sets up the Host end of the network device with an IP address, brings
|
/* This sets up the Host end of the network device with an IP address, brings
|
||||||
* it up so packets will flow, the copies the MAC address into the hwaddr
|
* it up so packets will flow, the copies the MAC address into the hwaddr
|
||||||
* pointer. */
|
* pointer. */
|
||||||
static void configure_device(int fd, const char *devname, u32 ipaddr,
|
static void configure_device(int fd, const char *tapif, u32 ipaddr)
|
||||||
unsigned char hwaddr[6])
|
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||||
|
|
||||||
/* Don't read these incantations. Just cut & paste them like I did! */
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strcpy(ifr.ifr_name, devname);
|
strcpy(ifr.ifr_name, tapif);
|
||||||
|
|
||||||
|
/* Don't read these incantations. Just cut & paste them like I did! */
|
||||||
sin->sin_family = AF_INET;
|
sin->sin_family = AF_INET;
|
||||||
sin->sin_addr.s_addr = htonl(ipaddr);
|
sin->sin_addr.s_addr = htonl(ipaddr);
|
||||||
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
|
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
|
||||||
err(1, "Setting %s interface address", devname);
|
err(1, "Setting %s interface address", tapif);
|
||||||
ifr.ifr_flags = IFF_UP;
|
ifr.ifr_flags = IFF_UP;
|
||||||
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
|
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
|
||||||
err(1, "Bringing interface %s up", devname);
|
err(1, "Bringing interface %s up", tapif);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_mac(int fd, const char *tapif, unsigned char hwaddr[6])
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strcpy(ifr.ifr_name, tapif);
|
||||||
|
|
||||||
/* SIOC stands for Socket I/O Control. G means Get (vs S for Set
|
/* SIOC stands for Socket I/O Control. G means Get (vs S for Set
|
||||||
* above). IF means Interface, and HWADDR is hardware address.
|
* above). IF means Interface, and HWADDR is hardware address.
|
||||||
* Simple! */
|
* Simple! */
|
||||||
if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
|
if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
|
||||||
err(1, "getting hw address for %s", devname);
|
err(1, "getting hw address for %s", tapif);
|
||||||
memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
|
memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*L:195 Our network is a Host<->Guest network. This can either use bridging or
|
static int get_tun_device(char tapif[IFNAMSIZ])
|
||||||
* routing, but the principle is the same: it uses the "tun" device to inject
|
|
||||||
* packets into the Host as if they came in from a normal network card. We
|
|
||||||
* just shunt packets between the Guest and the tun device. */
|
|
||||||
static void setup_tun_net(const char *arg)
|
|
||||||
{
|
{
|
||||||
struct device *dev;
|
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int netfd, ipfd;
|
int netfd;
|
||||||
u32 ip;
|
|
||||||
const char *br_name = NULL;
|
/* Start with this zeroed. Messy but sure. */
|
||||||
struct virtio_net_config conf;
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
/* We open the /dev/net/tun device and tell it we want a tap device. A
|
/* We open the /dev/net/tun device and tell it we want a tap device. A
|
||||||
* tap device is like a tun device, only somehow different. To tell
|
* tap device is like a tun device, only somehow different. To tell
|
||||||
* the truth, I completely blundered my way through this code, but it
|
* the truth, I completely blundered my way through this code, but it
|
||||||
* works now! */
|
* works now! */
|
||||||
netfd = open_or_die("/dev/net/tun", O_RDWR);
|
netfd = open_or_die("/dev/net/tun", O_RDWR);
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
|
||||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
|
||||||
strcpy(ifr.ifr_name, "tap%d");
|
strcpy(ifr.ifr_name, "tap%d");
|
||||||
if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
|
if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
|
||||||
err(1, "configuring /dev/net/tun");
|
err(1, "configuring /dev/net/tun");
|
||||||
|
|
||||||
|
if (ioctl(netfd, TUNSETOFFLOAD,
|
||||||
|
TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
|
||||||
|
err(1, "Could not set features for tun device");
|
||||||
|
|
||||||
/* We don't need checksums calculated for packets coming in this
|
/* We don't need checksums calculated for packets coming in this
|
||||||
* device: trust us! */
|
* device: trust us! */
|
||||||
ioctl(netfd, TUNSETNOCSUM, 1);
|
ioctl(netfd, TUNSETNOCSUM, 1);
|
||||||
|
|
||||||
|
memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
|
||||||
|
return netfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*L:195 Our network is a Host<->Guest network. This can either use bridging or
|
||||||
|
* routing, but the principle is the same: it uses the "tun" device to inject
|
||||||
|
* packets into the Host as if they came in from a normal network card. We
|
||||||
|
* just shunt packets between the Guest and the tun device. */
|
||||||
|
static void setup_tun_net(char *arg)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
int netfd, ipfd;
|
||||||
|
u32 ip = INADDR_ANY;
|
||||||
|
bool bridging = false;
|
||||||
|
char tapif[IFNAMSIZ], *p;
|
||||||
|
struct virtio_net_config conf;
|
||||||
|
|
||||||
|
netfd = get_tun_device(tapif);
|
||||||
|
|
||||||
/* First we create a new network device. */
|
/* First we create a new network device. */
|
||||||
dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
|
dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
|
||||||
|
|
||||||
/* Network devices need a receive and a send queue, just like
|
/* Network devices need a receive and a send queue, just like
|
||||||
* console. */
|
* console. */
|
||||||
add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
|
add_virtqueue(dev, VIRTQUEUE_NUM, net_enable_fd);
|
||||||
add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
|
add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
|
||||||
|
|
||||||
/* We need a socket to perform the magic network ioctls to bring up the
|
/* We need a socket to perform the magic network ioctls to bring up the
|
||||||
|
@ -1364,28 +1523,56 @@ static void setup_tun_net(const char *arg)
|
||||||
|
|
||||||
/* If the command line was --tunnet=bridge:<name> do bridging. */
|
/* If the command line was --tunnet=bridge:<name> do bridging. */
|
||||||
if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
|
if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
|
||||||
ip = INADDR_ANY;
|
arg += strlen(BRIDGE_PFX);
|
||||||
br_name = arg + strlen(BRIDGE_PFX);
|
bridging = true;
|
||||||
add_to_bridge(ipfd, ifr.ifr_name, br_name);
|
}
|
||||||
} else /* It is an IP address to set up the device with */
|
|
||||||
|
/* A mac address may follow the bridge name or IP address */
|
||||||
|
p = strchr(arg, ':');
|
||||||
|
if (p) {
|
||||||
|
str2mac(p+1, conf.mac);
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
p = arg + strlen(arg);
|
||||||
|
/* None supplied; query the randomly assigned mac. */
|
||||||
|
get_mac(ipfd, tapif, conf.mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* arg is now either an IP address or a bridge name */
|
||||||
|
if (bridging)
|
||||||
|
add_to_bridge(ipfd, tapif, arg);
|
||||||
|
else
|
||||||
ip = str2ip(arg);
|
ip = str2ip(arg);
|
||||||
|
|
||||||
/* Set up the tun device, and get the mac address for the interface. */
|
/* Set up the tun device. */
|
||||||
configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
|
configure_device(ipfd, tapif, ip);
|
||||||
|
|
||||||
/* Tell Guest what MAC address to use. */
|
/* Tell Guest what MAC address to use. */
|
||||||
add_feature(dev, VIRTIO_NET_F_MAC);
|
add_feature(dev, VIRTIO_NET_F_MAC);
|
||||||
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
|
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||||
|
/* Expect Guest to handle everything except UFO */
|
||||||
|
add_feature(dev, VIRTIO_NET_F_CSUM);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_CSUM);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_MAC);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_TSO4);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_TSO6);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_ECN);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_TSO4);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_TSO6);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_ECN);
|
||||||
set_config(dev, sizeof(conf), &conf);
|
set_config(dev, sizeof(conf), &conf);
|
||||||
|
|
||||||
/* We don't need the socket any more; setup is done. */
|
/* We don't need the socket any more; setup is done. */
|
||||||
close(ipfd);
|
close(ipfd);
|
||||||
|
|
||||||
verbose("device %u: tun net %u.%u.%u.%u\n",
|
devices.device_num++;
|
||||||
devices.device_num++,
|
|
||||||
(u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip);
|
if (bridging)
|
||||||
if (br_name)
|
verbose("device %u: tun %s attached to bridge: %s\n",
|
||||||
verbose("attached to bridge: %s\n", br_name);
|
devices.device_num, tapif, arg);
|
||||||
|
else
|
||||||
|
verbose("device %u: tun %s: %s\n",
|
||||||
|
devices.device_num, tapif, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Our block (disk) device should be really simple: the Guest asks for a block
|
/* Our block (disk) device should be really simple: the Guest asks for a block
|
||||||
|
@ -1550,7 +1737,7 @@ static bool handle_io_finish(int fd, struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the Guest submits some I/O, we just need to wake the I/O thread. */
|
/* When the Guest submits some I/O, we just need to wake the I/O thread. */
|
||||||
static void handle_virtblk_output(int fd, struct virtqueue *vq)
|
static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
struct vblk_info *vblk = vq->dev->priv;
|
struct vblk_info *vblk = vq->dev->priv;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
|
@ -1621,6 +1808,64 @@ static void setup_block_file(const char *filename)
|
||||||
verbose("device %u: virtblock %llu sectors\n",
|
verbose("device %u: virtblock %llu sectors\n",
|
||||||
devices.device_num, le64_to_cpu(conf.capacity));
|
devices.device_num, le64_to_cpu(conf.capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Our random number generator device reads from /dev/random into the Guest's
|
||||||
|
* input buffers. The usual case is that the Guest doesn't want random numbers
|
||||||
|
* and so has no buffers although /dev/random is still readable, whereas
|
||||||
|
* console is the reverse.
|
||||||
|
*
|
||||||
|
* The same logic applies, however. */
|
||||||
|
static bool handle_rng_input(int fd, struct device *dev)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned int head, in_num, out_num, totlen = 0;
|
||||||
|
struct iovec iov[dev->vq->vring.num];
|
||||||
|
|
||||||
|
/* First we need a buffer from the Guests's virtqueue. */
|
||||||
|
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
||||||
|
|
||||||
|
/* If they're not ready for input, stop listening to this file
|
||||||
|
* descriptor. We'll start again once they add an input buffer. */
|
||||||
|
if (head == dev->vq->vring.num)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (out_num)
|
||||||
|
errx(1, "Output buffers in rng?");
|
||||||
|
|
||||||
|
/* This is why we convert to iovecs: the readv() call uses them, and so
|
||||||
|
* it reads straight into the Guest's buffer. We loop to make sure we
|
||||||
|
* fill it. */
|
||||||
|
while (!iov_empty(iov, in_num)) {
|
||||||
|
len = readv(dev->fd, iov, in_num);
|
||||||
|
if (len <= 0)
|
||||||
|
err(1, "Read from /dev/random gave %i", len);
|
||||||
|
iov_consume(iov, in_num, len);
|
||||||
|
totlen += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the Guest about the new input. */
|
||||||
|
add_used_and_trigger(fd, dev->vq, head, totlen);
|
||||||
|
|
||||||
|
/* Everything went OK! */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And this creates a "hardware" random number device for the Guest. */
|
||||||
|
static void setup_rng(void)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open_or_die("/dev/random", O_RDONLY);
|
||||||
|
|
||||||
|
/* The device responds to return from I/O thread. */
|
||||||
|
dev = new_device("rng", VIRTIO_ID_RNG, fd, handle_rng_input);
|
||||||
|
|
||||||
|
/* The device has one virtqueue, where the Guest places inbufs. */
|
||||||
|
add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
|
||||||
|
|
||||||
|
verbose("device %u: rng\n", devices.device_num++);
|
||||||
|
}
|
||||||
/* That's the end of device setup. */
|
/* That's the end of device setup. */
|
||||||
|
|
||||||
/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
|
/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
|
||||||
|
@ -1628,11 +1873,12 @@ static void __attribute__((noreturn)) restart_guest(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Closing pipes causes the Waker thread and io_threads to die, and
|
/* Since we don't track all open fds, we simply close everything beyond
|
||||||
* closing /dev/lguest cleans up the Guest. Since we don't track all
|
* stderr. */
|
||||||
* open fds, we simply close everything beyond stderr. */
|
|
||||||
for (i = 3; i < FD_SETSIZE; i++)
|
for (i = 3; i < FD_SETSIZE; i++)
|
||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
|
/* The exec automatically gets rid of the I/O and Waker threads. */
|
||||||
execv(main_args[0], main_args);
|
execv(main_args[0], main_args);
|
||||||
err(1, "Could not exec %s", main_args[0]);
|
err(1, "Could not exec %s", main_args[0]);
|
||||||
}
|
}
|
||||||
|
@ -1663,7 +1909,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
|
||||||
/* ERESTART means that we need to reboot the guest */
|
/* ERESTART means that we need to reboot the guest */
|
||||||
} else if (errno == ERESTART) {
|
} else if (errno == ERESTART) {
|
||||||
restart_guest();
|
restart_guest();
|
||||||
/* EAGAIN means the Waker wanted us to look at some input.
|
/* EAGAIN means a signal (timeout).
|
||||||
* Anything else means a bug or incompatible change. */
|
* Anything else means a bug or incompatible change. */
|
||||||
} else if (errno != EAGAIN)
|
} else if (errno != EAGAIN)
|
||||||
err(1, "Running guest failed");
|
err(1, "Running guest failed");
|
||||||
|
@ -1691,13 +1937,14 @@ static struct option opts[] = {
|
||||||
{ "verbose", 0, NULL, 'v' },
|
{ "verbose", 0, NULL, 'v' },
|
||||||
{ "tunnet", 1, NULL, 't' },
|
{ "tunnet", 1, NULL, 't' },
|
||||||
{ "block", 1, NULL, 'b' },
|
{ "block", 1, NULL, 'b' },
|
||||||
|
{ "rng", 0, NULL, 'r' },
|
||||||
{ "initrd", 1, NULL, 'i' },
|
{ "initrd", 1, NULL, 'i' },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
errx(1, "Usage: lguest [--verbose] "
|
errx(1, "Usage: lguest [--verbose] "
|
||||||
"[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
|
"[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
|
||||||
"|--block=<filename>|--initrd=<filename>]...\n"
|
"|--block=<filename>|--initrd=<filename>]...\n"
|
||||||
"<mem-in-mb> vmlinux [args...]");
|
"<mem-in-mb> vmlinux [args...]");
|
||||||
}
|
}
|
||||||
|
@ -1765,6 +2012,9 @@ int main(int argc, char *argv[])
|
||||||
case 'b':
|
case 'b':
|
||||||
setup_block_file(optarg);
|
setup_block_file(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
setup_rng();
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
initrd_name = optarg;
|
initrd_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -1783,6 +2033,9 @@ int main(int argc, char *argv[])
|
||||||
/* We always have a console device */
|
/* We always have a console device */
|
||||||
setup_console();
|
setup_console();
|
||||||
|
|
||||||
|
/* We can timeout waiting for Guest network transmit. */
|
||||||
|
setup_timeout();
|
||||||
|
|
||||||
/* Now we load the kernel */
|
/* Now we load the kernel */
|
||||||
start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
|
start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
|
||||||
|
|
||||||
|
@ -1826,10 +2079,10 @@ int main(int argc, char *argv[])
|
||||||
* /dev/lguest file descriptor. */
|
* /dev/lguest file descriptor. */
|
||||||
lguest_fd = tell_kernel(pgdir, start);
|
lguest_fd = tell_kernel(pgdir, start);
|
||||||
|
|
||||||
/* We fork off a child process, which wakes the Launcher whenever one
|
/* We clone off a thread, which wakes the Launcher whenever one of the
|
||||||
* of the input file descriptors needs attention. We call this the
|
* input file descriptors needs attention. We call this the Waker, and
|
||||||
* Waker, and we'll cover it in a moment. */
|
* we'll cover it in a moment. */
|
||||||
waker_fd = setup_waker(lguest_fd);
|
setup_waker(lguest_fd);
|
||||||
|
|
||||||
/* Finally, run the Guest. This doesn't return. */
|
/* Finally, run the Guest. This doesn't return. */
|
||||||
run_guest(lguest_fd);
|
run_guest(lguest_fd);
|
||||||
|
|
|
@ -1024,6 +1024,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
intel-mac-v3 Intel Mac Type 3
|
intel-mac-v3 Intel Mac Type 3
|
||||||
intel-mac-v4 Intel Mac Type 4
|
intel-mac-v4 Intel Mac Type 4
|
||||||
intel-mac-v5 Intel Mac Type 5
|
intel-mac-v5 Intel Mac Type 5
|
||||||
|
intel-mac-auto Intel Mac (detect type according to subsystem id)
|
||||||
macmini Intel Mac Mini (equivalent with type 3)
|
macmini Intel Mac Mini (equivalent with type 3)
|
||||||
macbook Intel Mac Book (eq. type 5)
|
macbook Intel Mac Book (eq. type 5)
|
||||||
macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
|
macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
|
||||||
|
|
|
@ -73,10 +73,10 @@ recompiled, or use "make C=2" to run sparse on the files whether they need to
|
||||||
be recompiled or not. The latter is a fast way to check the whole tree if you
|
be recompiled or not. The latter is a fast way to check the whole tree if you
|
||||||
have already built it.
|
have already built it.
|
||||||
|
|
||||||
The optional make variable CHECKFLAGS can be used to pass arguments to sparse.
|
The optional make variable CF can be used to pass arguments to sparse. The
|
||||||
The build system passes -Wbitwise to sparse automatically. To perform
|
build system passes -Wbitwise to sparse automatically. To perform endianness
|
||||||
endianness checks, you may define __CHECK_ENDIAN__:
|
checks, you may define __CHECK_ENDIAN__:
|
||||||
|
|
||||||
make C=2 CHECKFLAGS="-D__CHECK_ENDIAN__"
|
make C=2 CF="-D__CHECK_ENDIAN__"
|
||||||
|
|
||||||
These checks are disabled by default as they generate a host of warnings.
|
These checks are disabled by default as they generate a host of warnings.
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
|
1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
|
||||||
2 -> Hauppauge HVR850 (au0828) [2040:7240]
|
2 -> Hauppauge HVR850 (au0828) [2040:7240]
|
||||||
3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620]
|
3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620]
|
||||||
|
4 -> Hauppauge HVR950Q rev xxF8 (au0828) [2040:7201,2040:7211,2040:7281]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
|
0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
|
||||||
1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2750,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
|
1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
|
||||||
2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
|
2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
|
||||||
3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
|
3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
|
||||||
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201]
|
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201]
|
||||||
5 -> MSI VOX USB 2.0 (em2820/em2840)
|
5 -> MSI VOX USB 2.0 (em2820/em2840)
|
||||||
6 -> Terratec Cinergy 200 USB (em2800)
|
6 -> Terratec Cinergy 200 USB (em2800)
|
||||||
7 -> Leadtek Winfast USB II (em2800)
|
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
|
||||||
8 -> Kworld USB2800 (em2800)
|
8 -> Kworld USB2800 (em2800)
|
||||||
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
|
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
|
||||||
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
|
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
|
||||||
|
@ -14,7 +14,46 @@
|
||||||
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
|
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
|
||||||
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
|
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
|
||||||
15 -> V-Gear PocketTV (em2800)
|
15 -> V-Gear PocketTV (em2800)
|
||||||
16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f]
|
16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b,2040:651f]
|
||||||
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
|
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
|
||||||
18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
|
18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
|
||||||
19 -> PointNix Intra-Oral Camera (em2860)
|
19 -> PointNix Intra-Oral Camera (em2860)
|
||||||
|
20 -> AMD ATI TV Wonder HD 600 (em2880) [0438:b002]
|
||||||
|
21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800) [eb1a:2801]
|
||||||
|
22 -> Unknown EM2750/EM2751 webcam grabber (em2750) [eb1a:2750,eb1a:2751]
|
||||||
|
23 -> Huaqi DLCW-130 (em2750)
|
||||||
|
24 -> D-Link DUB-T210 TV Tuner (em2820/em2840) [2001:f112]
|
||||||
|
25 -> Gadmei UTV310 (em2820/em2840)
|
||||||
|
26 -> Hercules Smart TV USB 2.0 (em2820/em2840)
|
||||||
|
27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840)
|
||||||
|
28 -> Leadtek Winfast USB II Deluxe (em2820/em2840)
|
||||||
|
29 -> Pinnacle Dazzle DVC 100 (em2820/em2840)
|
||||||
|
30 -> Videology 20K14XUSB USB2.0 (em2820/em2840)
|
||||||
|
31 -> Usbgear VD204v9 (em2821)
|
||||||
|
32 -> Supercomp USB 2.0 TV (em2821)
|
||||||
|
33 -> SIIG AVTuner-PVR/Prolink PlayTV USB 2.0 (em2821)
|
||||||
|
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
|
||||||
|
35 -> Typhoon DVD Maker (em2860)
|
||||||
|
36 -> NetGMBH Cam (em2860)
|
||||||
|
37 -> Gadmei UTV330 (em2860)
|
||||||
|
38 -> Yakumo MovieMixer (em2861)
|
||||||
|
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
|
||||||
|
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
|
||||||
|
41 -> Kworld 350 U DVB-T (em2870) [eb1a:e350]
|
||||||
|
42 -> Kworld 355 U DVB-T (em2870) [eb1a:e355,eb1a:e357]
|
||||||
|
43 -> Terratec Cinergy T XS (em2870) [0ccd:0043]
|
||||||
|
44 -> Terratec Cinergy T XS (MT2060) (em2870)
|
||||||
|
45 -> Pinnacle PCTV DVB-T (em2870)
|
||||||
|
46 -> Compro, VideoMate U3 (em2870) [185b:2870]
|
||||||
|
47 -> KWorld DVB-T 305U (em2880) [eb1a:e305]
|
||||||
|
48 -> KWorld DVB-T 310U (em2880)
|
||||||
|
49 -> MSI DigiVox A/D (em2880) [eb1a:e310]
|
||||||
|
50 -> MSI DigiVox A/D II (em2880) [eb1a:e320]
|
||||||
|
51 -> Terratec Hybrid XS Secam (em2880) [0ccd:004c]
|
||||||
|
52 -> DNT DA2 Hybrid (em2881)
|
||||||
|
53 -> Pinnacle Hybrid Pro (em2881)
|
||||||
|
54 -> Kworld VS-DVB-T 323UR (em2882) [eb1a:e323]
|
||||||
|
55 -> Terratec Hybrid XS (em2882) (em2882) [0ccd:005e]
|
||||||
|
56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226]
|
||||||
|
57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316]
|
||||||
|
58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
List of the webcams know by gspca.
|
List of the webcams known by gspca.
|
||||||
|
|
||||||
The modules are:
|
The modules are:
|
||||||
gspca_main main driver
|
gspca_main main driver
|
||||||
|
|
3
Kbuild
3
Kbuild
|
@ -43,7 +43,7 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild
|
||||||
# 2) Generate asm-offsets.h
|
# 2) Generate asm-offsets.h
|
||||||
#
|
#
|
||||||
|
|
||||||
offsets-file := include/asm-$(SRCARCH)/asm-offsets.h
|
offsets-file := include/asm/asm-offsets.h
|
||||||
|
|
||||||
always += $(offsets-file)
|
always += $(offsets-file)
|
||||||
targets += $(offsets-file)
|
targets += $(offsets-file)
|
||||||
|
@ -81,7 +81,6 @@ arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \
|
||||||
$(call if_changed_dep,cc_s_c)
|
$(call if_changed_dep,cc_s_c)
|
||||||
|
|
||||||
$(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
|
$(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
|
||||||
$(Q)mkdir -p $(dir $@)
|
|
||||||
$(call cmd,offsets)
|
$(call cmd,offsets)
|
||||||
|
|
||||||
#####
|
#####
|
||||||
|
|
|
@ -3796,6 +3796,12 @@ P: Ben Nizette
|
||||||
M: bn@niasdigital.com
|
M: bn@niasdigital.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
SOC-CAMERA V4L2 SUBSYSTEM
|
||||||
|
P: Guennadi Liakhovetski
|
||||||
|
M: g.liakhovetski@gmx.de
|
||||||
|
L: video4linux-list@redhat.com
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
SOFTWARE RAID (Multiple Disks) SUPPORT
|
SOFTWARE RAID (Multiple Disks) SUPPORT
|
||||||
P: Ingo Molnar
|
P: Ingo Molnar
|
||||||
M: mingo@redhat.com
|
M: mingo@redhat.com
|
||||||
|
|
123
Makefile
123
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 26
|
SUBLEVEL = 27
|
||||||
EXTRAVERSION =
|
EXTRAVERSION = -rc1
|
||||||
NAME = Rotary Wombat
|
NAME = Rotary Wombat
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@ -205,6 +205,13 @@ ifeq ($(ARCH),x86_64)
|
||||||
SRCARCH := x86
|
SRCARCH := x86
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Where to locate arch specific headers
|
||||||
|
ifeq ($(ARCH),sparc64)
|
||||||
|
hdr-arch := sparc
|
||||||
|
else
|
||||||
|
hdr-arch := $(SRCARCH)
|
||||||
|
endif
|
||||||
|
|
||||||
KCONFIG_CONFIG ?= .config
|
KCONFIG_CONFIG ?= .config
|
||||||
|
|
||||||
# SHELL used by kbuild
|
# SHELL used by kbuild
|
||||||
|
@ -326,7 +333,8 @@ AFLAGS_KERNEL =
|
||||||
# Needed to be compatible with the O= option
|
# Needed to be compatible with the O= option
|
||||||
LINUXINCLUDE := -Iinclude \
|
LINUXINCLUDE := -Iinclude \
|
||||||
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
|
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
|
||||||
-include include/linux/autoconf.h
|
-I$(srctree)/arch/$(hdr-arch)/include \
|
||||||
|
-include include/linux/autoconf.h
|
||||||
|
|
||||||
KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||||
|
|
||||||
|
@ -922,7 +930,9 @@ ifneq ($(KBUILD_SRC),)
|
||||||
/bin/false; \
|
/bin/false; \
|
||||||
fi;
|
fi;
|
||||||
$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
|
$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
|
||||||
$(Q)ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm
|
$(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/system.h ]; then \
|
||||||
|
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
|
||||||
|
fi
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# prepare2 creates a makefile if using a separate output directory
|
# prepare2 creates a makefile if using a separate output directory
|
||||||
|
@ -948,22 +958,34 @@ export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
||||||
|
|
||||||
# The asm symlink changes when $(ARCH) changes.
|
# The asm symlink changes when $(ARCH) changes.
|
||||||
# Detect this and ask user to run make mrproper
|
# Detect this and ask user to run make mrproper
|
||||||
|
define check-symlink
|
||||||
include/asm: FORCE
|
set -e; \
|
||||||
$(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`; \
|
if [ -L include/asm ]; then \
|
||||||
if [ -L include/asm ]; then \
|
asmlink=`readlink include/asm | cut -d '-' -f 2`; \
|
||||||
if [ "$$asmlink" != "$(SRCARCH)" ]; then \
|
if [ "$$asmlink" != "$(SRCARCH)" ]; then \
|
||||||
echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
|
echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
|
||||||
echo " set ARCH or save .config and run 'make mrproper' to fix it"; \
|
echo " set ARCH or save .config and run 'make mrproper' to fix it"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
else \
|
|
||||||
echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \
|
|
||||||
if [ ! -d include ]; then \
|
|
||||||
mkdir -p include; \
|
|
||||||
fi; \
|
|
||||||
ln -fsn asm-$(SRCARCH) $@; \
|
|
||||||
fi
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
# We create the target directory of the symlink if it does
|
||||||
|
# not exist so the test in chack-symlink works and we have a
|
||||||
|
# directory for generated filesas used by some architectures.
|
||||||
|
define create-symlink
|
||||||
|
if [ ! -L include/asm ]; then \
|
||||||
|
echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \
|
||||||
|
if [ ! -d include/asm-$(SRCARCH) ]; then \
|
||||||
|
mkdir -p include/asm-$(SRCARCH); \
|
||||||
|
fi; \
|
||||||
|
ln -fsn asm-$(SRCARCH) $@; \
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
include/asm: FORCE
|
||||||
|
$(Q)$(check-symlink)
|
||||||
|
$(Q)$(create-symlink)
|
||||||
|
|
||||||
# Generate some files
|
# Generate some files
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
@ -1010,36 +1032,43 @@ firmware_install: FORCE
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Kernel headers
|
# Kernel headers
|
||||||
INSTALL_HDR_PATH=$(objtree)/usr
|
|
||||||
export INSTALL_HDR_PATH
|
|
||||||
|
|
||||||
HDRFILTER=generic i386 x86_64
|
#Default location for installed headers
|
||||||
HDRARCHES=$(filter-out $(HDRFILTER),$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
|
export INSTALL_HDR_PATH = $(objtree)/usr
|
||||||
|
|
||||||
|
hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
|
||||||
|
# Find out where the Kbuild file is located to support
|
||||||
|
# arch/$(ARCH)/include/asm
|
||||||
|
hdr-dir = $(strip \
|
||||||
|
$(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
|
||||||
|
arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
|
||||||
|
|
||||||
|
# If we do an all arch process set dst to asm-$(hdr-arch)
|
||||||
|
hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
|
||||||
|
|
||||||
|
PHONY += __headers
|
||||||
|
__headers: include/linux/version.h scripts_basic FORCE
|
||||||
|
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
|
||||||
|
|
||||||
PHONY += headers_install_all
|
PHONY += headers_install_all
|
||||||
headers_install_all: include/linux/version.h scripts_basic FORCE
|
headers_install_all:
|
||||||
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
|
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
|
||||||
$(Q)for arch in $(HDRARCHES); do \
|
|
||||||
$(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
|
|
||||||
done
|
|
||||||
|
|
||||||
PHONY += headers_install
|
PHONY += headers_install
|
||||||
headers_install: include/linux/version.h scripts_basic FORCE
|
headers_install: __headers
|
||||||
@if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
|
$(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
|
||||||
echo '*** Error: Headers not exportable for this architecture ($(SRCARCH))'; \
|
$(error Headers not exportable for the $(SRCARCH) architecture))
|
||||||
exit 1 ; fi
|
$(Q)$(MAKE) $(hdr-inst)=include
|
||||||
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
|
$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
|
||||||
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include
|
|
||||||
|
|
||||||
PHONY += headers_check_all
|
PHONY += headers_check_all
|
||||||
headers_check_all: headers_install_all
|
headers_check_all: headers_install_all
|
||||||
$(Q)for arch in $(HDRARCHES); do \
|
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
|
||||||
$(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
|
|
||||||
done
|
|
||||||
|
|
||||||
PHONY += headers_check
|
PHONY += headers_check
|
||||||
headers_check: headers_install
|
headers_check: headers_install
|
||||||
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
|
$(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
|
||||||
|
$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Modules
|
# Modules
|
||||||
|
@ -1131,7 +1160,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
|
||||||
include/linux/autoconf.h include/linux/version.h \
|
include/linux/autoconf.h include/linux/version.h \
|
||||||
include/linux/utsrelease.h \
|
include/linux/utsrelease.h \
|
||||||
include/linux/bounds.h include/asm*/asm-offsets.h \
|
include/linux/bounds.h include/asm*/asm-offsets.h \
|
||||||
Module.symvers tags TAGS cscope*
|
Module.symvers Module.markers tags TAGS cscope*
|
||||||
|
|
||||||
# clean - Delete most, but leave enough to build external modules
|
# clean - Delete most, but leave enough to build external modules
|
||||||
#
|
#
|
||||||
|
@ -1150,7 +1179,7 @@ clean: archclean $(clean-dirs)
|
||||||
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
||||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
||||||
-o -name '*.symtypes' -o -name 'modules.order' \
|
-o -name '*.symtypes' -o -name 'modules.order' \
|
||||||
-o -name 'Module.markers' \) \
|
-o -name 'Module.markers' -o -name '.tmp_*.o.*' \) \
|
||||||
-type f -print | xargs rm -f
|
-type f -print | xargs rm -f
|
||||||
|
|
||||||
# mrproper - Delete all generated files, including .config
|
# mrproper - Delete all generated files, including .config
|
||||||
|
@ -1224,21 +1253,17 @@ help:
|
||||||
@echo ' cscope - Generate cscope index'
|
@echo ' cscope - Generate cscope index'
|
||||||
@echo ' kernelrelease - Output the release version string'
|
@echo ' kernelrelease - Output the release version string'
|
||||||
@echo ' kernelversion - Output the version stored in Makefile'
|
@echo ' kernelversion - Output the version stored in Makefile'
|
||||||
@if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
|
@echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
|
||||||
echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
|
|
||||||
echo ' (default: $(INSTALL_HDR_PATH))'; \
|
echo ' (default: $(INSTALL_HDR_PATH))'; \
|
||||||
fi
|
echo ''
|
||||||
@echo ''
|
|
||||||
@echo 'Static analysers'
|
@echo 'Static analysers'
|
||||||
@echo ' checkstack - Generate a list of stack hogs'
|
@echo ' checkstack - Generate a list of stack hogs'
|
||||||
@echo ' namespacecheck - Name space analysis on compiled kernel'
|
@echo ' namespacecheck - Name space analysis on compiled kernel'
|
||||||
@echo ' versioncheck - Sanity check on version.h usage'
|
@echo ' versioncheck - Sanity check on version.h usage'
|
||||||
@echo ' includecheck - Check for duplicate included header files'
|
@echo ' includecheck - Check for duplicate included header files'
|
||||||
@echo ' export_report - List the usages of all exported symbols'
|
@echo ' export_report - List the usages of all exported symbols'
|
||||||
@if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
|
@echo ' headers_check - Sanity check on exported headers'; \
|
||||||
echo ' headers_check - Sanity check on exported headers'; \
|
echo ''
|
||||||
fi
|
|
||||||
@echo ''
|
|
||||||
@echo 'Kernel packaging:'
|
@echo 'Kernel packaging:'
|
||||||
@$(MAKE) $(build)=$(package-dir) help
|
@$(MAKE) $(build)=$(package-dir) help
|
||||||
@echo ''
|
@echo ''
|
||||||
|
@ -1411,7 +1436,11 @@ define find-sources
|
||||||
\( -name config -o -name 'asm-*' \) -prune \
|
\( -name config -o -name 'asm-*' \) -prune \
|
||||||
-o -name $1 -print; \
|
-o -name $1 -print; \
|
||||||
for arch in $(ALLINCLUDE_ARCHS) ; do \
|
for arch in $(ALLINCLUDE_ARCHS) ; do \
|
||||||
find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
|
test -e $(__srctree)include/asm-$${arch} && \
|
||||||
|
find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
|
||||||
|
-name $1 -print; \
|
||||||
|
test -e $(__srctree)arch/$${arch}/include/asm && \
|
||||||
|
find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \
|
||||||
-name $1 -print; \
|
-name $1 -print; \
|
||||||
done ; \
|
done ; \
|
||||||
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
||||||
|
|
|
@ -17,6 +17,7 @@ config ARM
|
||||||
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
||||||
select HAVE_FTRACE if (!XIP_KERNEL)
|
select HAVE_FTRACE if (!XIP_KERNEL)
|
||||||
select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
|
select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
|
||||||
|
select HAVE_GENERIC_DMA_COHERENT
|
||||||
help
|
help
|
||||||
The ARM series is a line of low-power-consumption RISC chip designs
|
The ARM series is a line of low-power-consumption RISC chip designs
|
||||||
licensed by ARM Ltd and targeted at embedded applications and
|
licensed by ARM Ltd and targeted at embedded applications and
|
||||||
|
@ -234,6 +235,7 @@ config ARCH_VERSATILE
|
||||||
config ARCH_AT91
|
config ARCH_AT91
|
||||||
bool "Atmel AT91"
|
bool "Atmel AT91"
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
|
select HAVE_CLK
|
||||||
help
|
help
|
||||||
This enables support for systems based on the Atmel AT91RM9200,
|
This enables support for systems based on the Atmel AT91RM9200,
|
||||||
AT91SAM9 and AT91CAP9 processors.
|
AT91SAM9 and AT91CAP9 processors.
|
||||||
|
@ -267,7 +269,6 @@ config ARCH_EP93XX
|
||||||
select ARM_VIC
|
select ARM_VIC
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
select HAVE_CLK
|
select HAVE_CLK
|
||||||
select HAVE_CLK
|
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
This enables support for the Cirrus EP93xx series of CPUs.
|
This enables support for the Cirrus EP93xx series of CPUs.
|
||||||
|
@ -314,7 +315,7 @@ config ARCH_IOP32X
|
||||||
select PLAT_IOP
|
select PLAT_IOP
|
||||||
select PCI
|
select PCI
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
select HAVE_GPIO_LIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
Support for Intel's 80219 and IOP32X (XScale) family of
|
Support for Intel's 80219 and IOP32X (XScale) family of
|
||||||
processors.
|
processors.
|
||||||
|
@ -325,7 +326,7 @@ config ARCH_IOP33X
|
||||||
select PLAT_IOP
|
select PLAT_IOP
|
||||||
select PCI
|
select PCI
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
select HAVE_GPIO_LIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
Support for Intel's IOP33X (XScale) family of processors.
|
Support for Intel's IOP33X (XScale) family of processors.
|
||||||
|
|
||||||
|
@ -418,7 +419,7 @@ config ARCH_MXC
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select ARCH_MTD_XIP
|
select ARCH_MTD_XIP
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
select HAVE_GPIO_LIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
Support for Freescale MXC/iMX-based family of processors
|
Support for Freescale MXC/iMX-based family of processors
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
|
||||||
tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi
|
tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi
|
||||||
tune-$(CONFIG_CPU_ARM9TDMI) :=-mtune=arm9tdmi
|
tune-$(CONFIG_CPU_ARM9TDMI) :=-mtune=arm9tdmi
|
||||||
tune-$(CONFIG_CPU_ARM940T) :=-mtune=arm9tdmi
|
tune-$(CONFIG_CPU_ARM940T) :=-mtune=arm9tdmi
|
||||||
tune-$(CONFIG_CPU_ARM946T) :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
|
tune-$(CONFIG_CPU_ARM946E) :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
|
||||||
tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
|
tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
|
||||||
tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
|
tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
|
||||||
tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi
|
tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi
|
||||||
|
|
|
@ -331,17 +331,17 @@ static int locomo_gpio_type(unsigned int irq, unsigned int type)
|
||||||
|
|
||||||
mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
|
mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
|
||||||
|
|
||||||
if (type == IRQT_PROBE) {
|
if (type == IRQ_TYPE_PROBE) {
|
||||||
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
|
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
|
||||||
return 0;
|
return 0;
|
||||||
type = __IRQT_RISEDGE | __IRQT_FALEDGE;
|
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type & __IRQT_RISEDGE)
|
if (type & IRQ_TYPE_EDGE_RISING)
|
||||||
GPIO_IRQ_rising_edge |= mask;
|
GPIO_IRQ_rising_edge |= mask;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_rising_edge &= ~mask;
|
GPIO_IRQ_rising_edge &= ~mask;
|
||||||
if (type & __IRQT_FALEDGE)
|
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||||
GPIO_IRQ_falling_edge |= mask;
|
GPIO_IRQ_falling_edge |= mask;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_falling_edge &= ~mask;
|
GPIO_IRQ_falling_edge &= ~mask;
|
||||||
|
@ -473,7 +473,7 @@ static void locomo_setup_irq(struct locomo *lchip)
|
||||||
/*
|
/*
|
||||||
* Install handler for IRQ_LOCOMO_HW.
|
* Install handler for IRQ_LOCOMO_HW.
|
||||||
*/
|
*/
|
||||||
set_irq_type(lchip->irq, IRQT_FALLING);
|
set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
|
||||||
set_irq_chip_data(lchip->irq, irqbase);
|
set_irq_chip_data(lchip->irq, irqbase);
|
||||||
set_irq_chained_handler(lchip->irq, locomo_handler);
|
set_irq_chained_handler(lchip->irq, locomo_handler);
|
||||||
|
|
||||||
|
|
|
@ -241,14 +241,14 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
|
||||||
void __iomem *mapbase = get_irq_chip_data(irq);
|
void __iomem *mapbase = get_irq_chip_data(irq);
|
||||||
unsigned long ip0;
|
unsigned long ip0;
|
||||||
|
|
||||||
if (flags == IRQT_PROBE)
|
if (flags == IRQ_TYPE_PROBE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
|
if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
|
ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
|
||||||
if (flags & __IRQT_RISEDGE)
|
if (flags & IRQ_TYPE_EDGE_RISING)
|
||||||
ip0 &= ~mask;
|
ip0 &= ~mask;
|
||||||
else
|
else
|
||||||
ip0 |= mask;
|
ip0 |= mask;
|
||||||
|
@ -338,14 +338,14 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
|
||||||
void __iomem *mapbase = get_irq_chip_data(irq);
|
void __iomem *mapbase = get_irq_chip_data(irq);
|
||||||
unsigned long ip1;
|
unsigned long ip1;
|
||||||
|
|
||||||
if (flags == IRQT_PROBE)
|
if (flags == IRQ_TYPE_PROBE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((!(flags & __IRQT_RISEDGE) ^ !(flags & __IRQT_FALEDGE)) == 0)
|
if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
|
ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
|
||||||
if (flags & __IRQT_RISEDGE)
|
if (flags & IRQ_TYPE_EDGE_RISING)
|
||||||
ip1 &= ~mask;
|
ip1 &= ~mask;
|
||||||
else
|
else
|
||||||
ip1 |= mask;
|
ip1 |= mask;
|
||||||
|
@ -427,7 +427,7 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
|
||||||
/*
|
/*
|
||||||
* Register SA1111 interrupt
|
* Register SA1111 interrupt
|
||||||
*/
|
*/
|
||||||
set_irq_type(sachip->irq, IRQT_RISING);
|
set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_data(sachip->irq, irqbase);
|
set_irq_data(sachip->irq, irqbase);
|
||||||
set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
|
set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -330,10 +330,10 @@ static void __init cap9adk_board_init(void)
|
||||||
/* Serial */
|
/* Serial */
|
||||||
at91_add_device_serial();
|
at91_add_device_serial();
|
||||||
/* USB Host */
|
/* USB Host */
|
||||||
set_irq_type(AT91CAP9_ID_UHP, IRQT_HIGH);
|
set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
|
||||||
at91_add_device_usbh(&cap9adk_usbh_data);
|
at91_add_device_usbh(&cap9adk_usbh_data);
|
||||||
/* USB HS */
|
/* USB HS */
|
||||||
set_irq_type(AT91CAP9_ID_UDPHS, IRQT_HIGH);
|
set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
|
||||||
at91_add_device_usba(&cap9adk_usba_udc_data);
|
at91_add_device_usba(&cap9adk_usba_udc_data);
|
||||||
/* SPI */
|
/* SPI */
|
||||||
at91_add_device_spi(cap9adk_spi_devices, ARRAY_SIZE(cap9adk_spi_devices));
|
at91_add_device_spi(cap9adk_spi_devices, ARRAY_SIZE(cap9adk_spi_devices));
|
||||||
|
@ -350,7 +350,7 @@ static void __init cap9adk_board_init(void)
|
||||||
/* I2C */
|
/* I2C */
|
||||||
at91_add_device_i2c(NULL, 0);
|
at91_add_device_i2c(NULL, 0);
|
||||||
/* LCD Controller */
|
/* LCD Controller */
|
||||||
set_irq_type(AT91CAP9_ID_LCDC, IRQT_HIGH);
|
set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
|
||||||
at91_add_device_lcdc(&cap9adk_lcdc_data);
|
at91_add_device_lcdc(&cap9adk_lcdc_data);
|
||||||
/* AC97 */
|
/* AC97 */
|
||||||
at91_add_device_ac97(&cap9adk_ac97_data);
|
at91_add_device_ac97(&cap9adk_ac97_data);
|
||||||
|
|
|
@ -56,19 +56,19 @@ static int at91_aic_set_type(unsigned irq, unsigned type)
|
||||||
unsigned int smr, srctype;
|
unsigned int smr, srctype;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
srctype = AT91_AIC_SRCTYPE_HIGH;
|
srctype = AT91_AIC_SRCTYPE_HIGH;
|
||||||
break;
|
break;
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
srctype = AT91_AIC_SRCTYPE_RISING;
|
srctype = AT91_AIC_SRCTYPE_RISING;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
|
if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
|
||||||
srctype = AT91_AIC_SRCTYPE_LOW;
|
srctype = AT91_AIC_SRCTYPE_LOW;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
|
if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
|
||||||
srctype = AT91_AIC_SRCTYPE_FALLING;
|
srctype = AT91_AIC_SRCTYPE_FALLING;
|
||||||
else
|
else
|
||||||
|
|
|
@ -226,7 +226,7 @@ static void ep93xx_gpio_irq_ack(unsigned int irq)
|
||||||
int port = line >> 3;
|
int port = line >> 3;
|
||||||
int port_mask = 1 << (line & 7);
|
int port_mask = 1 << (line & 7);
|
||||||
|
|
||||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
|
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
|
||||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||||
ep93xx_gpio_update_int_params(port);
|
ep93xx_gpio_update_int_params(port);
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
|
||||||
int port = line >> 3;
|
int port = line >> 3;
|
||||||
int port_mask = 1 << (line & 7);
|
int port_mask = 1 << (line & 7);
|
||||||
|
|
||||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE)
|
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
|
||||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||||
|
|
||||||
gpio_int_unmasked[port] &= ~port_mask;
|
gpio_int_unmasked[port] &= ~port_mask;
|
||||||
|
@ -283,27 +283,27 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||||
gpio_direction_input(gpio);
|
gpio_direction_input(gpio);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
gpio_int_type1[port] |= port_mask;
|
gpio_int_type1[port] |= port_mask;
|
||||||
gpio_int_type2[port] |= port_mask;
|
gpio_int_type2[port] |= port_mask;
|
||||||
desc->handle_irq = handle_edge_irq;
|
desc->handle_irq = handle_edge_irq;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
gpio_int_type1[port] |= port_mask;
|
gpio_int_type1[port] |= port_mask;
|
||||||
gpio_int_type2[port] &= ~port_mask;
|
gpio_int_type2[port] &= ~port_mask;
|
||||||
desc->handle_irq = handle_edge_irq;
|
desc->handle_irq = handle_edge_irq;
|
||||||
break;
|
break;
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
gpio_int_type1[port] &= ~port_mask;
|
gpio_int_type1[port] &= ~port_mask;
|
||||||
gpio_int_type2[port] |= port_mask;
|
gpio_int_type2[port] |= port_mask;
|
||||||
desc->handle_irq = handle_level_irq;
|
desc->handle_irq = handle_level_irq;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
gpio_int_type1[port] &= ~port_mask;
|
gpio_int_type1[port] &= ~port_mask;
|
||||||
gpio_int_type2[port] &= ~port_mask;
|
gpio_int_type2[port] &= ~port_mask;
|
||||||
desc->handle_irq = handle_level_irq;
|
desc->handle_irq = handle_level_irq;
|
||||||
break;
|
break;
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
gpio_int_type1[port] |= port_mask;
|
gpio_int_type1[port] |= port_mask;
|
||||||
/* set initial polarity based on current input level */
|
/* set initial polarity based on current input level */
|
||||||
if (gpio_get_value(gpio))
|
if (gpio_get_value(gpio))
|
||||||
|
|
|
@ -111,7 +111,7 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
|
||||||
reg = irq >> 5;
|
reg = irq >> 5;
|
||||||
bit = 1 << (irq % 32);
|
bit = 1 << (irq % 32);
|
||||||
|
|
||||||
if (type == IRQT_PROBE) {
|
if (type == IRQ_TYPE_PROBE) {
|
||||||
/* Don't mess with enabled GPIOs using preconfigured edges or
|
/* Don't mess with enabled GPIOs using preconfigured edges or
|
||||||
GPIOs set to alternate function during probe */
|
GPIOs set to alternate function during probe */
|
||||||
/* TODO: support probe */
|
/* TODO: support probe */
|
||||||
|
@ -120,7 +120,7 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
|
||||||
// return 0;
|
// return 0;
|
||||||
// if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
|
// if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
|
||||||
// return 0;
|
// return 0;
|
||||||
// type = __IRQT_RISEDGE | __IRQT_FALEDGE;
|
// type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIUS(reg) |= bit;
|
GIUS(reg) |= bit;
|
||||||
|
@ -128,19 +128,19 @@ imx_gpio_irq_type(unsigned int _irq, unsigned int type)
|
||||||
|
|
||||||
DEBUG_IRQ("setting type of irq %d to ", _irq);
|
DEBUG_IRQ("setting type of irq %d to ", _irq);
|
||||||
|
|
||||||
if (type & __IRQT_RISEDGE) {
|
if (type & IRQ_TYPE_EDGE_RISING) {
|
||||||
DEBUG_IRQ("rising edges\n");
|
DEBUG_IRQ("rising edges\n");
|
||||||
irq_type = 0x0;
|
irq_type = 0x0;
|
||||||
}
|
}
|
||||||
if (type & __IRQT_FALEDGE) {
|
if (type & IRQ_TYPE_EDGE_FALLING) {
|
||||||
DEBUG_IRQ("falling edges\n");
|
DEBUG_IRQ("falling edges\n");
|
||||||
irq_type = 0x1;
|
irq_type = 0x1;
|
||||||
}
|
}
|
||||||
if (type & __IRQT_LOWLVL) {
|
if (type & IRQ_TYPE_LEVEL_LOW) {
|
||||||
DEBUG_IRQ("low level\n");
|
DEBUG_IRQ("low level\n");
|
||||||
irq_type = 0x3;
|
irq_type = 0x3;
|
||||||
}
|
}
|
||||||
if (type & __IRQT_HIGHLVL) {
|
if (type & IRQ_TYPE_LEVEL_HIGH) {
|
||||||
DEBUG_IRQ("high level\n");
|
DEBUG_IRQ("high level\n");
|
||||||
irq_type = 0x2;
|
irq_type = 0x2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,19 +329,19 @@ static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
|
||||||
/*
|
/*
|
||||||
* Then, set the proper trigger type.
|
* Then, set the proper trigger type.
|
||||||
*/
|
*/
|
||||||
if (type & IRQT_FALLING)
|
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||||
GPIO_IRQ_falling_edge |= 1 << line;
|
GPIO_IRQ_falling_edge |= 1 << line;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_falling_edge &= ~(1 << line);
|
GPIO_IRQ_falling_edge &= ~(1 << line);
|
||||||
if (type & IRQT_RISING)
|
if (type & IRQ_TYPE_EDGE_RISING)
|
||||||
GPIO_IRQ_rising_edge |= 1 << line;
|
GPIO_IRQ_rising_edge |= 1 << line;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_rising_edge &= ~(1 << line);
|
GPIO_IRQ_rising_edge &= ~(1 << line);
|
||||||
if (type & IRQT_LOW)
|
if (type & IRQ_TYPE_LEVEL_LOW)
|
||||||
GPIO_IRQ_level_low |= 1 << line;
|
GPIO_IRQ_level_low |= 1 << line;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_level_low &= ~(1 << line);
|
GPIO_IRQ_level_low &= ~(1 << line);
|
||||||
if (type & IRQT_HIGH)
|
if (type & IRQ_TYPE_LEVEL_HIGH)
|
||||||
GPIO_IRQ_level_high |= 1 << line;
|
GPIO_IRQ_level_high |= 1 << line;
|
||||||
else
|
else
|
||||||
GPIO_IRQ_level_high &= ~(1 << line);
|
GPIO_IRQ_level_high &= ~(1 << line);
|
||||||
|
|
|
@ -126,23 +126,23 @@ static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
|
int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
|
||||||
irq_type = IXP23XX_IRQ_EDGE;
|
irq_type = IXP23XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
|
int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
|
||||||
irq_type = IXP23XX_IRQ_EDGE;
|
irq_type = IXP23XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
|
int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
|
||||||
irq_type = IXP23XX_IRQ_EDGE;
|
irq_type = IXP23XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
|
int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
|
||||||
irq_type = IXP23XX_IRQ_LEVEL;
|
irq_type = IXP23XX_IRQ_LEVEL;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
|
int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
|
||||||
irq_type = IXP23XX_IRQ_LEVEL;
|
irq_type = IXP23XX_IRQ_LEVEL;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -110,8 +110,8 @@ static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
|
||||||
|
|
||||||
static void __init roadrunner_pci_preinit(void)
|
static void __init roadrunner_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
|
set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp23xx_pci_preinit();
|
ixp23xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
|
|
||||||
void __init avila_pci_preinit(void)
|
void __init avila_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_AVILA_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_AVILA_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_AVILA_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_AVILA_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_AVILA_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_AVILA_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_AVILA_PCI_INTD, IRQT_LOW);
|
set_irq_type(IRQ_AVILA_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,23 +142,23 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (type){
|
switch (type){
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
|
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
|
||||||
irq_type = IXP4XX_IRQ_EDGE;
|
irq_type = IXP4XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
|
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
|
||||||
irq_type = IXP4XX_IRQ_EDGE;
|
irq_type = IXP4XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
|
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
|
||||||
irq_type = IXP4XX_IRQ_EDGE;
|
irq_type = IXP4XX_IRQ_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
|
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
|
||||||
irq_type = IXP4XX_IRQ_LEVEL;
|
irq_type = IXP4XX_IRQ_LEVEL;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
|
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
|
||||||
irq_type = IXP4XX_IRQ_LEVEL;
|
irq_type = IXP4XX_IRQ_LEVEL;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
|
|
||||||
void __init coyote_pci_preinit(void)
|
void __init coyote_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
|
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
|
set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
|
|
||||||
void __init dsmg600_pci_preinit(void)
|
void __init dsmg600_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTD, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTE, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTE, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_DSMG600_PCI_INTF, IRQT_LOW);
|
set_irq_type(IRQ_DSMG600_PCI_INTF, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
void __init fsg_pci_preinit(void)
|
void __init fsg_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_FSG_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_FSG_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_FSG_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_FSG_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_FSG_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_FSG_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
void __init gateway7001_pci_preinit(void)
|
void __init gateway7001_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,10 @@
|
||||||
*/
|
*/
|
||||||
void __init gtwx5715_pci_preinit(void)
|
void __init gtwx5715_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
|
set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
|
set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
|
set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
|
set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
|
|
||||||
void __init ixdp425_pci_preinit(void)
|
void __init ixdp425_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
void __init ixdpg425_pci_preinit(void)
|
void __init ixdpg425_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
|
|
||||||
void __init nas100d_pci_preinit(void)
|
void __init nas100d_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_NAS100D_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_NAS100D_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NAS100D_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_NAS100D_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NAS100D_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_NAS100D_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NAS100D_PCI_INTD, IRQT_LOW);
|
set_irq_type(IRQ_NAS100D_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NAS100D_PCI_INTE, IRQT_LOW);
|
set_irq_type(IRQ_NAS100D_PCI_INTE, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
|
|
||||||
void __init nslu2_pci_preinit(void)
|
void __init nslu2_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_NSLU2_PCI_INTA, IRQT_LOW);
|
set_irq_type(IRQ_NSLU2_PCI_INTA, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NSLU2_PCI_INTB, IRQT_LOW);
|
set_irq_type(IRQ_NSLU2_PCI_INTB, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_NSLU2_PCI_INTC, IRQT_LOW);
|
set_irq_type(IRQ_NSLU2_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
void __init wg302v2_pci_preinit(void)
|
void __init wg302v2_pci_preinit(void)
|
||||||
{
|
{
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
|
||||||
set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
|
||||||
|
|
||||||
ixp4xx_pci_preinit();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,21 +72,21 @@ static int ks8695_irq_set_type(unsigned int irqno, unsigned int type)
|
||||||
ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
|
ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
mode = IOPC_TM_HIGH;
|
mode = IOPC_TM_HIGH;
|
||||||
level_triggered = 1;
|
level_triggered = 1;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
mode = IOPC_TM_LOW;
|
mode = IOPC_TM_LOW;
|
||||||
level_triggered = 1;
|
level_triggered = 1;
|
||||||
break;
|
break;
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
mode = IOPC_TM_RISING;
|
mode = IOPC_TM_RISING;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
mode = IOPC_TM_FALLING;
|
mode = IOPC_TM_FALLING;
|
||||||
break;
|
break;
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
mode = IOPC_TM_EDGE;
|
mode = IOPC_TM_EDGE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -99,19 +99,19 @@ netx_hif_irq_type(unsigned int _irq, unsigned int type)
|
||||||
|
|
||||||
irq = _irq - NETX_IRQ_HIF_CHAINED(0);
|
irq = _irq - NETX_IRQ_HIF_CHAINED(0);
|
||||||
|
|
||||||
if (type & __IRQT_RISEDGE) {
|
if (type & IRQ_TYPE_EDGE_RISING) {
|
||||||
DEBUG_IRQ("rising edges\n");
|
DEBUG_IRQ("rising edges\n");
|
||||||
val |= (1 << 26) << irq;
|
val |= (1 << 26) << irq;
|
||||||
}
|
}
|
||||||
if (type & __IRQT_FALEDGE) {
|
if (type & IRQ_TYPE_EDGE_FALLING) {
|
||||||
DEBUG_IRQ("falling edges\n");
|
DEBUG_IRQ("falling edges\n");
|
||||||
val &= ~((1 << 26) << irq);
|
val &= ~((1 << 26) << irq);
|
||||||
}
|
}
|
||||||
if (type & __IRQT_LOWLVL) {
|
if (type & IRQ_TYPE_LEVEL_LOW) {
|
||||||
DEBUG_IRQ("low level\n");
|
DEBUG_IRQ("low level\n");
|
||||||
val &= ~((1 << 26) << irq);
|
val &= ~((1 << 26) << irq);
|
||||||
}
|
}
|
||||||
if (type & __IRQT_HIGHLVL) {
|
if (type & IRQ_TYPE_LEVEL_HIGH) {
|
||||||
DEBUG_IRQ("high level\n");
|
DEBUG_IRQ("high level\n");
|
||||||
val |= (1 << 26) << irq;
|
val |= (1 << 26) << irq;
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ static void __init osk_init_cf(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* the CF I/O IRQ is really active-low */
|
/* the CF I/O IRQ is really active-low */
|
||||||
set_irq_type(OMAP_GPIO_IRQ(62), IRQT_FALLING);
|
set_irq_type(OMAP_GPIO_IRQ(62), IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init osk_init_irq(void)
|
static void __init osk_init_irq(void)
|
||||||
|
@ -483,7 +483,7 @@ static void __init osk_mistral_init(void)
|
||||||
omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
|
omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
|
||||||
gpio_request(4, "ts_int");
|
gpio_request(4, "ts_int");
|
||||||
gpio_direction_input(4);
|
gpio_direction_input(4);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
|
set_irq_type(OMAP_GPIO_IRQ(4), IRQ_TYPE_EDGE_FALLING);
|
||||||
|
|
||||||
spi_register_board_info(mistral_boardinfo,
|
spi_register_board_info(mistral_boardinfo,
|
||||||
ARRAY_SIZE(mistral_boardinfo));
|
ARRAY_SIZE(mistral_boardinfo));
|
||||||
|
@ -494,7 +494,7 @@ static void __init osk_mistral_init(void)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
gpio_direction_input(OMAP_MPUIO(2));
|
gpio_direction_input(OMAP_MPUIO(2));
|
||||||
set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQ_TYPE_EDGE_RISING);
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
/* share the IRQ in case someone wants to use the
|
/* share the IRQ in case someone wants to use the
|
||||||
* button for more than wakeup from system sleep.
|
* button for more than wakeup from system sleep.
|
||||||
|
|
|
@ -298,11 +298,11 @@ palmz71_powercable(int irq, void *dev_id)
|
||||||
if (omap_get_gpio_datain(PALMZ71_USBDETECT_GPIO)) {
|
if (omap_get_gpio_datain(PALMZ71_USBDETECT_GPIO)) {
|
||||||
printk(KERN_INFO "PM: Power cable connected\n");
|
printk(KERN_INFO "PM: Power cable connected\n");
|
||||||
set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
|
set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
|
||||||
IRQT_FALLING);
|
IRQ_TYPE_EDGE_FALLING);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_INFO "PM: Power cable disconnected\n");
|
printk(KERN_INFO "PM: Power cable disconnected\n");
|
||||||
set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
|
set_irq_type(OMAP_GPIO_IRQ(PALMZ71_USBDETECT_GPIO),
|
||||||
IRQT_RISING);
|
IRQ_TYPE_EDGE_RISING);
|
||||||
}
|
}
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,10 +186,10 @@ static void __init voiceblue_init(void)
|
||||||
omap_request_gpio(13);
|
omap_request_gpio(13);
|
||||||
omap_request_gpio(14);
|
omap_request_gpio(14);
|
||||||
omap_request_gpio(15);
|
omap_request_gpio(15);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(12), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(12), IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(14), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(14), IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(15), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(15), IRQ_TYPE_EDGE_RISING);
|
||||||
|
|
||||||
platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
|
platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
|
||||||
omap_board_config = voiceblue_config;
|
omap_board_config = voiceblue_config;
|
||||||
|
|
|
@ -181,7 +181,7 @@ void omap1510_fpga_init_irq(void)
|
||||||
*/
|
*/
|
||||||
omap_request_gpio(13);
|
omap_request_gpio(13);
|
||||||
omap_set_gpio_direction(13, 1);
|
omap_set_gpio_direction(13, 1);
|
||||||
set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(13), IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
|
set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -337,17 +337,17 @@ static void __init apollon_sw_init(void)
|
||||||
omap_request_gpio(SW_DOWN_GPIO58);
|
omap_request_gpio(SW_DOWN_GPIO58);
|
||||||
omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
|
omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
|
||||||
|
|
||||||
set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQ_TYPE_EDGE_RISING);
|
||||||
if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
|
if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
|
||||||
IRQF_SHARED, "enter sw",
|
IRQF_SHARED, "enter sw",
|
||||||
&apollon_sw_interrupt))
|
&apollon_sw_interrupt))
|
||||||
return;
|
return;
|
||||||
set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQ_TYPE_EDGE_RISING);
|
||||||
if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
|
if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
|
||||||
IRQF_SHARED, "up sw",
|
IRQF_SHARED, "up sw",
|
||||||
&apollon_sw_interrupt))
|
&apollon_sw_interrupt))
|
||||||
return;
|
return;
|
||||||
set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
|
set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQ_TYPE_EDGE_RISING);
|
||||||
if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
|
if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
|
||||||
IRQF_SHARED, "down sw",
|
IRQF_SHARED, "down sw",
|
||||||
&apollon_sw_interrupt))
|
&apollon_sw_interrupt))
|
||||||
|
|
|
@ -213,7 +213,7 @@ void __init db88f5281_pci_preinit(void)
|
||||||
pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
|
pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
|
||||||
if (gpio_request(pin, "PCI Int1") == 0) {
|
if (gpio_request(pin, "PCI Int1") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "db88f5281_pci_preinit faield to "
|
printk(KERN_ERR "db88f5281_pci_preinit faield to "
|
||||||
"set_irq_type pin %d\n", pin);
|
"set_irq_type pin %d\n", pin);
|
||||||
|
@ -226,7 +226,7 @@ void __init db88f5281_pci_preinit(void)
|
||||||
pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
|
pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
|
||||||
if (gpio_request(pin, "PCI Int2") == 0) {
|
if (gpio_request(pin, "PCI Int2") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "db88f5281_pci_preinit faield "
|
printk(KERN_ERR "db88f5281_pci_preinit faield "
|
||||||
"to set_irq_type pin %d\n", pin);
|
"to set_irq_type pin %d\n", pin);
|
||||||
|
|
|
@ -91,27 +91,27 @@ static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
desc->handle_irq = handle_level_irq;
|
desc->handle_irq = handle_level_irq;
|
||||||
desc->status |= IRQ_LEVEL;
|
desc->status |= IRQ_LEVEL;
|
||||||
orion5x_clrbits(GPIO_IN_POL, (1 << pin));
|
orion5x_clrbits(GPIO_IN_POL, (1 << pin));
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
desc->handle_irq = handle_level_irq;
|
desc->handle_irq = handle_level_irq;
|
||||||
desc->status |= IRQ_LEVEL;
|
desc->status |= IRQ_LEVEL;
|
||||||
orion5x_setbits(GPIO_IN_POL, (1 << pin));
|
orion5x_setbits(GPIO_IN_POL, (1 << pin));
|
||||||
break;
|
break;
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
desc->handle_irq = handle_edge_irq;
|
desc->handle_irq = handle_edge_irq;
|
||||||
desc->status &= ~IRQ_LEVEL;
|
desc->status &= ~IRQ_LEVEL;
|
||||||
orion5x_clrbits(GPIO_IN_POL, (1 << pin));
|
orion5x_clrbits(GPIO_IN_POL, (1 << pin));
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
desc->handle_irq = handle_edge_irq;
|
desc->handle_irq = handle_edge_irq;
|
||||||
desc->status &= ~IRQ_LEVEL;
|
desc->status &= ~IRQ_LEVEL;
|
||||||
orion5x_setbits(GPIO_IN_POL, (1 << pin));
|
orion5x_setbits(GPIO_IN_POL, (1 << pin));
|
||||||
break;
|
break;
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
desc->handle_irq = handle_edge_irq;
|
desc->handle_irq = handle_edge_irq;
|
||||||
desc->status &= ~IRQ_LEVEL;
|
desc->status &= ~IRQ_LEVEL;
|
||||||
/*
|
/*
|
||||||
|
@ -156,7 +156,7 @@ static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||||
if (cause & (1 << pin)) {
|
if (cause & (1 << pin)) {
|
||||||
irq = gpio_to_irq(pin);
|
irq = gpio_to_irq(pin);
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
|
if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
|
||||||
/* Swap polarity (race with GPIO line) */
|
/* Swap polarity (race with GPIO line) */
|
||||||
u32 polarity = readl(GPIO_IN_POL);
|
u32 polarity = readl(GPIO_IN_POL);
|
||||||
polarity ^= 1 << pin;
|
polarity ^= 1 << pin;
|
||||||
|
|
|
@ -148,7 +148,7 @@ void __init rd88f5182_pci_preinit(void)
|
||||||
pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
|
pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
|
||||||
if (gpio_request(pin, "PCI IntA") == 0) {
|
if (gpio_request(pin, "PCI IntA") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
||||||
"set_irq_type pin %d\n", pin);
|
"set_irq_type pin %d\n", pin);
|
||||||
|
@ -161,7 +161,7 @@ void __init rd88f5182_pci_preinit(void)
|
||||||
pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
|
pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
|
||||||
if (gpio_request(pin, "PCI IntB") == 0) {
|
if (gpio_request(pin, "PCI IntB") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
||||||
"set_irq_type pin %d\n", pin);
|
"set_irq_type pin %d\n", pin);
|
||||||
|
|
|
@ -117,7 +117,7 @@ void __init qnap_ts209_pci_preinit(void)
|
||||||
pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
|
pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
|
||||||
if (gpio_request(pin, "PCI Int1") == 0) {
|
if (gpio_request(pin, "PCI Int1") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
|
printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
|
||||||
"set_irq_type pin %d\n", pin);
|
"set_irq_type pin %d\n", pin);
|
||||||
|
@ -131,7 +131,7 @@ void __init qnap_ts209_pci_preinit(void)
|
||||||
pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
|
pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
|
||||||
if (gpio_request(pin, "PCI Int2") == 0) {
|
if (gpio_request(pin, "PCI Int2") == 0) {
|
||||||
if (gpio_direction_input(pin) == 0) {
|
if (gpio_direction_input(pin) == 0) {
|
||||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed "
|
printk(KERN_ERR "qnap_ts209_pci_preinit failed "
|
||||||
"to set_irq_type pin %d\n", pin);
|
"to set_irq_type pin %d\n", pin);
|
||||||
|
|
|
@ -56,28 +56,28 @@ static void pnx4008_mask_ack_irq(unsigned int irq)
|
||||||
static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
|
static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
|
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
|
||||||
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */
|
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */
|
||||||
set_irq_handler(irq, handle_edge_irq);
|
set_irq_handler(irq, handle_edge_irq);
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
|
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
|
||||||
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */
|
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */
|
||||||
set_irq_handler(irq, handle_edge_irq);
|
set_irq_handler(irq, handle_edge_irq);
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
|
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
|
||||||
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */
|
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */
|
||||||
set_irq_handler(irq, handle_level_irq);
|
set_irq_handler(irq, handle_level_irq);
|
||||||
break;
|
break;
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
|
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
|
||||||
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */
|
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */
|
||||||
set_irq_handler(irq, handle_level_irq);
|
set_irq_handler(irq, handle_level_irq);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* IRQT_BOTHEDGE is not supported */
|
/* IRQ_TYPE_EDGE_BOTH is not supported */
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
|
printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -71,7 +71,7 @@ void __cmx270_pci_init_irq(int irq_gpio)
|
||||||
|
|
||||||
cmx270_it8152_irq_gpio = irq_gpio;
|
cmx270_it8152_irq_gpio = irq_gpio;
|
||||||
|
|
||||||
set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING);
|
set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
|
||||||
|
|
||||||
set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
|
set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ static void __init lpd270_init_irq(void)
|
||||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||||
}
|
}
|
||||||
set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
|
set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
|
||||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ static void __init lubbock_init_irq(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
|
set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
|
||||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -191,7 +191,7 @@ static void __init mainstone_init_irq(void)
|
||||||
MST_INTSETCLR = 0;
|
MST_INTSETCLR = 0;
|
||||||
|
|
||||||
set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
|
set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
|
||||||
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
|
set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -146,18 +146,18 @@ void sharpsl_pm_pxa_init(void)
|
||||||
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
|
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
|
||||||
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
|
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
|
||||||
}
|
}
|
||||||
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQT_BOTHEDGE);
|
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
|
||||||
|
|
||||||
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
|
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
|
||||||
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
|
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
|
||||||
}
|
}
|
||||||
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQT_FALLING);
|
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
|
||||||
|
|
||||||
if (sharpsl_pm.machinfo->gpio_fatal) {
|
if (sharpsl_pm.machinfo->gpio_fatal) {
|
||||||
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
|
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
|
||||||
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
|
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
|
||||||
}
|
}
|
||||||
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING);
|
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sharpsl_pm.machinfo->batfull_irq)
|
if (sharpsl_pm.machinfo->batfull_irq)
|
||||||
|
@ -166,7 +166,7 @@ void sharpsl_pm_pxa_init(void)
|
||||||
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
|
if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
|
||||||
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
|
dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
|
||||||
}
|
}
|
||||||
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING);
|
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ static struct resource dm9000_resources[] = {
|
||||||
[2] = {
|
[2] = {
|
||||||
.start = TRIZEPS4_ETH_IRQ,
|
.start = TRIZEPS4_ETH_IRQ,
|
||||||
.end = TRIZEPS4_ETH_IRQ,
|
.end = TRIZEPS4_ETH_IRQ,
|
||||||
.flags = (IORESOURCE_IRQ | IRQT_RISING),
|
.flags = (IORESOURCE_IRQ | IRQ_TYPE_EDGE_RISING),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ static struct resource cerf_flash_resource = {
|
||||||
static void __init cerf_init_irq(void)
|
static void __init cerf_init_irq(void)
|
||||||
{
|
{
|
||||||
sa1100_init_irq();
|
sa1100_init_irq();
|
||||||
set_irq_type(CERF_ETH_IRQ, IRQT_RISING);
|
set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct map_desc cerf_io_desc[] __initdata = {
|
static struct map_desc cerf_io_desc[] __initdata = {
|
||||||
|
|
|
@ -834,7 +834,7 @@ static void __init h3800_init_irq(void)
|
||||||
set_irq_chip(irq, &h3800_gpio_irqchip);
|
set_irq_chip(irq, &h3800_gpio_irqchip);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING);
|
set_irq_type(IRQ_GPIO_H3800_ASIC, IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux);
|
set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,17 +46,17 @@ static int sa1100_gpio_type(unsigned int irq, unsigned int type)
|
||||||
else
|
else
|
||||||
mask = GPIO11_27_MASK(irq);
|
mask = GPIO11_27_MASK(irq);
|
||||||
|
|
||||||
if (type == IRQT_PROBE) {
|
if (type == IRQ_TYPE_PROBE) {
|
||||||
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
|
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
|
||||||
return 0;
|
return 0;
|
||||||
type = __IRQT_RISEDGE | __IRQT_FALEDGE;
|
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type & __IRQT_RISEDGE) {
|
if (type & IRQ_TYPE_EDGE_RISING) {
|
||||||
GPIO_IRQ_rising_edge |= mask;
|
GPIO_IRQ_rising_edge |= mask;
|
||||||
} else
|
} else
|
||||||
GPIO_IRQ_rising_edge &= ~mask;
|
GPIO_IRQ_rising_edge &= ~mask;
|
||||||
if (type & __IRQT_FALEDGE) {
|
if (type & IRQ_TYPE_EDGE_FALLING) {
|
||||||
GPIO_IRQ_falling_edge |= mask;
|
GPIO_IRQ_falling_edge |= mask;
|
||||||
} else
|
} else
|
||||||
GPIO_IRQ_falling_edge &= ~mask;
|
GPIO_IRQ_falling_edge &= ~mask;
|
||||||
|
|
|
@ -151,7 +151,7 @@ static int __devinit neponset_probe(struct platform_device *dev)
|
||||||
/*
|
/*
|
||||||
* Install handler for GPIO25.
|
* Install handler for GPIO25.
|
||||||
*/
|
*/
|
||||||
set_irq_type(IRQ_GPIO25, IRQT_RISING);
|
set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
|
||||||
set_irq_chained_handler(IRQ_GPIO25, neponset_irq_handler);
|
set_irq_chained_handler(IRQ_GPIO25, neponset_irq_handler);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -143,7 +143,7 @@ static void __init pleb_map_io(void)
|
||||||
|
|
||||||
GPDR &= ~GPIO_ETH0_IRQ;
|
GPDR &= ~GPIO_ETH0_IRQ;
|
||||||
|
|
||||||
set_irq_type(GPIO_ETH0_IRQ, IRQT_FALLING);
|
set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(PLEB, "PLEB")
|
MACHINE_START(PLEB, "PLEB")
|
||||||
|
|
|
@ -274,6 +274,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
|
||||||
void *
|
void *
|
||||||
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
|
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
|
||||||
{
|
{
|
||||||
|
void *memory;
|
||||||
|
|
||||||
|
if (dma_alloc_from_coherent(dev, size, handle, &memory))
|
||||||
|
return memory;
|
||||||
|
|
||||||
if (arch_is_coherent()) {
|
if (arch_is_coherent()) {
|
||||||
void *virt;
|
void *virt;
|
||||||
|
|
||||||
|
@ -362,6 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
|
||||||
|
|
||||||
WARN_ON(irqs_disabled());
|
WARN_ON(irqs_disabled());
|
||||||
|
|
||||||
|
if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
|
||||||
|
return;
|
||||||
|
|
||||||
if (arch_is_coherent()) {
|
if (arch_is_coherent()) {
|
||||||
kfree(cpu_addr);
|
kfree(cpu_addr);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -37,7 +37,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pmd_t *pmd;
|
pmd_t *pmd;
|
||||||
pte_t *pte, entry;
|
pte_t *pte, entry;
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
pgd = pgd_offset(vma->vm_mm, address);
|
pgd = pgd_offset(vma->vm_mm, address);
|
||||||
if (pgd_none(*pgd))
|
if (pgd_none(*pgd))
|
||||||
|
@ -54,16 +54,20 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
|
||||||
pte = pte_offset_map(pmd, address);
|
pte = pte_offset_map(pmd, address);
|
||||||
entry = *pte;
|
entry = *pte;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this page is present, it's actually being shared.
|
||||||
|
*/
|
||||||
|
ret = pte_present(entry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this page isn't present, or is already setup to
|
* If this page isn't present, or is already setup to
|
||||||
* fault (ie, is old), we can safely ignore any issues.
|
* fault (ie, is old), we can safely ignore any issues.
|
||||||
*/
|
*/
|
||||||
if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
|
if (ret && pte_val(entry) & shared_pte_mask) {
|
||||||
flush_cache_page(vma, address, pte_pfn(entry));
|
flush_cache_page(vma, address, pte_pfn(entry));
|
||||||
pte_val(entry) &= ~shared_pte_mask;
|
pte_val(entry) &= ~shared_pte_mask;
|
||||||
set_pte_at(vma->vm_mm, address, pte, entry);
|
set_pte_at(vma->vm_mm, address, pte, entry);
|
||||||
flush_tlb_page(vma, address);
|
flush_tlb_page(vma, address);
|
||||||
ret = 1;
|
|
||||||
}
|
}
|
||||||
pte_unmap(pte);
|
pte_unmap(pte);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -73,19 +73,19 @@ static int gpio_set_irq_type(u32 irq, u32 type)
|
||||||
void __iomem *reg = port->base;
|
void __iomem *reg = port->base;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
edge = GPIO_INT_RISE_EDGE;
|
edge = GPIO_INT_RISE_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
edge = GPIO_INT_FALL_EDGE;
|
edge = GPIO_INT_FALL_EDGE;
|
||||||
break;
|
break;
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
edge = GPIO_INT_LOW_LEV;
|
edge = GPIO_INT_LOW_LEV;
|
||||||
break;
|
break;
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
edge = GPIO_INT_HIGH_LEV;
|
edge = GPIO_INT_HIGH_LEV;
|
||||||
break;
|
break;
|
||||||
default: /* this includes IRQT_BOTHEDGE */
|
default: /* this includes IRQ_TYPE_EDGE_BOTH */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -517,13 +517,13 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
|
||||||
u32 gpio_bit = 1 << gpio;
|
u32 gpio_bit = 1 << gpio;
|
||||||
|
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
|
||||||
trigger & __IRQT_LOWLVL);
|
trigger & IRQ_TYPE_LEVEL_LOW);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
|
||||||
trigger & __IRQT_HIGHLVL);
|
trigger & IRQ_TYPE_LEVEL_HIGH);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
|
||||||
trigger & __IRQT_RISEDGE);
|
trigger & IRQ_TYPE_EDGE_RISING);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
|
||||||
trigger & __IRQT_FALEDGE);
|
trigger & IRQ_TYPE_EDGE_FALLING);
|
||||||
|
|
||||||
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
|
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
|
||||||
if (trigger != 0)
|
if (trigger != 0)
|
||||||
|
@ -555,9 +555,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
case METHOD_MPUIO:
|
case METHOD_MPUIO:
|
||||||
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger & __IRQT_RISEDGE)
|
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger & __IRQT_FALEDGE)
|
else if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -567,9 +567,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
case METHOD_GPIO_1510:
|
case METHOD_GPIO_1510:
|
||||||
reg += OMAP1510_GPIO_INT_CONTROL;
|
reg += OMAP1510_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger & __IRQT_RISEDGE)
|
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger & __IRQT_FALEDGE)
|
else if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -584,9 +584,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
gpio &= 0x07;
|
gpio &= 0x07;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
l &= ~(3 << (gpio << 1));
|
l &= ~(3 << (gpio << 1));
|
||||||
if (trigger & __IRQT_RISEDGE)
|
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||||
l |= 2 << (gpio << 1);
|
l |= 2 << (gpio << 1);
|
||||||
if (trigger & __IRQT_FALEDGE)
|
if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||||
l |= 1 << (gpio << 1);
|
l |= 1 << (gpio << 1);
|
||||||
if (trigger)
|
if (trigger)
|
||||||
/* Enable wake-up during idle for dynamic tick */
|
/* Enable wake-up during idle for dynamic tick */
|
||||||
|
@ -599,9 +599,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
case METHOD_GPIO_730:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_INT_CONTROL;
|
reg += OMAP730_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger & __IRQT_RISEDGE)
|
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger & __IRQT_FALEDGE)
|
else if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -887,7 +887,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
|
||||||
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
|
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
|
||||||
_set_gpio_irqenable(bank, gpio, 0);
|
_set_gpio_irqenable(bank, gpio, 0);
|
||||||
_clear_gpio_irqstatus(bank, gpio);
|
_clear_gpio_irqstatus(bank, gpio);
|
||||||
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
|
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
|
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
|
||||||
|
@ -924,7 +924,7 @@ int omap_request_gpio(int gpio)
|
||||||
/* Set trigger to none. You need to enable the desired trigger with
|
/* Set trigger to none. You need to enable the desired trigger with
|
||||||
* request_irq() or set_irq_type().
|
* request_irq() or set_irq_type().
|
||||||
*/
|
*/
|
||||||
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
|
_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_OMAP15XX
|
#ifdef CONFIG_ARCH_OMAP15XX
|
||||||
if (bank->method == METHOD_GPIO_1510) {
|
if (bank->method == METHOD_GPIO_1510) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ config PLAT_S3C24XX
|
||||||
depends on ARCH_S3C2410
|
depends on ARCH_S3C2410
|
||||||
default y if ARCH_S3C2410
|
default y if ARCH_S3C2410
|
||||||
select NO_IOPORT
|
select NO_IOPORT
|
||||||
select HAVE_GPIO_LIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
help
|
help
|
||||||
Base platform code for any Samsung S3C24XX device
|
Base platform code for any Samsung S3C24XX device
|
||||||
|
|
||||||
|
|
|
@ -292,27 +292,27 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
|
||||||
/* Set the external interrupt to pointed trigger type */
|
/* Set the external interrupt to pointed trigger type */
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case IRQT_NOEDGE:
|
case IRQ_TYPE_NONE:
|
||||||
printk(KERN_WARNING "No edge setting!\n");
|
printk(KERN_WARNING "No edge setting!\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRQT_RISING:
|
case IRQ_TYPE_EDGE_RISING:
|
||||||
newvalue = S3C2410_EXTINT_RISEEDGE;
|
newvalue = S3C2410_EXTINT_RISEEDGE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRQT_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
newvalue = S3C2410_EXTINT_FALLEDGE;
|
newvalue = S3C2410_EXTINT_FALLEDGE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRQT_BOTHEDGE:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
newvalue = S3C2410_EXTINT_BOTHEDGE;
|
newvalue = S3C2410_EXTINT_BOTHEDGE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRQT_LOW:
|
case IRQ_TYPE_LEVEL_LOW:
|
||||||
newvalue = S3C2410_EXTINT_LOWLEV;
|
newvalue = S3C2410_EXTINT_LOWLEV;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRQT_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
newvalue = S3C2410_EXTINT_HILEV;
|
newvalue = S3C2410_EXTINT_HILEV;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/atmel-mci.h>
|
||||||
|
|
||||||
#include <asm/arch/at32ap700x.h>
|
#include <asm/arch/at32ap700x.h>
|
||||||
#include <asm/arch/board.h>
|
#include <asm/arch/board.h>
|
||||||
#include <asm/arch/init.h>
|
#include <asm/arch/init.h>
|
||||||
|
@ -260,6 +262,21 @@ void __init setup_board(void)
|
||||||
at32_setup_serial_console(0);
|
at32_setup_serial_console(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||||
|
|
||||||
|
/* MMC card detect requires MACB0 *NOT* be used */
|
||||||
|
#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
|
||||||
|
static struct mci_platform_data __initdata mci0_data = {
|
||||||
|
.detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */
|
||||||
|
.wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
|
||||||
|
};
|
||||||
|
#define MCI_PDATA &mci0_data
|
||||||
|
#else
|
||||||
|
#define MCI_PDATA NULL
|
||||||
|
#endif /* SW6 for sd{cd,wp} routing */
|
||||||
|
|
||||||
|
#endif /* SW2 for MMC signal routing */
|
||||||
|
|
||||||
static int __init atstk1002_init(void)
|
static int __init atstk1002_init(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -309,7 +326,7 @@ static int __init atstk1002_init(void)
|
||||||
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
|
#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
|
||||||
at32_add_device_mci(0, NULL);
|
at32_add_device_mci(0, MCI_PDATA);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
|
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
|
||||||
set_hw_addr(at32_add_device_eth(1, ð_data[1]));
|
set_hw_addr(at32_add_device_eth(1, ð_data[1]));
|
||||||
|
|
|
@ -154,7 +154,7 @@ static int __init atstk1003_init(void)
|
||||||
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||||
at32_add_device_mci(0);
|
at32_add_device_mci(0, NULL);
|
||||||
#endif
|
#endif
|
||||||
at32_add_device_usba(0, NULL);
|
at32_add_device_usba(0, NULL);
|
||||||
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
|
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
|
||||||
|
|
|
@ -137,7 +137,7 @@ static int __init atstk1004_init(void)
|
||||||
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||||
at32_add_device_mci(0);
|
at32_add_device_mci(0, NULL);
|
||||||
#endif
|
#endif
|
||||||
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
|
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
|
||||||
fbmem_start, fbmem_size, 0);
|
fbmem_start, fbmem_size, 0);
|
||||||
|
|
|
@ -43,6 +43,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct clock_event_device *evdev = dev_id;
|
struct clock_event_device *evdev = dev_id;
|
||||||
|
|
||||||
|
if (unlikely(!(intc_get_pending(0) & 1)))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable the interrupt until the clockevent subsystem
|
* Disable the interrupt until the clockevent subsystem
|
||||||
* reprograms it.
|
* reprograms it.
|
||||||
|
@ -55,7 +58,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
static struct irqaction timer_irqaction = {
|
static struct irqaction timer_irqaction = {
|
||||||
.handler = timer_interrupt,
|
.handler = timer_interrupt,
|
||||||
.flags = IRQF_TIMER | IRQF_DISABLED,
|
/* Oprofile uses the same irq as the timer, so allow it to be shared */
|
||||||
|
.flags = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
|
||||||
.name = "avr32_comparator",
|
.name = "avr32_comparator",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/usb/atmel_usba_udc.h>
|
#include <linux/usb/atmel_usba_udc.h>
|
||||||
|
|
||||||
|
@ -1285,7 +1286,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
|
||||||
{
|
{
|
||||||
struct mci_platform_data _data;
|
struct mci_platform_data _data;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct dw_dma_slave *dws;
|
|
||||||
|
|
||||||
if (id != 0)
|
if (id != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1300,7 +1300,9 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
data = &_data;
|
data = &_data;
|
||||||
memset(data, 0, sizeof(struct mci_platform_data));
|
memset(data, -1, sizeof(struct mci_platform_data));
|
||||||
|
data->detect_pin = GPIO_PIN_NONE;
|
||||||
|
data->wp_pin = GPIO_PIN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platform_device_add_data(pdev, data,
|
if (platform_device_add_data(pdev, data,
|
||||||
|
@ -1314,12 +1316,10 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
|
||||||
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
|
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
|
||||||
select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
|
select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
|
||||||
|
|
||||||
if (data) {
|
if (gpio_is_valid(data->detect_pin))
|
||||||
if (data->detect_pin != GPIO_PIN_NONE)
|
at32_select_gpio(data->detect_pin, 0);
|
||||||
at32_select_gpio(data->detect_pin, 0);
|
if (gpio_is_valid(data->wp_pin))
|
||||||
if (data->wp_pin != GPIO_PIN_NONE)
|
at32_select_gpio(data->wp_pin, 0);
|
||||||
at32_select_gpio(data->wp_pin, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
atmel_mci0_pclk.dev = &pdev->dev;
|
atmel_mci0_pclk.dev = &pdev->dev;
|
||||||
|
|
||||||
|
@ -1853,11 +1853,11 @@ at32_add_device_cf(unsigned int id, unsigned int extint,
|
||||||
if (at32_init_ide_or_cf(pdev, data->cs, extint))
|
if (at32_init_ide_or_cf(pdev, data->cs, extint))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (data->detect_pin != GPIO_PIN_NONE)
|
if (gpio_is_valid(data->detect_pin))
|
||||||
at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
|
at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
|
||||||
if (data->reset_pin != GPIO_PIN_NONE)
|
if (gpio_is_valid(data->reset_pin))
|
||||||
at32_select_gpio(data->reset_pin, 0);
|
at32_select_gpio(data->reset_pin, 0);
|
||||||
if (data->vcc_pin != GPIO_PIN_NONE)
|
if (gpio_is_valid(data->vcc_pin))
|
||||||
at32_select_gpio(data->vcc_pin, 0);
|
at32_select_gpio(data->vcc_pin, 0);
|
||||||
/* READY is used as extint, so we can't select it as gpio */
|
/* READY is used as extint, so we can't select it as gpio */
|
||||||
|
|
||||||
|
@ -1937,9 +1937,11 @@ static struct clk atmel_ac97c0_pclk = {
|
||||||
.index = 10,
|
.index = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct platform_device *__init at32_add_device_ac97c(unsigned int id)
|
struct platform_device *__init
|
||||||
|
at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
struct ac97c_platform_data _data;
|
||||||
|
|
||||||
if (id != 0)
|
if (id != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1950,19 +1952,37 @@ struct platform_device *__init at32_add_device_ac97c(unsigned int id)
|
||||||
|
|
||||||
if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
|
if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
|
||||||
ARRAY_SIZE(atmel_ac97c0_resource)))
|
ARRAY_SIZE(atmel_ac97c0_resource)))
|
||||||
goto err_add_resources;
|
goto fail;
|
||||||
|
|
||||||
select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
|
if (!data) {
|
||||||
select_peripheral(PB(21), PERIPH_B, 0); /* SDO */
|
data = &_data;
|
||||||
select_peripheral(PB(22), PERIPH_B, 0); /* SDI */
|
memset(data, 0, sizeof(struct ac97c_platform_data));
|
||||||
select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
|
data->reset_pin = GPIO_PIN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->dma_rx_periph_id = 3;
|
||||||
|
data->dma_tx_periph_id = 4;
|
||||||
|
data->dma_controller_id = 0;
|
||||||
|
|
||||||
|
if (platform_device_add_data(pdev, data,
|
||||||
|
sizeof(struct ac97c_platform_data)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
select_peripheral(PB(20), PERIPH_B, 0); /* SDO */
|
||||||
|
select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */
|
||||||
|
select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */
|
||||||
|
select_peripheral(PB(23), PERIPH_B, 0); /* SDI */
|
||||||
|
|
||||||
|
/* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
|
||||||
|
if (data->reset_pin != GPIO_PIN_NONE)
|
||||||
|
at32_select_gpio(data->reset_pin, 0);
|
||||||
|
|
||||||
atmel_ac97c0_pclk.dev = &pdev->dev;
|
atmel_ac97c0_pclk.dev = &pdev->dev;
|
||||||
|
|
||||||
platform_device_add(pdev);
|
platform_device_add(pdev);
|
||||||
return pdev;
|
return pdev;
|
||||||
|
|
||||||
err_add_resources:
|
fail:
|
||||||
platform_device_put(pdev);
|
platform_device_put(pdev);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,6 +641,7 @@ config PCI
|
||||||
bool
|
bool
|
||||||
depends on ETRAX_CARDBUS
|
depends on ETRAX_CARDBUS
|
||||||
default y
|
default y
|
||||||
|
select HAVE_GENERIC_DMA_COHERENT
|
||||||
|
|
||||||
config ETRAX_IOP_FW_LOAD
|
config ETRAX_IOP_FW_LOAD
|
||||||
tristate "IO-processor hotplug firmware loading support"
|
tristate "IO-processor hotplug firmware loading support"
|
||||||
|
|
|
@ -15,35 +15,16 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
struct dma_coherent_mem {
|
|
||||||
void *virt_base;
|
|
||||||
u32 device_base;
|
|
||||||
int size;
|
|
||||||
int flags;
|
|
||||||
unsigned long *bitmap;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *dma_alloc_coherent(struct device *dev, size_t size,
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, gfp_t gfp)
|
dma_addr_t *dma_handle, gfp_t gfp)
|
||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
|
||||||
int order = get_order(size);
|
int order = get_order(size);
|
||||||
/* ignore region specifiers */
|
/* ignore region specifiers */
|
||||||
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
|
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
|
||||||
|
|
||||||
if (mem) {
|
if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
|
||||||
int page = bitmap_find_free_region(mem->bitmap, mem->size,
|
return ret;
|
||||||
order);
|
|
||||||
if (page >= 0) {
|
|
||||||
*dma_handle = mem->device_base + (page << PAGE_SHIFT);
|
|
||||||
ret = mem->virt_base + (page << PAGE_SHIFT);
|
|
||||||
memset(ret, 0, size);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (mem->flags & DMA_MEMORY_EXCLUSIVE)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
|
if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
|
||||||
gfp |= GFP_DMA;
|
gfp |= GFP_DMA;
|
||||||
|
@ -60,90 +41,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
void dma_free_coherent(struct device *dev, size_t size,
|
void dma_free_coherent(struct device *dev, size_t size,
|
||||||
void *vaddr, dma_addr_t dma_handle)
|
void *vaddr, dma_addr_t dma_handle)
|
||||||
{
|
{
|
||||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
|
||||||
int order = get_order(size);
|
int order = get_order(size);
|
||||||
|
|
||||||
if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
if (!dma_release_from_coherent(dev, order, vaddr))
|
||||||
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
bitmap_release_region(mem->bitmap, page, order);
|
|
||||||
} else
|
|
||||||
free_pages((unsigned long)vaddr, order);
|
free_pages((unsigned long)vaddr, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
|
|
||||||
dma_addr_t device_addr, size_t size, int flags)
|
|
||||||
{
|
|
||||||
void __iomem *mem_base;
|
|
||||||
int pages = size >> PAGE_SHIFT;
|
|
||||||
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
|
|
||||||
|
|
||||||
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
|
|
||||||
goto out;
|
|
||||||
if (!size)
|
|
||||||
goto out;
|
|
||||||
if (dev->dma_mem)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
|
|
||||||
|
|
||||||
mem_base = ioremap(bus_addr, size);
|
|
||||||
if (!mem_base)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
|
|
||||||
if (!dev->dma_mem)
|
|
||||||
goto iounmap_out;
|
|
||||||
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
|
||||||
if (!dev->dma_mem->bitmap)
|
|
||||||
goto free1_out;
|
|
||||||
|
|
||||||
dev->dma_mem->virt_base = mem_base;
|
|
||||||
dev->dma_mem->device_base = device_addr;
|
|
||||||
dev->dma_mem->size = pages;
|
|
||||||
dev->dma_mem->flags = flags;
|
|
||||||
|
|
||||||
if (flags & DMA_MEMORY_MAP)
|
|
||||||
return DMA_MEMORY_MAP;
|
|
||||||
|
|
||||||
return DMA_MEMORY_IO;
|
|
||||||
|
|
||||||
free1_out:
|
|
||||||
kfree(dev->dma_mem);
|
|
||||||
iounmap_out:
|
|
||||||
iounmap(mem_base);
|
|
||||||
out:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(dma_declare_coherent_memory);
|
|
||||||
|
|
||||||
void dma_release_declared_memory(struct device *dev)
|
|
||||||
{
|
|
||||||
struct dma_coherent_mem *mem = dev->dma_mem;
|
|
||||||
|
|
||||||
if(!mem)
|
|
||||||
return;
|
|
||||||
dev->dma_mem = NULL;
|
|
||||||
iounmap(mem->virt_base);
|
|
||||||
kfree(mem->bitmap);
|
|
||||||
kfree(mem);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(dma_release_declared_memory);
|
|
||||||
|
|
||||||
void *dma_mark_declared_memory_occupied(struct device *dev,
|
|
||||||
dma_addr_t device_addr, size_t size)
|
|
||||||
{
|
|
||||||
struct dma_coherent_mem *mem = dev->dma_mem;
|
|
||||||
int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
||||||
int pos, err;
|
|
||||||
|
|
||||||
if (!mem)
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
|
|
||||||
err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
|
|
||||||
if (err != 0)
|
|
||||||
return ERR_PTR(err);
|
|
||||||
return mem->virt_base + (pos << PAGE_SHIFT);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
|
|
||||||
|
|
|
@ -125,9 +125,9 @@ void kvm_arch_hardware_enable(void *garbage)
|
||||||
PAGE_KERNEL));
|
PAGE_KERNEL));
|
||||||
local_irq_save(saved_psr);
|
local_irq_save(saved_psr);
|
||||||
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
|
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
|
||||||
|
local_irq_restore(saved_psr);
|
||||||
if (slot < 0)
|
if (slot < 0)
|
||||||
return;
|
return;
|
||||||
local_irq_restore(saved_psr);
|
|
||||||
|
|
||||||
spin_lock(&vp_lock);
|
spin_lock(&vp_lock);
|
||||||
status = ia64_pal_vp_init_env(kvm_vsa_base ?
|
status = ia64_pal_vp_init_env(kvm_vsa_base ?
|
||||||
|
@ -160,9 +160,9 @@ void kvm_arch_hardware_disable(void *garbage)
|
||||||
|
|
||||||
local_irq_save(saved_psr);
|
local_irq_save(saved_psr);
|
||||||
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
|
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
|
||||||
|
local_irq_restore(saved_psr);
|
||||||
if (slot < 0)
|
if (slot < 0)
|
||||||
return;
|
return;
|
||||||
local_irq_restore(saved_psr);
|
|
||||||
|
|
||||||
status = ia64_pal_vp_exit_env(host_iva);
|
status = ia64_pal_vp_exit_env(host_iva);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -1253,6 +1253,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
|
||||||
uninit:
|
uninit:
|
||||||
kvm_vcpu_uninit(vcpu);
|
kvm_vcpu_uninit(vcpu);
|
||||||
fail:
|
fail:
|
||||||
|
local_irq_restore(psr);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ config PPC
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select HAVE_ARCH_KGDB
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
|
select HAVE_ARCH_TRACEHOOK
|
||||||
select HAVE_LMB
|
select HAVE_LMB
|
||||||
select HAVE_DMA_ATTRS if PPC64
|
select HAVE_DMA_ATTRS if PPC64
|
||||||
select USE_GENERIC_SMP_HELPERS if SMP
|
select USE_GENERIC_SMP_HELPERS if SMP
|
||||||
|
|
|
@ -148,7 +148,7 @@ transfer_to_handler:
|
||||||
/* Check to see if the dbcr0 register is set up to debug. Use the
|
/* Check to see if the dbcr0 register is set up to debug. Use the
|
||||||
internal debug mode bit to do this. */
|
internal debug mode bit to do this. */
|
||||||
lwz r12,THREAD_DBCR0(r12)
|
lwz r12,THREAD_DBCR0(r12)
|
||||||
andis. r12,r12,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
|
andis. r12,r12,DBCR0_IDM@h
|
||||||
beq+ 3f
|
beq+ 3f
|
||||||
/* From user and task is ptraced - load up global dbcr0 */
|
/* From user and task is ptraced - load up global dbcr0 */
|
||||||
li r12,-1 /* clear all pending debug events */
|
li r12,-1 /* clear all pending debug events */
|
||||||
|
@ -292,7 +292,7 @@ syscall_exit_cont:
|
||||||
/* If the process has its own DBCR0 value, load it up. The internal
|
/* If the process has its own DBCR0 value, load it up. The internal
|
||||||
debug mode bit tells us that dbcr0 should be loaded. */
|
debug mode bit tells us that dbcr0 should be loaded. */
|
||||||
lwz r0,THREAD+THREAD_DBCR0(r2)
|
lwz r0,THREAD+THREAD_DBCR0(r2)
|
||||||
andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
|
andis. r10,r0,DBCR0_IDM@h
|
||||||
bnel- load_dbcr0
|
bnel- load_dbcr0
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_44x
|
#ifdef CONFIG_44x
|
||||||
|
@ -343,7 +343,12 @@ syscall_dotrace:
|
||||||
stw r0,_TRAP(r1)
|
stw r0,_TRAP(r1)
|
||||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||||
bl do_syscall_trace_enter
|
bl do_syscall_trace_enter
|
||||||
lwz r0,GPR0(r1) /* Restore original registers */
|
/*
|
||||||
|
* Restore argument registers possibly just changed.
|
||||||
|
* We use the return value of do_syscall_trace_enter
|
||||||
|
* for call number to look up in the table (r0).
|
||||||
|
*/
|
||||||
|
mr r0,r3
|
||||||
lwz r3,GPR3(r1)
|
lwz r3,GPR3(r1)
|
||||||
lwz r4,GPR4(r1)
|
lwz r4,GPR4(r1)
|
||||||
lwz r5,GPR5(r1)
|
lwz r5,GPR5(r1)
|
||||||
|
@ -720,7 +725,7 @@ restore_user:
|
||||||
/* Check whether this process has its own DBCR0 value. The internal
|
/* Check whether this process has its own DBCR0 value. The internal
|
||||||
debug mode bit tells us that dbcr0 should be loaded. */
|
debug mode bit tells us that dbcr0 should be loaded. */
|
||||||
lwz r0,THREAD+THREAD_DBCR0(r2)
|
lwz r0,THREAD+THREAD_DBCR0(r2)
|
||||||
andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
|
andis. r10,r0,DBCR0_IDM@h
|
||||||
bnel- load_dbcr0
|
bnel- load_dbcr0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1055,8 +1060,8 @@ do_user_signal: /* r10 contains MSR_KERNEL here */
|
||||||
SAVE_NVGPRS(r1)
|
SAVE_NVGPRS(r1)
|
||||||
rlwinm r3,r3,0,0,30
|
rlwinm r3,r3,0,0,30
|
||||||
stw r3,_TRAP(r1)
|
stw r3,_TRAP(r1)
|
||||||
2: li r3,0
|
2: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||||
addi r4,r1,STACK_FRAME_OVERHEAD
|
mr r4,r9
|
||||||
bl do_signal
|
bl do_signal
|
||||||
REST_NVGPRS(r1)
|
REST_NVGPRS(r1)
|
||||||
b recheck
|
b recheck
|
||||||
|
|
|
@ -214,7 +214,12 @@ syscall_dotrace:
|
||||||
bl .save_nvgprs
|
bl .save_nvgprs
|
||||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||||
bl .do_syscall_trace_enter
|
bl .do_syscall_trace_enter
|
||||||
ld r0,GPR0(r1) /* Restore original registers */
|
/*
|
||||||
|
* Restore argument registers possibly just changed.
|
||||||
|
* We use the return value of do_syscall_trace_enter
|
||||||
|
* for the call number to look up in the table (r0).
|
||||||
|
*/
|
||||||
|
mr r0,r3
|
||||||
ld r3,GPR3(r1)
|
ld r3,GPR3(r1)
|
||||||
ld r4,GPR4(r1)
|
ld r4,GPR4(r1)
|
||||||
ld r5,GPR5(r1)
|
ld r5,GPR5(r1)
|
||||||
|
@ -638,8 +643,7 @@ user_work:
|
||||||
b .ret_from_except_lite
|
b .ret_from_except_lite
|
||||||
|
|
||||||
1: bl .save_nvgprs
|
1: bl .save_nvgprs
|
||||||
li r3,0
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||||
addi r4,r1,STACK_FRAME_OVERHEAD
|
|
||||||
bl .do_signal
|
bl .do_signal
|
||||||
b .ret_from_except
|
b .ret_from_except
|
||||||
|
|
||||||
|
|
|
@ -493,18 +493,18 @@ static int __init serial_dev_init(void)
|
||||||
device_initcall(serial_dev_init);
|
device_initcall(serial_dev_init);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||||
/*
|
/*
|
||||||
* This is called very early, as part of console_init() (typically just after
|
* This is called very early, as part of console_init() (typically just after
|
||||||
* time_init()). This function is respondible for trying to find a good
|
* time_init()). This function is respondible for trying to find a good
|
||||||
* default console on serial ports. It tries to match the open firmware
|
* default console on serial ports. It tries to match the open firmware
|
||||||
* default output with one of the available serial console drivers, either
|
* default output with one of the available serial console drivers that have
|
||||||
* one of the platform serial ports that have been probed earlier by
|
* been probed earlier by find_legacy_serial_ports()
|
||||||
* find_legacy_serial_ports() or some more platform specific ones.
|
|
||||||
*/
|
*/
|
||||||
static int __init check_legacy_serial_console(void)
|
static int __init check_legacy_serial_console(void)
|
||||||
{
|
{
|
||||||
struct device_node *prom_stdout = NULL;
|
struct device_node *prom_stdout = NULL;
|
||||||
int speed = 0, offset = 0;
|
int i, speed = 0, offset = 0;
|
||||||
const char *name;
|
const char *name;
|
||||||
const u32 *spd;
|
const u32 *spd;
|
||||||
|
|
||||||
|
@ -548,31 +548,20 @@ static int __init check_legacy_serial_console(void)
|
||||||
if (spd)
|
if (spd)
|
||||||
speed = *spd;
|
speed = *spd;
|
||||||
|
|
||||||
if (0)
|
if (strcmp(name, "serial") != 0)
|
||||||
;
|
|
||||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
|
||||||
else if (strcmp(name, "serial") == 0) {
|
|
||||||
int i;
|
|
||||||
/* Look for it in probed array */
|
|
||||||
for (i = 0; i < legacy_serial_count; i++) {
|
|
||||||
if (prom_stdout != legacy_serial_infos[i].np)
|
|
||||||
continue;
|
|
||||||
offset = i;
|
|
||||||
speed = legacy_serial_infos[i].speed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i >= legacy_serial_count)
|
|
||||||
goto not_found;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
|
||||||
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
|
|
||||||
else if (strcmp(name, "ch-a") == 0)
|
|
||||||
offset = 0;
|
|
||||||
else if (strcmp(name, "ch-b") == 0)
|
|
||||||
offset = 1;
|
|
||||||
#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
|
|
||||||
else
|
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
|
||||||
|
/* Look for it in probed array */
|
||||||
|
for (i = 0; i < legacy_serial_count; i++) {
|
||||||
|
if (prom_stdout != legacy_serial_infos[i].np)
|
||||||
|
continue;
|
||||||
|
offset = i;
|
||||||
|
speed = legacy_serial_infos[i].speed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= legacy_serial_count)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
of_node_put(prom_stdout);
|
of_node_put(prom_stdout);
|
||||||
|
|
||||||
DBG("Found serial console at ttyS%d\n", offset);
|
DBG("Found serial console at ttyS%d\n", offset);
|
||||||
|
@ -591,3 +580,4 @@ static int __init check_legacy_serial_console(void)
|
||||||
}
|
}
|
||||||
console_initcall(check_legacy_serial_console);
|
console_initcall(check_legacy_serial_console);
|
||||||
|
|
||||||
|
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
||||||
|
|
|
@ -254,7 +254,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Clear the DAC and struct entries. One shot trigger */
|
/* Clear the DAC and struct entries. One shot trigger */
|
||||||
#if (defined(CONFIG_44x) || defined(CONFIG_BOOKE))
|
#if defined(CONFIG_BOOKE)
|
||||||
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
|
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
|
||||||
| DBCR0_IDM));
|
| DBCR0_IDM));
|
||||||
#endif
|
#endif
|
||||||
|
@ -286,7 +286,7 @@ int set_dabr(unsigned long dabr)
|
||||||
mtspr(SPRN_DABR, dabr);
|
mtspr(SPRN_DABR, dabr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
mtspr(SPRN_DAC1, dabr);
|
mtspr(SPRN_DAC1, dabr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
||||||
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
|
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
|
||||||
set_dabr(new->thread.dabr);
|
set_dabr(new->thread.dabr);
|
||||||
|
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
/* If new thread DAC (HW breakpoint) is the same then leave it */
|
/* If new thread DAC (HW breakpoint) is the same then leave it */
|
||||||
if (new->thread.dabr)
|
if (new->thread.dabr)
|
||||||
set_dabr(new->thread.dabr);
|
set_dabr(new->thread.dabr);
|
||||||
|
@ -568,7 +568,7 @@ void flush_thread(void)
|
||||||
current->thread.dabr = 0;
|
current->thread.dabr = 0;
|
||||||
set_dabr(0);
|
set_dabr(0);
|
||||||
|
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
|
current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,8 +205,6 @@ static int __initdata mem_reserve_cnt;
|
||||||
static cell_t __initdata regbuf[1024];
|
static cell_t __initdata regbuf[1024];
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CPU_THREADS 2
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error results ... some OF calls will return "-1" on error, some
|
* Error results ... some OF calls will return "-1" on error, some
|
||||||
* will return 0, some will return either. To simplify, here are
|
* will return 0, some will return either. To simplify, here are
|
||||||
|
@ -1339,10 +1337,6 @@ static void __init prom_hold_cpus(void)
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
phandle node;
|
phandle node;
|
||||||
char type[64];
|
char type[64];
|
||||||
int cpuid = 0;
|
|
||||||
unsigned int interrupt_server[MAX_CPU_THREADS];
|
|
||||||
unsigned int cpu_threads, hw_cpu_num;
|
|
||||||
int propsize;
|
|
||||||
struct prom_t *_prom = &RELOC(prom);
|
struct prom_t *_prom = &RELOC(prom);
|
||||||
unsigned long *spinloop
|
unsigned long *spinloop
|
||||||
= (void *) LOW_ADDR(__secondary_hold_spinloop);
|
= (void *) LOW_ADDR(__secondary_hold_spinloop);
|
||||||
|
@ -1386,7 +1380,6 @@ static void __init prom_hold_cpus(void)
|
||||||
reg = -1;
|
reg = -1;
|
||||||
prom_getprop(node, "reg", ®, sizeof(reg));
|
prom_getprop(node, "reg", ®, sizeof(reg));
|
||||||
|
|
||||||
prom_debug("\ncpuid = 0x%x\n", cpuid);
|
|
||||||
prom_debug("cpu hw idx = 0x%x\n", reg);
|
prom_debug("cpu hw idx = 0x%x\n", reg);
|
||||||
|
|
||||||
/* Init the acknowledge var which will be reset by
|
/* Init the acknowledge var which will be reset by
|
||||||
|
@ -1395,28 +1388,9 @@ static void __init prom_hold_cpus(void)
|
||||||
*/
|
*/
|
||||||
*acknowledge = (unsigned long)-1;
|
*acknowledge = (unsigned long)-1;
|
||||||
|
|
||||||
propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
|
if (reg != _prom->cpu) {
|
||||||
&interrupt_server,
|
|
||||||
sizeof(interrupt_server));
|
|
||||||
if (propsize < 0) {
|
|
||||||
/* no property. old hardware has no SMT */
|
|
||||||
cpu_threads = 1;
|
|
||||||
interrupt_server[0] = reg; /* fake it with phys id */
|
|
||||||
} else {
|
|
||||||
/* We have a threaded processor */
|
|
||||||
cpu_threads = propsize / sizeof(u32);
|
|
||||||
if (cpu_threads > MAX_CPU_THREADS) {
|
|
||||||
prom_printf("SMT: too many threads!\n"
|
|
||||||
"SMT: found %x, max is %x\n",
|
|
||||||
cpu_threads, MAX_CPU_THREADS);
|
|
||||||
cpu_threads = 1; /* ToDo: panic? */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hw_cpu_num = interrupt_server[0];
|
|
||||||
if (hw_cpu_num != _prom->cpu) {
|
|
||||||
/* Primary Thread of non-boot cpu */
|
/* Primary Thread of non-boot cpu */
|
||||||
prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
|
prom_printf("starting cpu hw idx %x... ", reg);
|
||||||
call_prom("start-cpu", 3, 0, node,
|
call_prom("start-cpu", 3, 0, node,
|
||||||
secondary_hold, reg);
|
secondary_hold, reg);
|
||||||
|
|
||||||
|
@ -1431,17 +1405,10 @@ static void __init prom_hold_cpus(void)
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
else
|
else
|
||||||
prom_printf("%x : boot cpu %x\n", cpuid, reg);
|
prom_printf("boot cpu hw idx %x\n", reg);
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
/* Reserve cpu #s for secondary threads. They start later. */
|
|
||||||
cpuid += cpu_threads;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpuid > NR_CPUS)
|
|
||||||
prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
|
|
||||||
") exceeded: ignoring extras\n");
|
|
||||||
|
|
||||||
prom_debug("prom_hold_cpus: end...\n");
|
prom_debug("prom_hold_cpus: end...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/regset.h>
|
#include <linux/regset.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/user.h>
|
#include <linux/user.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
@ -717,7 +718,7 @@ void user_disable_single_step(struct task_struct *task)
|
||||||
struct pt_regs *regs = task->thread.regs;
|
struct pt_regs *regs = task->thread.regs;
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
/* If DAC then do not single step, skip */
|
/* If DAC then do not single step, skip */
|
||||||
if (task->thread.dabr)
|
if (task->thread.dabr)
|
||||||
return;
|
return;
|
||||||
|
@ -744,10 +745,11 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
||||||
if (addr > 0)
|
if (addr > 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* The bottom 3 bits in dabr are flags */
|
||||||
if ((data & ~0x7UL) >= TASK_SIZE)
|
if ((data & ~0x7UL) >= TASK_SIZE)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#ifndef CONFIG_BOOKE
|
||||||
|
|
||||||
/* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
|
/* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
|
||||||
* It was assumed, on previous implementations, that 3 bits were
|
* It was assumed, on previous implementations, that 3 bits were
|
||||||
|
@ -769,7 +771,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
||||||
task->thread.dabr = data;
|
task->thread.dabr = data;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
|
|
||||||
/* As described above, it was assumed 3 bits were passed with the data
|
/* As described above, it was assumed 3 bits were passed with the data
|
||||||
* address, but we will assume only the mode bits will be passed
|
* address, but we will assume only the mode bits will be passed
|
||||||
|
@ -1013,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_syscall_trace(void)
|
/*
|
||||||
|
* We must return the syscall number to actually look up in the table.
|
||||||
|
* This can be -1L to skip running any syscall at all.
|
||||||
|
*/
|
||||||
|
long do_syscall_trace_enter(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
long ret = 0;
|
||||||
between a syscall stop and SIGTRAP delivery */
|
|
||||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
|
||||||
? 0x80 : 0));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* this isn't the same as continuing with a signal, but it will do
|
|
||||||
* for normal use. strace only continues with a signal if the
|
|
||||||
* stopping signal is not SIGTRAP. -brl
|
|
||||||
*/
|
|
||||||
if (current->exit_code) {
|
|
||||||
send_sig(current->exit_code, current, 1);
|
|
||||||
current->exit_code = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_syscall_trace_enter(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
secure_computing(regs->gpr[0]);
|
secure_computing(regs->gpr[0]);
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||||
&& (current->ptrace & PT_PTRACED))
|
tracehook_report_syscall_entry(regs))
|
||||||
do_syscall_trace();
|
/*
|
||||||
|
* Tracing decided this syscall should not happen.
|
||||||
|
* We'll return a bogus call number to get an ENOSYS
|
||||||
|
* error, but leave the original number in regs->gpr[0].
|
||||||
|
*/
|
||||||
|
ret = -1L;
|
||||||
|
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context)) {
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
|
@ -1055,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
|
||||||
regs->gpr[5] & 0xffffffff,
|
regs->gpr[5] & 0xffffffff,
|
||||||
regs->gpr[6] & 0xffffffff);
|
regs->gpr[6] & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret ?: regs->gpr[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_syscall_trace_leave(struct pt_regs *regs)
|
void do_syscall_trace_leave(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
int step;
|
||||||
|
|
||||||
if (unlikely(current->audit_context))
|
if (unlikely(current->audit_context))
|
||||||
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
|
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
|
||||||
regs->result);
|
regs->result);
|
||||||
|
|
||||||
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|
step = test_thread_flag(TIF_SINGLESTEP);
|
||||||
|| test_thread_flag(TIF_SINGLESTEP))
|
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
&& (current->ptrace & PT_PTRACED))
|
tracehook_report_syscall_exit(regs, step);
|
||||||
do_syscall_trace();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,7 +367,6 @@ static void __init cpu_init_thread_core_maps(int tpc)
|
||||||
* setup_cpu_maps - initialize the following cpu maps:
|
* setup_cpu_maps - initialize the following cpu maps:
|
||||||
* cpu_possible_map
|
* cpu_possible_map
|
||||||
* cpu_present_map
|
* cpu_present_map
|
||||||
* cpu_sibling_map
|
|
||||||
*
|
*
|
||||||
* Having the possible map set up early allows us to restrict allocations
|
* Having the possible map set up early allows us to restrict allocations
|
||||||
* of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
|
* of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
|
||||||
|
@ -475,29 +474,6 @@ void __init smp_setup_cpu_maps(void)
|
||||||
*/
|
*/
|
||||||
cpu_init_thread_core_maps(nthreads);
|
cpu_init_thread_core_maps(nthreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Being that cpu_sibling_map is now a per_cpu array, then it cannot
|
|
||||||
* be initialized until the per_cpu areas have been created. This
|
|
||||||
* function is now called from setup_per_cpu_areas().
|
|
||||||
*/
|
|
||||||
void __init smp_setup_cpu_sibling_map(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
int i, cpu, base;
|
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
|
||||||
DBG("Sibling map for CPU %d:", cpu);
|
|
||||||
base = cpu_first_thread_in_core(cpu);
|
|
||||||
for (i = 0; i < threads_per_core; i++) {
|
|
||||||
cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
|
|
||||||
DBG(" %d", base + i);
|
|
||||||
}
|
|
||||||
DBG("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_PPC64 */
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
#ifdef CONFIG_PCSPKR_PLATFORM
|
#ifdef CONFIG_PCSPKR_PLATFORM
|
||||||
|
|
|
@ -611,9 +611,6 @@ void __init setup_per_cpu_areas(void)
|
||||||
paca[i].data_offset = ptr - __per_cpu_start;
|
paca[i].data_offset = ptr - __per_cpu_start;
|
||||||
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that per_cpu is setup, initialize cpu_sibling_map */
|
|
||||||
smp_setup_cpu_sibling_map();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
* this archive for more details.
|
* this archive for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ptrace.h>
|
#include <linux/tracehook.h>
|
||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
@ -112,7 +112,7 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
|
@ -147,7 +147,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||||
*/
|
*/
|
||||||
if (current->thread.dabr) {
|
if (current->thread.dabr) {
|
||||||
set_dabr(current->thread.dabr);
|
set_dabr(current->thread.dabr);
|
||||||
#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_BOOKE)
|
||||||
mtspr(SPRN_DBCR0, current->thread.dbcr0);
|
mtspr(SPRN_DBCR0, current->thread.dbcr0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -177,11 +177,28 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||||
* its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
|
* its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
|
||||||
*/
|
*/
|
||||||
current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
|
current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let tracing know that we've done the handler setup.
|
||||||
|
*/
|
||||||
|
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||||
|
test_thread_flag(TIF_SINGLESTEP));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_signal(struct pt_regs *regs, unsigned long thread_info_flags)
|
||||||
|
{
|
||||||
|
if (thread_info_flags & _TIF_SIGPENDING)
|
||||||
|
do_signal_pending(NULL, regs);
|
||||||
|
|
||||||
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||||
unsigned long r5, unsigned long r6, unsigned long r7,
|
unsigned long r5, unsigned long r6, unsigned long r7,
|
||||||
unsigned long r8, struct pt_regs *regs)
|
unsigned long r8, struct pt_regs *regs)
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/time.h>
|
#include <asm/time.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
|
#include <asm/cputhreads.h>
|
||||||
#include <asm/cputable.h>
|
#include <asm/cputable.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/mpic.h>
|
#include <asm/mpic.h>
|
||||||
|
@ -62,10 +63,12 @@ struct thread_info *secondary_ti;
|
||||||
cpumask_t cpu_possible_map = CPU_MASK_NONE;
|
cpumask_t cpu_possible_map = CPU_MASK_NONE;
|
||||||
cpumask_t cpu_online_map = CPU_MASK_NONE;
|
cpumask_t cpu_online_map = CPU_MASK_NONE;
|
||||||
DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
|
DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
|
||||||
|
DEFINE_PER_CPU(cpumask_t, cpu_core_map) = CPU_MASK_NONE;
|
||||||
|
|
||||||
EXPORT_SYMBOL(cpu_online_map);
|
EXPORT_SYMBOL(cpu_online_map);
|
||||||
EXPORT_SYMBOL(cpu_possible_map);
|
EXPORT_SYMBOL(cpu_possible_map);
|
||||||
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
||||||
|
EXPORT_PER_CPU_SYMBOL(cpu_core_map);
|
||||||
|
|
||||||
/* SMP operations for this machine */
|
/* SMP operations for this machine */
|
||||||
struct smp_ops_t *smp_ops;
|
struct smp_ops_t *smp_ops;
|
||||||
|
@ -228,6 +231,8 @@ void __devinit smp_prepare_boot_cpu(void)
|
||||||
BUG_ON(smp_processor_id() != boot_cpuid);
|
BUG_ON(smp_processor_id() != boot_cpuid);
|
||||||
|
|
||||||
cpu_set(boot_cpuid, cpu_online_map);
|
cpu_set(boot_cpuid, cpu_online_map);
|
||||||
|
cpu_set(boot_cpuid, per_cpu(cpu_sibling_map, boot_cpuid));
|
||||||
|
cpu_set(boot_cpuid, per_cpu(cpu_core_map, boot_cpuid));
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
paca[boot_cpuid].__current = current;
|
paca[boot_cpuid].__current = current;
|
||||||
#endif
|
#endif
|
||||||
|
@ -375,11 +380,60 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the value of the reg property corresponding to the given
|
||||||
|
* logical cpu.
|
||||||
|
*/
|
||||||
|
int cpu_to_core_id(int cpu)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
const int *reg;
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
np = of_get_cpu_node(cpu, NULL);
|
||||||
|
if (!np)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
reg = of_get_property(np, "reg", NULL);
|
||||||
|
if (!reg)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
id = *reg;
|
||||||
|
out:
|
||||||
|
of_node_put(np);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be called when no change can occur to cpu_present_map,
|
||||||
|
* i.e. during cpu online or offline.
|
||||||
|
*/
|
||||||
|
static struct device_node *cpu_to_l2cache(int cpu)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
const phandle *php;
|
||||||
|
phandle ph;
|
||||||
|
|
||||||
|
if (!cpu_present(cpu))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
np = of_get_cpu_node(cpu, NULL);
|
||||||
|
if (np == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
php = of_get_property(np, "l2-cache", NULL);
|
||||||
|
if (php == NULL)
|
||||||
|
return NULL;
|
||||||
|
ph = *php;
|
||||||
|
of_node_put(np);
|
||||||
|
|
||||||
|
return of_find_node_by_phandle(ph);
|
||||||
|
}
|
||||||
|
|
||||||
/* Activate a secondary processor. */
|
/* Activate a secondary processor. */
|
||||||
int __devinit start_secondary(void *unused)
|
int __devinit start_secondary(void *unused)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
|
struct device_node *l2_cache;
|
||||||
|
int i, base;
|
||||||
|
|
||||||
atomic_inc(&init_mm.mm_count);
|
atomic_inc(&init_mm.mm_count);
|
||||||
current->active_mm = &init_mm;
|
current->active_mm = &init_mm;
|
||||||
|
@ -400,6 +454,33 @@ int __devinit start_secondary(void *unused)
|
||||||
|
|
||||||
ipi_call_lock();
|
ipi_call_lock();
|
||||||
cpu_set(cpu, cpu_online_map);
|
cpu_set(cpu, cpu_online_map);
|
||||||
|
/* Update sibling maps */
|
||||||
|
base = cpu_first_thread_in_core(cpu);
|
||||||
|
for (i = 0; i < threads_per_core; i++) {
|
||||||
|
if (cpu_is_offline(base + i))
|
||||||
|
continue;
|
||||||
|
cpu_set(cpu, per_cpu(cpu_sibling_map, base + i));
|
||||||
|
cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
|
||||||
|
|
||||||
|
/* cpu_core_map should be a superset of
|
||||||
|
* cpu_sibling_map even if we don't have cache
|
||||||
|
* information, so update the former here, too.
|
||||||
|
*/
|
||||||
|
cpu_set(cpu, per_cpu(cpu_core_map, base +i));
|
||||||
|
cpu_set(base + i, per_cpu(cpu_core_map, cpu));
|
||||||
|
}
|
||||||
|
l2_cache = cpu_to_l2cache(cpu);
|
||||||
|
for_each_online_cpu(i) {
|
||||||
|
struct device_node *np = cpu_to_l2cache(i);
|
||||||
|
if (!np)
|
||||||
|
continue;
|
||||||
|
if (np == l2_cache) {
|
||||||
|
cpu_set(cpu, per_cpu(cpu_core_map, i));
|
||||||
|
cpu_set(i, per_cpu(cpu_core_map, cpu));
|
||||||
|
}
|
||||||
|
of_node_put(np);
|
||||||
|
}
|
||||||
|
of_node_put(l2_cache);
|
||||||
ipi_call_unlock();
|
ipi_call_unlock();
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
@ -437,10 +518,42 @@ void __init smp_cpus_done(unsigned int max_cpus)
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
int __cpu_disable(void)
|
int __cpu_disable(void)
|
||||||
{
|
{
|
||||||
if (smp_ops->cpu_disable)
|
struct device_node *l2_cache;
|
||||||
return smp_ops->cpu_disable();
|
int cpu = smp_processor_id();
|
||||||
|
int base, i;
|
||||||
|
int err;
|
||||||
|
|
||||||
return -ENOSYS;
|
if (!smp_ops->cpu_disable)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
err = smp_ops->cpu_disable();
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Update sibling maps */
|
||||||
|
base = cpu_first_thread_in_core(cpu);
|
||||||
|
for (i = 0; i < threads_per_core; i++) {
|
||||||
|
cpu_clear(cpu, per_cpu(cpu_sibling_map, base + i));
|
||||||
|
cpu_clear(base + i, per_cpu(cpu_sibling_map, cpu));
|
||||||
|
cpu_clear(cpu, per_cpu(cpu_core_map, base +i));
|
||||||
|
cpu_clear(base + i, per_cpu(cpu_core_map, cpu));
|
||||||
|
}
|
||||||
|
|
||||||
|
l2_cache = cpu_to_l2cache(cpu);
|
||||||
|
for_each_present_cpu(i) {
|
||||||
|
struct device_node *np = cpu_to_l2cache(i);
|
||||||
|
if (!np)
|
||||||
|
continue;
|
||||||
|
if (np == l2_cache) {
|
||||||
|
cpu_clear(cpu, per_cpu(cpu_core_map, i));
|
||||||
|
cpu_clear(i, per_cpu(cpu_core_map, cpu));
|
||||||
|
}
|
||||||
|
of_node_put(np);
|
||||||
|
}
|
||||||
|
of_node_put(l2_cache);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpu_die(unsigned int cpu)
|
void __cpu_die(unsigned int cpu)
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/stacktrace.h>
|
#include <linux/stacktrace.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct cpu, cpu_devices);
|
static DEFINE_PER_CPU(struct cpu, cpu_devices);
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(struct kobject *, cache_toplevel);
|
||||||
|
|
||||||
/* SMT stuff */
|
/* SMT stuff */
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||||
|
@ -297,8 +299,289 @@ static struct sysdev_attribute pa6t_attrs[] = {
|
||||||
#endif /* CONFIG_DEBUG_KERNEL */
|
#endif /* CONFIG_DEBUG_KERNEL */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cache_desc {
|
||||||
|
struct kobject kobj;
|
||||||
|
struct cache_desc *next;
|
||||||
|
const char *type; /* Instruction, Data, or Unified */
|
||||||
|
u32 size; /* total cache size in KB */
|
||||||
|
u32 line_size; /* in bytes */
|
||||||
|
u32 nr_sets; /* number of sets */
|
||||||
|
u32 level; /* e.g. 1, 2, 3... */
|
||||||
|
u32 associativity; /* e.g. 8-way... 0 is fully associative */
|
||||||
|
};
|
||||||
|
|
||||||
static void register_cpu_online(unsigned int cpu)
|
DEFINE_PER_CPU(struct cache_desc *, cache_desc);
|
||||||
|
|
||||||
|
static struct cache_desc *kobj_to_cache_desc(struct kobject *k)
|
||||||
|
{
|
||||||
|
return container_of(k, struct cache_desc, kobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cache_desc_release(struct kobject *k)
|
||||||
|
{
|
||||||
|
struct cache_desc *desc = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
pr_debug("%s: releasing %s\n", __func__, kobject_name(k));
|
||||||
|
|
||||||
|
if (desc->next)
|
||||||
|
kobject_put(&desc->next->kobj);
|
||||||
|
|
||||||
|
kfree(kobj_to_cache_desc(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cache_desc_show(struct kobject *k, struct attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct kobj_attribute *kobj_attr;
|
||||||
|
|
||||||
|
kobj_attr = container_of(attr, struct kobj_attribute, attr);
|
||||||
|
|
||||||
|
return kobj_attr->show(k, kobj_attr, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sysfs_ops cache_desc_sysfs_ops = {
|
||||||
|
.show = cache_desc_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct kobj_type cache_desc_type = {
|
||||||
|
.release = cache_desc_release,
|
||||||
|
.sysfs_ops = &cache_desc_sysfs_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t cache_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%uK\n", cache->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_size_attr =
|
||||||
|
__ATTR(size, 0444, cache_size_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t cache_line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", cache->line_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_line_size_attr =
|
||||||
|
__ATTR(coherency_line_size, 0444, cache_line_size_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t cache_nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", cache->nr_sets);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_nr_sets_attr =
|
||||||
|
__ATTR(number_of_sets, 0444, cache_nr_sets_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t cache_type_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%s\n", cache->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_type_attr =
|
||||||
|
__ATTR(type, 0444, cache_type_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t cache_level_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", cache->level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_level_attr =
|
||||||
|
__ATTR(level, 0444, cache_level_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t cache_assoc_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct cache_desc *cache = kobj_to_cache_desc(k);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", cache->associativity);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cache_assoc_attr =
|
||||||
|
__ATTR(ways_of_associativity, 0444, cache_assoc_show, NULL);
|
||||||
|
|
||||||
|
struct cache_desc_info {
|
||||||
|
const char *type;
|
||||||
|
const char *size_prop;
|
||||||
|
const char *line_size_prop;
|
||||||
|
const char *nr_sets_prop;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* PowerPC Processor binding says the [di]-cache-* must be equal on
|
||||||
|
* unified caches, so just use d-cache properties. */
|
||||||
|
static struct cache_desc_info ucache_info = {
|
||||||
|
.type = "Unified",
|
||||||
|
.size_prop = "d-cache-size",
|
||||||
|
.line_size_prop = "d-cache-line-size",
|
||||||
|
.nr_sets_prop = "d-cache-sets",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cache_desc_info dcache_info = {
|
||||||
|
.type = "Data",
|
||||||
|
.size_prop = "d-cache-size",
|
||||||
|
.line_size_prop = "d-cache-line-size",
|
||||||
|
.nr_sets_prop = "d-cache-sets",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cache_desc_info icache_info = {
|
||||||
|
.type = "Instruction",
|
||||||
|
.size_prop = "i-cache-size",
|
||||||
|
.line_size_prop = "i-cache-line-size",
|
||||||
|
.nr_sets_prop = "i-cache-sets",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cache_desc * __cpuinit create_cache_desc(struct device_node *np, struct kobject *parent, int index, int level, struct cache_desc_info *info)
|
||||||
|
{
|
||||||
|
const u32 *cache_line_size;
|
||||||
|
struct cache_desc *new;
|
||||||
|
const u32 *cache_size;
|
||||||
|
const u32 *nr_sets;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
new = kzalloc(sizeof(*new), GFP_KERNEL);
|
||||||
|
if (!new)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rc = kobject_init_and_add(&new->kobj, &cache_desc_type, parent,
|
||||||
|
"index%d", index);
|
||||||
|
if (rc)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* type */
|
||||||
|
new->type = info->type;
|
||||||
|
rc = sysfs_create_file(&new->kobj, &cache_type_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
|
||||||
|
/* level */
|
||||||
|
new->level = level;
|
||||||
|
rc = sysfs_create_file(&new->kobj, &cache_level_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
|
||||||
|
/* size */
|
||||||
|
cache_size = of_get_property(np, info->size_prop, NULL);
|
||||||
|
if (cache_size) {
|
||||||
|
new->size = *cache_size / 1024;
|
||||||
|
rc = sysfs_create_file(&new->kobj,
|
||||||
|
&cache_size_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* coherency_line_size */
|
||||||
|
cache_line_size = of_get_property(np, info->line_size_prop, NULL);
|
||||||
|
if (cache_line_size) {
|
||||||
|
new->line_size = *cache_line_size;
|
||||||
|
rc = sysfs_create_file(&new->kobj,
|
||||||
|
&cache_line_size_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* number_of_sets */
|
||||||
|
nr_sets = of_get_property(np, info->nr_sets_prop, NULL);
|
||||||
|
if (nr_sets) {
|
||||||
|
new->nr_sets = *nr_sets;
|
||||||
|
rc = sysfs_create_file(&new->kobj,
|
||||||
|
&cache_nr_sets_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ways_of_associativity */
|
||||||
|
if (new->nr_sets == 1) {
|
||||||
|
/* fully associative */
|
||||||
|
new->associativity = 0;
|
||||||
|
goto create_assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new->nr_sets && new->size && new->line_size) {
|
||||||
|
/* If we have values for all of these we can derive
|
||||||
|
* the associativity. */
|
||||||
|
new->associativity =
|
||||||
|
((new->size * 1024) / new->nr_sets) / new->line_size;
|
||||||
|
create_assoc:
|
||||||
|
rc = sysfs_create_file(&new->kobj,
|
||||||
|
&cache_assoc_attr.attr);
|
||||||
|
WARN_ON(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
err:
|
||||||
|
kfree(new);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cache_is_unified(struct device_node *np)
|
||||||
|
{
|
||||||
|
return of_get_property(np, "cache-unified", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cache_desc * __cpuinit create_cache_index_info(struct device_node *np, struct kobject *parent, int index, int level)
|
||||||
|
{
|
||||||
|
const phandle *next_cache_phandle;
|
||||||
|
struct device_node *next_cache;
|
||||||
|
struct cache_desc *new, **end;
|
||||||
|
|
||||||
|
pr_debug("%s(node = %s, index = %d)\n", __func__, np->full_name, index);
|
||||||
|
|
||||||
|
if (cache_is_unified(np)) {
|
||||||
|
new = create_cache_desc(np, parent, index, level,
|
||||||
|
&ucache_info);
|
||||||
|
} else {
|
||||||
|
new = create_cache_desc(np, parent, index, level,
|
||||||
|
&dcache_info);
|
||||||
|
if (new) {
|
||||||
|
index++;
|
||||||
|
new->next = create_cache_desc(np, parent, index, level,
|
||||||
|
&icache_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!new)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
end = &new->next;
|
||||||
|
while (*end)
|
||||||
|
end = &(*end)->next;
|
||||||
|
|
||||||
|
next_cache_phandle = of_get_property(np, "l2-cache", NULL);
|
||||||
|
if (!next_cache_phandle)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
next_cache = of_find_node_by_phandle(*next_cache_phandle);
|
||||||
|
if (!next_cache)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*end = create_cache_index_info(next_cache, parent, ++index, ++level);
|
||||||
|
|
||||||
|
of_node_put(next_cache);
|
||||||
|
out:
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cpuinit create_cache_info(struct sys_device *sysdev)
|
||||||
|
{
|
||||||
|
struct kobject *cache_toplevel;
|
||||||
|
struct device_node *np = NULL;
|
||||||
|
int cpu = sysdev->id;
|
||||||
|
|
||||||
|
cache_toplevel = kobject_create_and_add("cache", &sysdev->kobj);
|
||||||
|
if (!cache_toplevel)
|
||||||
|
return;
|
||||||
|
per_cpu(cache_toplevel, cpu) = cache_toplevel;
|
||||||
|
np = of_get_cpu_node(cpu, NULL);
|
||||||
|
if (np != NULL) {
|
||||||
|
per_cpu(cache_desc, cpu) =
|
||||||
|
create_cache_index_info(np, cache_toplevel, 0, 1);
|
||||||
|
of_node_put(np);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cpuinit register_cpu_online(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
||||||
struct sys_device *s = &c->sysdev;
|
struct sys_device *s = &c->sysdev;
|
||||||
|
@ -346,9 +629,33 @@ static void register_cpu_online(unsigned int cpu)
|
||||||
|
|
||||||
if (cpu_has_feature(CPU_FTR_DSCR))
|
if (cpu_has_feature(CPU_FTR_DSCR))
|
||||||
sysdev_create_file(s, &attr_dscr);
|
sysdev_create_file(s, &attr_dscr);
|
||||||
|
|
||||||
|
create_cache_info(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
static void remove_cache_info(struct sys_device *sysdev)
|
||||||
|
{
|
||||||
|
struct kobject *cache_toplevel;
|
||||||
|
struct cache_desc *cache_desc;
|
||||||
|
int cpu = sysdev->id;
|
||||||
|
|
||||||
|
cache_desc = per_cpu(cache_desc, cpu);
|
||||||
|
if (cache_desc != NULL) {
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_size_attr.attr);
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_line_size_attr.attr);
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_type_attr.attr);
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_level_attr.attr);
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_nr_sets_attr.attr);
|
||||||
|
sysfs_remove_file(&cache_desc->kobj, &cache_assoc_attr.attr);
|
||||||
|
|
||||||
|
kobject_put(&cache_desc->kobj);
|
||||||
|
}
|
||||||
|
cache_toplevel = per_cpu(cache_toplevel, cpu);
|
||||||
|
if (cache_toplevel != NULL)
|
||||||
|
kobject_put(cache_toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
static void unregister_cpu_online(unsigned int cpu)
|
static void unregister_cpu_online(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
||||||
|
@ -399,6 +706,8 @@ static void unregister_cpu_online(unsigned int cpu)
|
||||||
|
|
||||||
if (cpu_has_feature(CPU_FTR_DSCR))
|
if (cpu_has_feature(CPU_FTR_DSCR))
|
||||||
sysdev_remove_file(s, &attr_dscr);
|
sysdev_remove_file(s, &attr_dscr);
|
||||||
|
|
||||||
|
remove_cache_info(s);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HOTPLUG_CPU */
|
#endif /* CONFIG_HOTPLUG_CPU */
|
||||||
|
|
||||||
|
|
|
@ -530,7 +530,7 @@ static dma_addr_t vio_dma_iommu_map_single(struct device *dev, void *vaddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs);
|
ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs);
|
||||||
if (unlikely(dma_mapping_error(ret))) {
|
if (unlikely(dma_mapping_error(dev, ret))) {
|
||||||
vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
|
vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
|
||||||
atomic_inc(&viodev->cmo.allocs_failed);
|
atomic_inc(&viodev->cmo.allocs_failed);
|
||||||
}
|
}
|
||||||
|
@ -1031,8 +1031,8 @@ void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
|
||||||
static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
|
static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
|
||||||
static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
|
static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
|
||||||
static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
|
static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
|
||||||
static void vio_cmo_bus_init() {}
|
static void vio_cmo_bus_init(void) {}
|
||||||
static void vio_cmo_sysfs_init() { }
|
static void vio_cmo_sysfs_init(void) { }
|
||||||
#endif /* CONFIG_PPC_SMLPAR */
|
#endif /* CONFIG_PPC_SMLPAR */
|
||||||
EXPORT_SYMBOL(vio_cmo_entitlement_update);
|
EXPORT_SYMBOL(vio_cmo_entitlement_update);
|
||||||
EXPORT_SYMBOL(vio_cmo_set_dev_desired);
|
EXPORT_SYMBOL(vio_cmo_set_dev_desired);
|
||||||
|
|
|
@ -177,7 +177,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
|
||||||
vcpu->arch.msr & MSR_PR);
|
vcpu->arch.msr & MSR_PR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
|
void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||||
|
gva_t eend, u32 asid)
|
||||||
{
|
{
|
||||||
unsigned int pid = asid & 0xff;
|
unsigned int pid = asid & 0xff;
|
||||||
int i;
|
int i;
|
||||||
|
@ -191,7 +192,7 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
|
||||||
if (!get_tlb_v(stlbe))
|
if (!get_tlb_v(stlbe))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (eaddr < get_tlb_eaddr(stlbe))
|
if (eend < get_tlb_eaddr(stlbe))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (eaddr > get_tlb_end(stlbe))
|
if (eaddr > get_tlb_end(stlbe))
|
||||||
|
|
|
@ -137,7 +137,7 @@ static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
|
||||||
if (tlbe->word0 & PPC44x_TLB_VALID) {
|
if (tlbe->word0 & PPC44x_TLB_VALID) {
|
||||||
eaddr = get_tlb_eaddr(tlbe);
|
eaddr = get_tlb_eaddr(tlbe);
|
||||||
asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
|
asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
|
||||||
kvmppc_mmu_invalidate(vcpu, eaddr, asid);
|
kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ws) {
|
switch (ws) {
|
||||||
|
|
|
@ -736,14 +736,21 @@ static int __init hugetlbpage_init(void)
|
||||||
|
|
||||||
if (!cpu_has_feature(CPU_FTR_16M_PAGE))
|
if (!cpu_has_feature(CPU_FTR_16M_PAGE))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE
|
/* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE
|
||||||
* and adjust PTE_NONCACHE_NUM if the number of supported huge page
|
* and adjust PTE_NONCACHE_NUM if the number of supported huge page
|
||||||
* sizes changes.
|
* sizes changes.
|
||||||
*/
|
*/
|
||||||
set_huge_psize(MMU_PAGE_16M);
|
set_huge_psize(MMU_PAGE_16M);
|
||||||
set_huge_psize(MMU_PAGE_64K);
|
|
||||||
set_huge_psize(MMU_PAGE_16G);
|
set_huge_psize(MMU_PAGE_16G);
|
||||||
|
|
||||||
|
/* Temporarily disable support for 64K huge pages when 64K SPU local
|
||||||
|
* store support is enabled as the current implementation conflicts.
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_SPU_FS_64K_LS
|
||||||
|
set_huge_psize(MMU_PAGE_64K);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
|
for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
|
||||||
if (mmu_huge_psizes[psize]) {
|
if (mmu_huge_psizes[psize]) {
|
||||||
huge_pgtable_cache(psize) = kmem_cache_create(
|
huge_pgtable_cache(psize) = kmem_cache_create(
|
||||||
|
|
|
@ -541,6 +541,78 @@ static int __init pmac_declare_of_platform_devices(void)
|
||||||
}
|
}
|
||||||
machine_device_initcall(powermac, pmac_declare_of_platform_devices);
|
machine_device_initcall(powermac, pmac_declare_of_platform_devices);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
|
||||||
|
/*
|
||||||
|
* This is called very early, as part of console_init() (typically just after
|
||||||
|
* time_init()). This function is respondible for trying to find a good
|
||||||
|
* default console on serial ports. It tries to match the open firmware
|
||||||
|
* default output with one of the available serial console drivers.
|
||||||
|
*/
|
||||||
|
static int __init check_pmac_serial_console(void)
|
||||||
|
{
|
||||||
|
struct device_node *prom_stdout = NULL;
|
||||||
|
int offset = 0;
|
||||||
|
const char *name;
|
||||||
|
#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
|
||||||
|
char *devname = "ttyS";
|
||||||
|
#else
|
||||||
|
char *devname = "ttyPZ";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pr_debug(" -> check_pmac_serial_console()\n");
|
||||||
|
|
||||||
|
/* The user has requested a console so this is already set up. */
|
||||||
|
if (strstr(boot_command_line, "console=")) {
|
||||||
|
pr_debug(" console was specified !\n");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!of_chosen) {
|
||||||
|
pr_debug(" of_chosen is NULL !\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are getting a weird phandle from OF ... */
|
||||||
|
/* ... So use the full path instead */
|
||||||
|
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
|
||||||
|
if (name == NULL) {
|
||||||
|
pr_debug(" no linux,stdout-path !\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
prom_stdout = of_find_node_by_path(name);
|
||||||
|
if (!prom_stdout) {
|
||||||
|
pr_debug(" can't find stdout package %s !\n", name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
pr_debug("stdout is %s\n", prom_stdout->full_name);
|
||||||
|
|
||||||
|
name = of_get_property(prom_stdout, "name", NULL);
|
||||||
|
if (!name) {
|
||||||
|
pr_debug(" stdout package has no name !\n");
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "ch-a") == 0)
|
||||||
|
offset = 0;
|
||||||
|
else if (strcmp(name, "ch-b") == 0)
|
||||||
|
offset = 1;
|
||||||
|
else
|
||||||
|
goto not_found;
|
||||||
|
of_node_put(prom_stdout);
|
||||||
|
|
||||||
|
pr_debug("Found serial console at %s%d\n", devname, offset);
|
||||||
|
|
||||||
|
return add_preferred_console(devname, offset, NULL);
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
pr_debug("No preferred console found !\n");
|
||||||
|
of_node_put(prom_stdout);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
console_initcall(check_pmac_serial_console);
|
||||||
|
|
||||||
|
#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called very early, MMU is off, device-tree isn't unflattened
|
* Called very early, MMU is off, device-tree isn't unflattened
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -125,13 +125,23 @@ void udbg_scc_init(int force_scc)
|
||||||
out_8(sccc, 0xc0);
|
out_8(sccc, 0xc0);
|
||||||
|
|
||||||
/* If SCC was the OF output port, read the BRG value, else
|
/* If SCC was the OF output port, read the BRG value, else
|
||||||
* Setup for 57600 8N1
|
* Setup for 38400 or 57600 8N1 depending on the machine
|
||||||
*/
|
*/
|
||||||
if (ch_def != NULL) {
|
if (ch_def != NULL) {
|
||||||
out_8(sccc, 13);
|
out_8(sccc, 13);
|
||||||
scc_inittab[1] = in_8(sccc);
|
scc_inittab[1] = in_8(sccc);
|
||||||
out_8(sccc, 12);
|
out_8(sccc, 12);
|
||||||
scc_inittab[3] = in_8(sccc);
|
scc_inittab[3] = in_8(sccc);
|
||||||
|
} else if (machine_is_compatible("RackMac1,1")
|
||||||
|
|| machine_is_compatible("RackMac1,2")
|
||||||
|
|| machine_is_compatible("MacRISC4")) {
|
||||||
|
/* Xserves and G5s default to 57600 */
|
||||||
|
scc_inittab[1] = 0;
|
||||||
|
scc_inittab[3] = 0;
|
||||||
|
} else {
|
||||||
|
/* Others default to 38400 */
|
||||||
|
scc_inittab[1] = 0;
|
||||||
|
scc_inittab[3] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sizeof(scc_inittab); ++i)
|
for (i = 0; i < sizeof(scc_inittab); ++i)
|
||||||
|
|
|
@ -289,7 +289,9 @@ static int cmm_thread(void *dummy)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CMM_SHOW(name, format, args...) \
|
#define CMM_SHOW(name, format, args...) \
|
||||||
static ssize_t show_##name(struct sys_device *dev, char *buf) \
|
static ssize_t show_##name(struct sys_device *dev, \
|
||||||
|
struct sysdev_attribute *attr, \
|
||||||
|
char *buf) \
|
||||||
{ \
|
{ \
|
||||||
return sprintf(buf, format, ##args); \
|
return sprintf(buf, format, ##args); \
|
||||||
} \
|
} \
|
||||||
|
@ -298,12 +300,14 @@ static int cmm_thread(void *dummy)
|
||||||
CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));
|
CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));
|
||||||
CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
|
CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
|
||||||
|
|
||||||
static ssize_t show_oom_pages(struct sys_device *dev, char *buf)
|
static ssize_t show_oom_pages(struct sys_device *dev,
|
||||||
|
struct sysdev_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages));
|
return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_oom_pages(struct sys_device *dev,
|
static ssize_t store_oom_pages(struct sys_device *dev,
|
||||||
|
struct sysdev_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
unsigned long val = simple_strtoul (buf, NULL, 10);
|
unsigned long val = simple_strtoul (buf, NULL, 10);
|
||||||
|
|
|
@ -197,7 +197,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
|
||||||
args.new = BREAKPOINT_INSTRUCTION;
|
args.new = BREAKPOINT_INSTRUCTION;
|
||||||
|
|
||||||
kcb->kprobe_status = KPROBE_SWAP_INST;
|
kcb->kprobe_status = KPROBE_SWAP_INST;
|
||||||
stop_machine_run(swap_instruction, &args, NR_CPUS);
|
stop_machine(swap_instruction, &args, NULL);
|
||||||
kcb->kprobe_status = status;
|
kcb->kprobe_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
||||||
args.new = p->opcode;
|
args.new = p->opcode;
|
||||||
|
|
||||||
kcb->kprobe_status = KPROBE_SWAP_INST;
|
kcb->kprobe_status = KPROBE_SWAP_INST;
|
||||||
stop_machine_run(swap_instruction, &args, NR_CPUS);
|
stop_machine(swap_instruction, &args, NULL);
|
||||||
kcb->kprobe_status = status;
|
kcb->kprobe_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||||
* No kprobe at this address. The fault has not been
|
* No kprobe at this address. The fault has not been
|
||||||
* caused by a kprobe breakpoint. The race of breakpoint
|
* caused by a kprobe breakpoint. The race of breakpoint
|
||||||
* vs. kprobe remove does not exist because on s390 we
|
* vs. kprobe remove does not exist because on s390 we
|
||||||
* use stop_machine_run to arm/disarm the breakpoints.
|
* use stop_machine to arm/disarm the breakpoints.
|
||||||
*/
|
*/
|
||||||
goto no_kprobe;
|
goto no_kprobe;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
|
static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
|
||||||
u64 guestaddr)
|
unsigned long guestaddr)
|
||||||
{
|
{
|
||||||
u64 prefix = vcpu->arch.sie_block->prefix;
|
unsigned long prefix = vcpu->arch.sie_block->prefix;
|
||||||
u64 origin = vcpu->kvm->arch.guest_origin;
|
unsigned long origin = vcpu->kvm->arch.guest_origin;
|
||||||
u64 memsize = vcpu->kvm->arch.guest_memsize;
|
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
|
||||||
|
|
||||||
if (guestaddr < 2 * PAGE_SIZE)
|
if (guestaddr < 2 * PAGE_SIZE)
|
||||||
guestaddr += prefix;
|
guestaddr += prefix;
|
||||||
|
@ -37,7 +37,7 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
|
||||||
return (void __user *) guestaddr;
|
return (void __user *) guestaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u64 *result)
|
u64 *result)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -47,10 +47,10 @@ static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
if (IS_ERR((void __force *) uptr))
|
if (IS_ERR((void __force *) uptr))
|
||||||
return PTR_ERR((void __force *) uptr);
|
return PTR_ERR((void __force *) uptr);
|
||||||
|
|
||||||
return get_user(*result, (u64 __user *) uptr);
|
return get_user(*result, (unsigned long __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u32 *result)
|
u32 *result)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -63,7 +63,7 @@ static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return get_user(*result, (u32 __user *) uptr);
|
return get_user(*result, (u32 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u16 *result)
|
u16 *result)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -76,7 +76,7 @@ static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return get_user(*result, (u16 __user *) uptr);
|
return get_user(*result, (u16 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u8 *result)
|
u8 *result)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -87,7 +87,7 @@ static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return get_user(*result, (u8 __user *) uptr);
|
return get_user(*result, (u8 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u64 value)
|
u64 value)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -100,7 +100,7 @@ static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return put_user(value, (u64 __user *) uptr);
|
return put_user(value, (u64 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u32 value)
|
u32 value)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -113,7 +113,7 @@ static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return put_user(value, (u32 __user *) uptr);
|
return put_user(value, (u32 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u16 value)
|
u16 value)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -126,7 +126,7 @@ static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
return put_user(value, (u16 __user *) uptr);
|
return put_user(value, (u16 __user *) uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
|
static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
|
||||||
u8 value)
|
u8 value)
|
||||||
{
|
{
|
||||||
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
|
||||||
|
@ -138,7 +138,8 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
|
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
|
||||||
|
unsigned long guestdest,
|
||||||
const void *from, unsigned long n)
|
const void *from, unsigned long n)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -153,12 +154,12 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
|
static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
|
||||||
const void *from, unsigned long n)
|
const void *from, unsigned long n)
|
||||||
{
|
{
|
||||||
u64 prefix = vcpu->arch.sie_block->prefix;
|
unsigned long prefix = vcpu->arch.sie_block->prefix;
|
||||||
u64 origin = vcpu->kvm->arch.guest_origin;
|
unsigned long origin = vcpu->kvm->arch.guest_origin;
|
||||||
u64 memsize = vcpu->kvm->arch.guest_memsize;
|
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
|
||||||
|
|
||||||
if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
|
if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
|
||||||
goto slowpath;
|
goto slowpath;
|
||||||
|
@ -189,7 +190,8 @@ slowpath:
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
|
static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
|
||||||
u64 guestsrc, unsigned long n)
|
unsigned long guestsrc,
|
||||||
|
unsigned long n)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
@ -204,11 +206,11 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
|
static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
|
||||||
u64 guestsrc, unsigned long n)
|
unsigned long guestsrc, unsigned long n)
|
||||||
{
|
{
|
||||||
u64 prefix = vcpu->arch.sie_block->prefix;
|
unsigned long prefix = vcpu->arch.sie_block->prefix;
|
||||||
u64 origin = vcpu->kvm->arch.guest_origin;
|
unsigned long origin = vcpu->kvm->arch.guest_origin;
|
||||||
u64 memsize = vcpu->kvm->arch.guest_memsize;
|
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
|
||||||
|
|
||||||
if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
|
if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
|
||||||
goto slowpath;
|
goto slowpath;
|
||||||
|
@ -238,11 +240,12 @@ slowpath:
|
||||||
return __copy_from_guest_slow(vcpu, to, guestsrc, n);
|
return __copy_from_guest_slow(vcpu, to, guestsrc, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
|
static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
|
||||||
|
unsigned long guestdest,
|
||||||
const void *from, unsigned long n)
|
const void *from, unsigned long n)
|
||||||
{
|
{
|
||||||
u64 origin = vcpu->kvm->arch.guest_origin;
|
unsigned long origin = vcpu->kvm->arch.guest_origin;
|
||||||
u64 memsize = vcpu->kvm->arch.guest_memsize;
|
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
|
||||||
|
|
||||||
if (guestdest + n > memsize)
|
if (guestdest + n > memsize)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -256,10 +259,11 @@ static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
|
static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
|
||||||
u64 guestsrc, unsigned long n)
|
unsigned long guestsrc,
|
||||||
|
unsigned long n)
|
||||||
{
|
{
|
||||||
u64 origin = vcpu->kvm->arch.guest_origin;
|
unsigned long origin = vcpu->kvm->arch.guest_origin;
|
||||||
u64 memsize = vcpu->kvm->arch.guest_memsize;
|
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
|
||||||
|
|
||||||
if (guestsrc + n > memsize)
|
if (guestsrc + n > memsize)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "kvm-s390.h"
|
#include "kvm-s390.h"
|
||||||
#include "gaccess.h"
|
#include "gaccess.h"
|
||||||
|
|
||||||
static int handle_lctg(struct kvm_vcpu *vcpu)
|
static int handle_lctlg(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
|
int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
|
||||||
int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
|
int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
|
||||||
|
@ -30,7 +30,7 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
|
||||||
u64 useraddr;
|
u64 useraddr;
|
||||||
int reg, rc;
|
int reg, rc;
|
||||||
|
|
||||||
vcpu->stat.instruction_lctg++;
|
vcpu->stat.instruction_lctlg++;
|
||||||
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
|
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
@ -38,9 +38,12 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
|
||||||
if (base2)
|
if (base2)
|
||||||
useraddr += vcpu->arch.guest_gprs[base2];
|
useraddr += vcpu->arch.guest_gprs[base2];
|
||||||
|
|
||||||
|
if (useraddr & 7)
|
||||||
|
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
|
||||||
reg = reg1;
|
reg = reg1;
|
||||||
|
|
||||||
VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
|
VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
|
||||||
disp2);
|
disp2);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -74,6 +77,9 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
|
||||||
if (base2)
|
if (base2)
|
||||||
useraddr += vcpu->arch.guest_gprs[base2];
|
useraddr += vcpu->arch.guest_gprs[base2];
|
||||||
|
|
||||||
|
if (useraddr & 3)
|
||||||
|
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||||
|
|
||||||
VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
|
VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
|
||||||
disp2);
|
disp2);
|
||||||
|
|
||||||
|
@ -99,7 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
|
||||||
[0xae] = kvm_s390_handle_sigp,
|
[0xae] = kvm_s390_handle_sigp,
|
||||||
[0xb2] = kvm_s390_handle_priv,
|
[0xb2] = kvm_s390_handle_priv,
|
||||||
[0xb7] = handle_lctl,
|
[0xb7] = handle_lctl,
|
||||||
[0xeb] = handle_lctg,
|
[0xeb] = handle_lctlg,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int handle_noop(struct kvm_vcpu *vcpu)
|
static int handle_noop(struct kvm_vcpu *vcpu)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <asm/lowcore.h>
|
#include <asm/lowcore.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <linux/kvm_host.h>
|
#include <linux/kvm_host.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
#include "kvm-s390.h"
|
#include "kvm-s390.h"
|
||||||
#include "gaccess.h"
|
#include "gaccess.h"
|
||||||
|
|
||||||
|
@ -246,15 +247,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exception) {
|
if (exception) {
|
||||||
VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
|
printk("kvm: The guest lowcore is not mapped during interrupt "
|
||||||
" interrupt");
|
"delivery, killing userspace\n");
|
||||||
kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
do_exit(SIGKILL);
|
||||||
if (inti->type == KVM_S390_PROGRAM_INT) {
|
|
||||||
printk(KERN_WARNING "kvm: recursive program check\n");
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,14 +273,11 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
|
||||||
__LC_EXT_NEW_PSW, sizeof(psw_t));
|
__LC_EXT_NEW_PSW, sizeof(psw_t));
|
||||||
if (rc == -EFAULT)
|
if (rc == -EFAULT)
|
||||||
exception = 1;
|
exception = 1;
|
||||||
|
|
||||||
if (exception) {
|
if (exception) {
|
||||||
VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
|
printk("kvm: The guest lowcore is not mapped during interrupt "
|
||||||
" ckc interrupt");
|
"delivery, killing userspace\n");
|
||||||
kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
do_exit(SIGKILL);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue