Commit 11b0d994 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_work
parents edb74dc6 fcc6fcc6
......@@ -165,9 +165,9 @@ Note that there is a struct attribute embedded in the structure. In
order to relieve pain in declaring attributes, the subsystem should
also define a macro, like:
#define DEVICE_ATTR(_name,_str,_mode,_show,_store) \
#define DEVICE_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_name = { \
.attr = {.name = _str, .mode = _mode }, \
.attr = {.name = __stringify(_name) , .mode = _mode }, \
.show = _show, \
.store = _store, \
};
......@@ -252,7 +252,7 @@ struct bus_attribute {
Declaring:
BUS_ATTR(_name,_str,_mode,_show,_store)
BUS_ATTR(_name,_mode,_show,_store)
Creation/Removal:
......@@ -273,7 +273,7 @@ struct driver_attribute {
Declaring:
DRIVER_ATTR(_name,_str,_mode,_show,_store)
DRIVER_ATTR(_name,_mode,_show,_store)
Creation/Removal:
......
......@@ -87,7 +87,12 @@ ioctl(file,I2C_SLAVE,long addr)
ioctl(file,I2C_TENBIT,long select)
Selects ten bit addresses if select not equals 0, selects normal 7 bit
addresses if select equals 0.
addresses if select equals 0. Default 0.
ioctl(file,I2C_PEC,long select)
Selects SMBus PEC (packet error checking) generation and verification
if select not equals 0, disables if select equals 0. Default 0.
Used only for SMBus transactions.
ioctl(file,I2C_FUNCS,unsigned long *funcs)
Gets the adapter functionality and puts it in *funcs.
......
This diff is collapsed.
Primitive parallel port is driver for i2c bus, which exploits
features of modern bidirectional parallel ports.
Bidirectional ports have particular bits connected in following way:
|
/-----| R
--o| |-----|
read \-----| /------- Out pin
|/
- -|\
write V
|
---
It means when output is set to 1 we can read the port. Therefore
we can use 2 pins of parallel port as SDA and SCL for i2c bus. It
is not necessary to add any external - additional parts, we can
read and write the same port simultaneously.
I only use register base+2 so it is possible to use all
8 data bits of parallel port for other applications (I have
connected EEPROM and LCD display). I do not use bit Enable Bi-directional
Port. The only disadvantage is we can only support 5V chips.
Layout:
Cannon 25 pin
SDA - connect to pin 14 (Auto Linefeed)
SCL - connect to pin 16 (Initialize Printer)
GND - connect to pin 18-25
+5V - use external supply (I use 5V from 3.5" floppy connector)
no pullups requied
Module parameters:
base = 0xXXX
XXX - 278 or 378
That's all.
Daniel Smolik
marvin@sitour.cz
i2c-velleman driver
-------------------
This is a driver for i2c-hw access for Velleman K9000 and other adapters.
Useful links
------------
Velleman:
http://www.velleman.be/
Velleman K8000 Howto:
http://howto.htlw16.ac.at/k8000-howto.html
K8000 and K8005 libraries
-------------------------
The project has lead to new libs for the Velleman K8000 and K8005..
LIBK8000 v1.99.1 and LIBK8005 v0.21
With these libs you can control the K8000 and K8005 with the original
simple commands which are in the original Velleman software.
Like SetIOchannel, ReadADchannel, SendStepCCWFull and many more.
Via i2c kernel device /dev/velleman
The libs can be found on http://groups.yahoo.com/group/k8000/files/linux/
The Velleman K8000 interface card on http://www.velleman.be/kits/k8000.htm
The Velleman K8005 steppermotorcard on http://www.velleman.be/kits/k8005.htm
SMBus Protocol Summary
======================
The following is a summary of the SMBus protocol. It applies to
all revisions of the protocol (1.0, 1.1, and 2.0).
Certain protocol features which are not supported by
this package are briefly described at the end of this document.
Some adapters understand only the SMBus (System Management Bus) protocol,
which is a subset from the I2C protocol. Fortunately, many devices use
only the same subset, which makes it possible to put them on an SMBus.
......@@ -6,7 +13,7 @@ commands if at all possible (if the device uses only that subset of the
I2C protocol). This makes it possible to use the device driver on both
SMBus adapters and I2C adapters (the SMBus command set is automatically
translated to I2C on I2C adapters, but plain I2C commands can not be
handled at all on a pure SMBus adapter).
handled at all on most pure SMBus adapters).
Below is a list of SMBus commands.
......@@ -109,7 +116,7 @@ S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
SMBus Block Read
================
This command reads a block of upto 32 bytes from a device, from a
This command reads a block of up to 32 bytes from a device, from a
designated register that is specified through the Comm byte. The amount
of data is specified by the device in the Count byte.
......@@ -120,8 +127,90 @@ S Addr Wr [A] Comm [A]
SMBus Block Write
=================
The opposite of the Block Read command, this writes upto 32 bytes to
The opposite of the Block Read command, this writes up to 32 bytes to
a device, to a designated register that is specified through the
Comm byte. The amount of data is specified in the Count byte.
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
SMBus Block Process Call
========================
SMBus Block Process Call was introduced in Revision 2.0 of the specification.
This command selects a device register (through the Comm byte), sends
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.
S Addr Wr [A] Comm [A] Count [A] Data [A] ...
S Addr Rd [A] [Count] A [Data] ... A P
SMBus Host Notify
=================
This command is sent from a SMBus device acting as a master to the
SMBus host acting as a slave.
It is the same form as Write Word, with the command code replaced by the
alerting device's address.
[S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P]
Packet Error Checking (PEC)
===========================
Packet Error Checking was introduced in Revision 1.1 of the specification.
PEC adds a CRC-8 error-checking byte to all transfers.
Address Resolution Protocol (ARP)
=================================
The Address Resolution Protocol was introduced in Revision 2.0 of
the specification. It is a higher-layer protocol which uses the
messages above.
ARP adds device enumeration and dynamic address assignment to
the protocol. All ARP communications use slave address 0x61 and
require PEC checksums.
I2C Block Transactions
======================
The following I2C block transactions are supported by the
SMBus layer and are described here for completeness.
I2C block transactions do not limit the number of bytes transferred
but the SMBus layer places a limit of 32 bytes.
I2C Block Read
==============
This command reads a block of bytes from a device, from a
designated register that is specified through the Comm byte.
S Addr Wr [A] Comm [A]
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
I2C Block Read (2 Comm bytes)
=============================
This command reads a block of bytes from a device, from a
designated register that is specified through the two Comm bytes.
S Addr Wr [A] Comm1 [A] Comm2 [A]
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
I2C Block Write
===============
The opposite of the Block Read command, this writes bytes to
a device, to a designated register that is specified through the
Comm byte. Note that command lengths of 0, 2, or more bytes are
supported as they are indistinguishable from data.
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
......@@ -59,16 +59,16 @@ Algorithm drivers
i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
i2c-algo-bit: A bit-banging algorithm
i2c-algo-pcf: A PCF 8584 style algorithm
i2c-algo-ppc405: An algorithm for the I2C device in IBM 405xx processors (NOT BUILT BY DEFAULT)
i2c-algo-ibmocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT)
Adapter drivers
---------------
i2c-elektor: Elektor ISA card (uses i2c-algo-pcf)
i2c-elv: ELV parallel port adapter (uses i2c-algo-bit)
i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (BROKEN - missing i2c-pcf-epp.h)
i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatched)
i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
i2c-ppc405: IBM 405xx processor I2C device (uses i2c-algo-ppc405) (NOT BUILT BY DEFAULT)
i2c-adap_ibmocp: IBM 4xx processor I2C device (uses i2c-algo-ibmocp) (NOT BUILT BY DEFAULT)
i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit)
i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
i2c-velleman: Velleman K9000 parallel port adapter (uses i2c-algo-bit)
......
......@@ -365,7 +365,7 @@ The detect client function
The detect client function is called by i2c_probe or i2c_detect.
The `kind' parameter contains 0 if this call is due to a `force'
parameter, and 0 otherwise (for i2c_detect, it contains 0 if
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
this call is due to the generic `force' parameter, and the chip type
number if it is due to a specific `force' parameter).
......
......@@ -9,6 +9,8 @@
extern struct device device_root;
extern spinlock_t device_lock;
extern struct device * get_device_locked(struct device *);
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
......
......@@ -16,6 +16,9 @@
static LIST_HEAD(bus_driver_list);
#define to_dev(node) container_of(node,struct device,bus_list)
#define to_drv(node) container_of(node,struct device_driver,bus_list)
/**
* bus_for_each_dev - walk list of devices and do something to each
* @bus: bus in question
......@@ -26,42 +29,41 @@ static LIST_HEAD(bus_driver_list);
* counting on devices as we touch each one.
*
* Algorithm:
* Take the bus lock and get the first node in the list. We increment
* the reference count and unlock the bus. If we have a device from a
* previous iteration, we decrement the reference count.
* After we call the callback, we get the next node in the list and loop.
* At the end, if @dev is not null, we still have it pinned, so we need
* to let it go.
* Take device_lock and get the first node in the list.
* Try and increment the reference count on it. If we can't, it's in the
* process of being removed, but that process hasn't acquired device_lock.
* It's still in the list, so we grab the next node and try that one.
* We drop the lock to call the callback.
* We can't decrement the reference count yet, because we need the next
* node in the list. So, we set @prev to point to the current device.
* On the next go-round, we decrement the reference count on @prev, so if
* it's being removed, it won't affect us.
*/
int bus_for_each_dev(struct bus_type * bus, void * data,
int (*callback)(struct device * dev, void * data))
{
struct device * next;
struct device * dev = NULL;
struct list_head * node;
struct device * prev = NULL;
int error = 0;
get_bus(bus);
read_lock(&bus->lock);
node = bus->devices.next;
while (node != &bus->devices) {
next = list_entry(node,struct device,bus_list);
get_device(next);
read_unlock(&bus->lock);
if (dev)
put_device(dev);
dev = next;
if ((error = callback(dev,data))) {
put_device(dev);
break;
spin_lock(&device_lock);
list_for_each(node,&bus->devices) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
error = callback(dev,data);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
if (error)
break;
}
read_lock(&bus->lock);
node = dev->bus_list.next;
}
read_unlock(&bus->lock);
if (dev)
put_device(dev);
spin_unlock(&device_lock);
if (prev)
put_device(prev);
put_bus(bus);
return error;
}
......@@ -69,34 +71,30 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data))
{
struct device_driver * next;
struct device_driver * drv = NULL;
struct list_head * node;
struct device_driver * prev = NULL;
int error = 0;
/* pin bus in memory */
get_bus(bus);
read_lock(&bus->lock);
node = bus->drivers.next;
while (node != &bus->drivers) {
next = list_entry(node,struct device_driver,bus_list);
get_driver(next);
read_unlock(&bus->lock);
if (drv)
put_driver(drv);
drv = next;
if ((error = callback(drv,data))) {
put_driver(drv);
break;
spin_lock(&device_lock);
list_for_each(node,&bus->drivers) {
struct device_driver * drv = get_driver(to_drv(node));
if (drv) {
spin_unlock(&device_lock);
error = callback(drv,data);
if (prev)
put_driver(prev);
prev = drv;
spin_lock(&device_lock);
if (error)
break;
}
read_lock(&bus->lock);
node = drv->bus_list.next;
}
read_unlock(&bus->lock);
if (drv)
put_driver(drv);
spin_unlock(&device_lock);
if (prev)
put_driver(prev);
put_bus(bus);
return error;
}
......@@ -115,9 +113,9 @@ int bus_add_device(struct device * dev)
if (dev->bus) {
pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
get_bus(dev->bus);
write_lock(&dev->bus->lock);
spin_lock(&device_lock);
list_add_tail(&dev->bus_list,&dev->bus->devices);
write_unlock(&dev->bus->lock);
spin_unlock(&device_lock);
device_bus_link(dev);
}
return 0;
......@@ -134,9 +132,6 @@ void bus_remove_device(struct device * dev)
{
if (dev->bus) {
device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
write_lock(&dev->bus->lock);
list_del_init(&dev->bus_list);
write_unlock(&dev->bus->lock);
put_bus(dev->bus);
}
}
......
......@@ -25,6 +25,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list)
/**
* found_match - do actual binding of device to driver
......@@ -53,9 +55,9 @@ static int found_match(struct device * dev, struct device_driver * drv)
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id,drv->name);
write_lock(&drv->lock);
spin_lock(&device_lock);
list_add_tail(&dev->driver_list,&drv->devices);
write_unlock(&drv->lock);
spin_unlock(&device_lock);
goto Done;
......@@ -101,19 +103,14 @@ static void device_detach(struct device * dev)
struct device_driver * drv;
if (dev->driver) {
lock_device(dev);
spin_lock(&device_lock);
drv = dev->driver;
dev->driver = NULL;
unlock_device(dev);
write_lock(&drv->lock);
list_del_init(&dev->driver_list);
write_unlock(&drv->lock);
spin_unlock(&device_lock);
/* detach from driver */
if (drv->remove)
if (drv && drv->remove)
drv->remove(dev);
put_driver(drv);
}
}
......@@ -134,47 +131,26 @@ int driver_attach(struct device_driver * drv)
return bus_for_each_dev(drv->bus,drv,do_driver_attach);
}
static int do_driver_detach(struct device * dev, struct device_driver * drv)
{
lock_device(dev);
if (dev->driver == drv) {
dev->driver = NULL;
unlock_device(dev);
if (drv->remove)
drv->remove(dev);
} else
unlock_device(dev);
return 0;
}
void driver_detach(struct device_driver * drv)
{
struct device * next;
struct device * dev = NULL;
struct list_head * node;
int error = 0;
struct device * prev = NULL;
write_lock(&drv->lock);
node = drv->devices.next;
while (node != &drv->devices) {
next = list_entry(node,struct device,driver_list);
get_device(next);
list_del_init(&next->driver_list);
write_unlock(&drv->lock);
if (dev)
put_device(dev);
dev = next;
if ((error = do_driver_detach(dev,drv))) {
put_device(dev);
break;
spin_lock(&device_lock);
list_for_each(node,&drv->devices) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
if (prev)
list_del_init(&prev->driver_list);
spin_unlock(&device_lock);
device_detach(dev);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
write_lock(&drv->lock);
node = drv->devices.next;
}
write_unlock(&drv->lock);
if (dev)
put_device(dev);
spin_unlock(&device_lock);
}
/**
......@@ -191,7 +167,6 @@ void driver_detach(struct device_driver * drv)
int device_register(struct device *dev)
{
int error;
struct device *prev_dev;
if (!dev || !strlen(dev->bus_id))
return -EINVAL;
......@@ -199,24 +174,21 @@ int device_register(struct device *dev)
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
INIT_LIST_HEAD(&dev->driver_list);
INIT_LIST_HEAD(&dev->bus_list);
spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,2);
spin_lock(&device_lock);
if (dev != &device_root) {
if (!dev->parent)
dev->parent = &device_root;
get_device(dev->parent);
if (list_empty(&dev->parent->children))
prev_dev = dev->parent;
else
prev_dev = list_entry(dev->parent->children.prev, struct device, node);
list_add(&dev->g_list, &prev_dev->g_list);
spin_lock(&device_lock);
list_add_tail(&dev->g_list,&dev->parent->g_list);
list_add_tail(&dev->node,&dev->parent->children);
spin_unlock(&device_lock);
}
spin_unlock(&device_lock);
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
......@@ -234,12 +206,37 @@ int device_register(struct device *dev)
platform_notify(dev);
register_done:
if (error) {
spin_lock(&device_lock);
list_del_init(&dev->g_list);
list_del_init(&dev->node);
spin_unlock(&device_lock);
if (dev->parent)
put_device(dev->parent);
}
put_device(dev);
if (error && dev->parent)
put_device(dev->parent);
return error;
}
struct device * get_device_locked(struct device * dev)
{
struct device * ret = dev;
if (dev && atomic_read(&dev->refcount) > 0)
atomic_inc(&dev->refcount);
else
ret = NULL;
return ret;
}
struct device * get_device(struct device * dev)
{
struct device * ret;
spin_lock(&device_lock);
ret = get_device_locked(dev);
spin_unlock(&device_lock);
return ret;
}
/**
* put_device - decrement reference count, and clean up when it hits 0
* @dev: device in question
......@@ -250,6 +247,8 @@ void put_device(struct device * dev)
return;
list_del_init(&dev->node);
list_del_init(&dev->g_list);
list_del_init(&dev->bus_list);
list_del_init(&dev->driver_list);
spin_unlock(&device_lock);
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
......@@ -296,4 +295,5 @@ static int __init device_init(void)
core_initcall(device_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(get_device);
EXPORT_SYMBOL(put_device);
......@@ -10,35 +10,31 @@
#include <linux/errno.h>
#include "base.h"
#define to_dev(node) container_of(node,struct device,driver_list)
int driver_for_each_dev(struct device_driver * drv, void * data, int (*callback)(struct device *, void * ))
int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device *, void * ))
{
struct device * next;
struct device * dev = NULL;
struct list_head * node;
struct device * prev = NULL;
int error = 0;
get_driver(drv);
read_lock(&drv->lock);
node = drv->devices.next;
while (node != &drv->devices) {
next = list_entry(node,struct device,driver_list);
get_device(next);
read_unlock(&drv->lock);
if (dev)
put_device(dev);
dev = next;
if ((error = callback(dev,data))) {
put_device(dev);
break;
spin_lock(&device_lock);
list_for_each(node,&drv->devices) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
error = callback(dev,data);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
if (error)
break;
}
read_lock(&drv->lock);
node = dev->driver_list.next;
}
read_unlock(&drv->lock);
if (dev)
put_device(dev);
spin_unlock(&device_lock);
put_driver(drv);
return error;
}
......@@ -60,9 +56,9 @@ int driver_register(struct device_driver * drv)
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
INIT_LIST_HEAD(&drv->devices);
write_lock(&drv->bus->lock);
spin_lock(&device_lock);
list_add(&drv->bus_list,&drv->bus->drivers);
write_unlock(&drv->bus->lock);
spin_unlock(&device_lock);
driver_make_dir(drv);
driver_attach(drv);
put_driver(drv);
......@@ -81,10 +77,10 @@ static void __remove_driver(struct device_driver * drv)
void remove_driver(struct device_driver * drv)
{
write_lock(&drv->bus->lock);
spin_lock(&device_lock);
atomic_set(&drv->refcount,0);
list_del_init(&drv->bus_list);
write_unlock(&drv->bus->lock);
spin_unlock(&device_lock);
__remove_driver(drv);
}
......@@ -94,13 +90,10 @@ void remove_driver(struct device_driver * drv)
*/
void put_driver(struct device_driver * drv)
{
write_lock(&drv->bus->lock);
if (!atomic_dec_and_test(&drv->refcount)) {
write_unlock(&drv->bus->lock);
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
return;
}
list_del_init(&drv->bus_list);
write_unlock(&drv->bus->lock);
spin_unlock(&device_lock);
__remove_driver(drv);
}
......
......@@ -14,7 +14,7 @@ static ssize_t device_read_name(struct device * dev, char * buf, size_t count, l
return off ? 0 : sprintf(buf,"%s\n",dev->name);
}
static DEVICE_ATTR(name,"name",S_IRUGO,device_read_name,NULL);
static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL);
static ssize_t
device_read_power(struct device * dev, char * page, size_t count, loff_t off)
......@@ -85,7 +85,7 @@ device_write_power(struct device * dev, const char * buf, size_t count, loff_t o
return error < 0 ? error : count;
}
static DEVICE_ATTR(power,"power",S_IWUSR | S_IRUGO,
static DEVICE_ATTR(power,S_IWUSR | S_IRUGO,
device_read_power,device_write_power);
struct device_attribute * device_default_files[] = {
......
......@@ -14,6 +14,8 @@
#include <linux/module.h>
#include "base.h"
#define to_dev(node) container_of(node,struct device,g_list)
/**
* device_suspend - suspend all devices on the device tree
* @state: state we're entering
......@@ -25,30 +27,26 @@
*/
int device_suspend(u32 state, u32 level)
{
struct device * dev;
struct device * prev = &device_root;
struct list_head * node;
struct device * prev = NULL;
int error = 0;
printk(KERN_EMERG "Suspending Devices\n");
get_device(prev);
spin_lock(&device_lock);
dev = g_list_to_dev(prev->g_list.next);
while(dev != &device_root && !error) {
get_device(dev);
spin_unlock(&device_lock);
put_device(prev);
if (dev->driver && dev->driver->suspend)
error = dev->driver->suspend(dev,state,level);
spin_lock(&device_lock);
prev = dev;
dev = g_list_to_dev(prev->g_list.next);
list_for_each(node,&device_root.g_list) {
struct device * dev = get_device_locked(dev);
if (dev) {
spin_unlock(&device_lock);
if (dev->driver && dev->driver->suspend)
error = dev->driver->suspend(dev,state,level);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
}
spin_unlock(&device_lock);
put_device(prev);
return error;
}
......@@ -63,27 +61,23 @@ int device_suspend(u32 state, u32 level)
*/
void device_resume(u32 level)
{
struct device * dev;
struct device * prev = &device_root;
get_device(prev);
struct list_head * node;
struct device * prev = NULL;
spin_lock(&device_lock);
dev = g_list_to_dev(prev->g_list.prev);
while(dev != &device_root) {
get_device(dev);
spin_unlock(&device_lock);
put_device(prev);
if (dev->driver && dev->driver->resume)
dev->driver->resume(dev,level);
spin_lock(&device_lock);
prev = dev;
dev = g_list_to_dev(prev->g_list.prev);
list_for_each_prev(node,&device_root.g_list) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
if (dev->driver && dev->driver->resume)
dev->driver->resume(dev,level);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
}
spin_unlock(&device_lock);
put_device(prev);
printk(KERN_EMERG "Devices Resumed\n");
}
......@@ -98,29 +92,25 @@ void device_resume(u32 level)
*/
void device_shutdown(void)
{
struct device * dev;
struct device * prev = &device_root;
struct list_head * node;
struct device * prev = NULL;
printk(KERN_EMERG "Shutting down devices\n");
get_device(prev);
spin_lock(&device_lock);
dev = g_list_to_dev(prev->g_list.next);
while(dev != &device_root) {
get_device(dev);
spin_unlock(&device_lock);
put_device(prev);
if (dev->driver && dev->driver->remove)
dev->driver->remove(dev);
spin_lock(&device_lock);
prev = dev;
dev = g_list_to_dev(prev->g_list.next);
list_for_each(node,&device_root.g_list) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
if (dev->driver && dev->driver->remove)
dev->driver->remove(dev);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
}
spin_unlock(&device_lock);
put_device(prev);
}
EXPORT_SYMBOL(device_suspend);
......
......@@ -74,6 +74,7 @@
#include <linux/slab.h>
#include <linux/loop.h>
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <asm/uaccess.h>
......@@ -235,6 +236,7 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
up(&mapping->host->i_sem);
out:
kunmap(bvec->bv_page);
balance_dirty_pages(mapping);
return ret;
unlock:
......
......@@ -21,7 +21,7 @@
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
/* $Id: i2c-algo-bit.c,v 1.34 2001/11/19 18:45:02 mds Exp $ */
/* $Id: i2c-algo-bit.c,v 1.37 2002/07/08 00:41:49 mds Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
......@@ -143,7 +143,7 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
/* scl, sda may not be high */
DEBPROTO(printk(" Sr "));
setsda(adap,1);
setscl(adap,1);
sclhi(adap);
udelay(adap->udelay);
sdalo(adap);
......
This diff is collapsed.
/* ------------------------------------------------------------------------- */
/* i2c-algo-ibm_ocp.h i2c driver algorithms for IBM PPC 405 IIC adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-97 Simon G. Vogl
1998-99 Hans Berglund
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
/* Modifications by MontaVista Software, August 2000
Changes made to support the IIC peripheral on the IBM PPC 405 */
#ifndef I2C_ALGO_IIC_H
#define I2C_ALGO_IIC_H 1
/* --- Defines for pcf-adapters --------------------------------------- */
#include <linux/i2c.h>
struct i2c_algo_iic_data {
struct iic_regs *data; /* private data for lolevel routines */
void (*setiic) (void *data, int ctl, int val);
int (*getiic) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
void (*waitforpin) (void *data);
/* local settings */
int udelay;
int mdelay;
int timeout;
};
#define I2C_IIC_ADAP_MAX 16
int i2c_iic_add_bus(struct i2c_adapter *);
int i2c_iic_del_bus(struct i2c_adapter *);
#endif /* I2C_ALGO_IIC_H */
......@@ -18,9 +18,10 @@
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
/* $Id: i2c-core.c,v 1.73 2002/03/03 17:37:44 mds Exp $ */
/* $Id: i2c-core.c,v 1.83 2002/07/08 01:37:15 mds Exp $ */
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -371,7 +372,7 @@ int i2c_del_driver(struct i2c_driver *driver)
struct i2c_client *client = adap->clients[j];
if (client != NULL &&
client->driver == driver) {
DEB2(printk("i2c-core.o: "
DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n",
client->name));
if ((res = driver->
......@@ -1002,6 +1003,123 @@ int i2c_adapter_id(struct i2c_adapter *adap)
/* The SMBus parts */
#define POLY (0x1070U << 3)
static u8
crc8(u16 data)
{
int i;
for(i = 0; i < 8; i++) {
if (data & 0x8000)
data = data ^ POLY;
data = data << 1;
}
return (u8)(data >> 8);
}
/* CRC over count bytes in the first array plus the bytes in the rest
array if it is non-null. rest[0] is the (length of rest) - 1
and is included. */
u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
{
int i;
for(i = 0; i < count; i++)
crc = crc8((crc ^ first[i]) << 8);
if(rest != NULL)
for(i = 0; i <= rest[0]; i++)
crc = crc8((crc ^ rest[i]) << 8);
return crc;
}
u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
{
return i2c_smbus_partial_pec(0, count, first, rest);
}
/* Returns new "size" (transaction type)
Note that we convert byte to byte_data and byte_data to word_data
rather than invent new xxx_PEC transactions. */
int i2c_smbus_add_pec(u16 addr, u8 command, int size,
union i2c_smbus_data *data)
{
u8 buf[3];
buf[0] = addr << 1;
buf[1] = command;
switch(size) {
case I2C_SMBUS_BYTE:
data->byte = i2c_smbus_pec(2, buf, NULL);
size = I2C_SMBUS_BYTE_DATA;
break;
case I2C_SMBUS_BYTE_DATA:
buf[2] = data->byte;
data->word = buf[2] ||
(i2c_smbus_pec(3, buf, NULL) << 8);
size = I2C_SMBUS_WORD_DATA;
break;
case I2C_SMBUS_WORD_DATA:
/* unsupported */
break;
case I2C_SMBUS_BLOCK_DATA:
data->block[data->block[0] + 1] =
i2c_smbus_pec(2, buf, data->block);
size = I2C_SMBUS_BLOCK_DATA_PEC;
break;
}
return size;
}
int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
union i2c_smbus_data *data)
{
u8 buf[3], rpec, cpec;
buf[1] = command;
switch(size) {
case I2C_SMBUS_BYTE_DATA:
buf[0] = (addr << 1) | 1;
cpec = i2c_smbus_pec(2, buf, NULL);
rpec = data->byte;
break;
case I2C_SMBUS_WORD_DATA:
buf[0] = (addr << 1) | 1;
buf[2] = data->word & 0xff;
cpec = i2c_smbus_pec(3, buf, NULL);
rpec = data->word >> 8;
break;
case I2C_SMBUS_WORD_DATA_PEC:
/* unsupported */
cpec = rpec = 0;
break;
case I2C_SMBUS_PROC_CALL_PEC:
/* unsupported */
cpec = rpec = 0;
break;
case I2C_SMBUS_BLOCK_DATA_PEC:
buf[0] = (addr << 1);
buf[2] = (addr << 1) | 1;
cpec = i2c_smbus_pec(3, buf, data->block);
rpec = data->block[data->block[0] + 1];
break;
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
buf[0] = (addr << 1) | 1;
rpec = i2c_smbus_partial_pec(partial, 1,
buf, data->block);
cpec = data->block[data->block[0] + 1];
break;
default:
cpec = rpec = 0;
break;
}
if(rpec != cpec) {
DEB(printk(KERN_DEBUG "i2c-core.o: Bad PEC 0x%02x vs. 0x%02x\n",
rpec, cpec));
return -1;
}
return 0;
}
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
......@@ -1020,8 +1138,9 @@ extern s32 i2c_smbus_read_byte(struct i2c_client * client)
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
{
union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
}
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
......@@ -1099,8 +1218,8 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
......@@ -1109,6 +1228,26 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
I2C_SMBUS_BLOCK_DATA,&data);
}
/* Returns the number of read bytes */
extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > I2C_SMBUS_BLOCK_MAX - 1)
return -1;
data.block[0] = length;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
if(i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE, command,
I2C_SMBUS_BLOCK_PROC_CALL, &data))
return -1;
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
}
/* Returns the number of read bytes */
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
u8 command, u8 *values)
......@@ -1131,8 +1270,8 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
if (length > I2C_SMBUS_I2C_BLOCK_MAX)
length = I2C_SMBUS_I2C_BLOCK_MAX;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
......@@ -1194,34 +1333,43 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_PROC_CALL:
num = 2; /* Special case */
read_write = I2C_SMBUS_READ;
msg[0].len = 3;
msg[1].len = 2;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_DATA_PEC:
if (read_write == I2C_SMBUS_READ) {
printk(KERN_ERR "i2c-core.o: Block read not supported under "
"I2C emulation!\n");
return -1;
printk(KERN_ERR "i2c-core.o: Block read not supported "
"under I2C emulation!\n");
return -1;
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > 34) {
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
printk(KERN_ERR "i2c-core.o: smbus_access called with "
"invalid block write size (%d)\n",
data->block[0]);
return -1;
}
if(size == I2C_SMBUS_BLOCK_DATA_PEC)
(msg[0].len)++;
for (i = 1; i <= msg[0].len; i++)
msgbuf0[i] = data->block[i-1];
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
printk(KERN_ERR "i2c-core.o: Block process call not supported "
"under I2C emulation!\n");
return -1;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
msg[1].len = 32;
msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > 34) {
if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 2) {
printk("i2c-core.o: i2c_smbus_xfer_emulated called with "
"invalid block write size (%d)\n",
data->block[0]);
......@@ -1254,8 +1402,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* fixed at 32 for now */
data->block[0] = 32;
for (i = 0; i < 32; i++)
data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
data->block[i+1] = msgbuf1[i];
break;
}
......@@ -1268,7 +1416,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
union i2c_smbus_data * data)
{
s32 res;
flags = flags & I2C_M_TEN;
int swpec = 0;
u8 partial = 0;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if((flags & I2C_CLIENT_PEC) &&
!(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
swpec = 1;
if(read_write == I2C_SMBUS_READ &&
size == I2C_SMBUS_BLOCK_DATA)
size = I2C_SMBUS_BLOCK_DATA_PEC;
else if(size == I2C_SMBUS_PROC_CALL)
size = I2C_SMBUS_PROC_CALL_PEC;
else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
i2c_smbus_add_pec(addr, command,
I2C_SMBUS_BLOCK_DATA, data);
partial = data->block[data->block[0] + 1];
size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
} else if(read_write == I2C_SMBUS_WRITE &&
size != I2C_SMBUS_QUICK &&
size != I2C_SMBUS_I2C_BLOCK_DATA)
size = i2c_smbus_add_pec(addr, command, size, data);
}
if (adapter->algo->smbus_xfer) {
I2C_LOCK(adapter);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
......@@ -1277,6 +1447,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data);
if(res >= 0 && swpec &&
size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
(read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
if(i2c_smbus_check_pec(addr, command, size, partial, data))
return -1;
}
return res;
}
......
......@@ -28,7 +28,7 @@
/* The devfs code is contributed by Philipp Matthias Hahn
<pmhahn@titan.lahn.de> */
/* $Id: i2c-dev.c,v 1.44 2001/11/19 18:45:02 mds Exp $ */
/* $Id: i2c-dev.c,v 1.46 2002/07/06 02:07:39 mds Exp $ */
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -236,6 +236,12 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
else
client->flags &= ~I2C_M_TEN;
return 0;
case I2C_PEC:
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
return (copy_to_user((unsigned long *)arg,&funcs,
......@@ -312,7 +318,8 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
(data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) {
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
#ifdef DEBUG
printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size);
......@@ -355,10 +362,11 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
(data_arg.size == I2C_SMBUS_PROC_CALL))
datasize = sizeof(data_arg.data->word);
else /* size == I2C_SMBUS_BLOCK_DATA */
else /* size == smbus block, i2c block, or block proc. call */
datasize = sizeof(data_arg.data->block);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
......@@ -367,6 +375,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT;
......@@ -535,6 +544,8 @@ int i2cdev_cleanup(void)
return 0;
}
EXPORT_NO_SYMBOLS;
#ifdef MODULE
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
......
......@@ -55,12 +55,9 @@ static int i2c_debug = 0;
in some functions, called from the algo-pcf module. Sometimes it's
need to be rewriten - but for now just remove this for simpler reading */
#if (LINUX_VERSION_CODE < 0x020301)
static struct wait_queue *pcf_wait = NULL;
#else
static wait_queue_head_t pcf_wait;
#endif
static int pcf_pending;
spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED;
/* ----- global defines ----------------------------------------------- */
#define DEB(x) if (i2c_debug>=1) x
......@@ -121,12 +118,12 @@ static void pcf_isa_waitforpin(void) {
int timeout = 2;
if (irq > 0) {
cli();
spin_lock_irq(&irq_driver_lock);
if (pcf_pending == 0) {
interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
} else
pcf_pending = 0;
sti();
spin_unlock_irq(&irq_driver_lock);
} else {
udelay(100);
}
......@@ -280,9 +277,7 @@ int __init i2c_pcfisa_init(void)
base = DEFAULT_BASE;
}
#if (LINUX_VERSION_CODE >= 0x020301)
init_waitqueue_head(&pcf_wait);
#endif
if (pcf_isa_init() == 0) {
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) {
pcf_isa_exit();
......@@ -297,6 +292,7 @@ int __init i2c_pcfisa_init(void)
return 0;
}
EXPORT_NO_SYMBOLS;
#ifdef MODULE
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
......
/*
* linux/drivers/i2c/i2c-frodo.c
*
* Author: Abraham van der Merwe <abraham@2d3d.co.za>
*
* An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
* Development board (Frodo).
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
static void frodo_setsda (void *data,int state)
{
if (state)
FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT;
else
FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT;
}
static void frodo_setscl (void *data,int state)
{
if (state)
FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT;
else
FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT;
}
static int frodo_getsda (void *data)
{
return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0);
}
static int frodo_getscl (void *data)
{
return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0);
}
static struct i2c_algo_bit_data bit_frodo_data = {
setsda: frodo_setsda,
setscl: frodo_setscl,
getsda: frodo_getsda,
getscl: frodo_getscl,
udelay: 80,
mdelay: 80,
timeout: 100
};
static int frodo_client_register (struct i2c_client *client)
{
return (0);
}
static int frodo_client_unregister (struct i2c_client *client)
{
return (0);
}
static void frodo_inc_use (struct i2c_adapter *adapter)
{
MOD_INC_USE_COUNT;
}
static void frodo_dec_use (struct i2c_adapter *adapter)
{
MOD_DEC_USE_COUNT;
}
static struct i2c_adapter frodo_ops = {
name: "Frodo adapter driver",
id: I2C_HW_B_FRODO,
algo: NULL,
algo_data: &bit_frodo_data,
inc_use: frodo_inc_use,
dec_use: frodo_dec_use,
client_register: frodo_client_register,
client_unregister: frodo_client_unregister
};
static int __init i2c_frodo_init (void)
{
return (i2c_bit_add_bus (&frodo_ops));
}
EXPORT_NO_SYMBOLS;
static void __exit i2c_frodo_exit (void)
{
i2c_bit_del_bus (&frodo_ops);
}
MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
#ifdef MODULE_LICENSE
MODULE_LICENSE ("GPL");
#endif /* #ifdef MODULE_LICENSE */
EXPORT_NO_SYMBOLS;
module_init (i2c_frodo_init);
module_exit (i2c_frodo_exit);
......@@ -60,6 +60,7 @@ int __init sensors_init(void);
static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
static unsigned short i2c_inodes[SENSORS_ENTRY_MAX];
static ctl_table sysctl_table[] = {
{CTL_DEV, "dev", NULL, 0, 0555},
......@@ -172,7 +173,7 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
kfree(new_table);
kfree(name);
return -ENOMEM;
return -EPERM;
}
i2c_entries[id - 256] = new_header;
......@@ -188,6 +189,8 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
return id;
}
#endif /* DEBUG */
i2c_inodes[id - 256] =
new_header->ctl_table->child->child->de->low_ino;
new_header->ctl_table->child->child->de->owner = controlling_mod;
return id;
......@@ -210,6 +213,49 @@ void i2c_deregister_entry(int id)
}
}
/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o
impossible if some process still uses it or some file in it */
void i2c_fill_inode(struct inode *inode, int fill)
{
if (fill)
MOD_INC_USE_COUNT;
else
MOD_DEC_USE_COUNT;
}
/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading
the corresponding module impossible if some process still uses it or
some file in it */
void i2c_dir_fill_inode(struct inode *inode, int fill)
{
int i;
struct i2c_client *client;
#ifdef DEBUG
if (!inode) {
printk(KERN_ERR "i2c-proc.o: Warning: inode NULL in fill_inode()\n");
return;
}
#endif /* def DEBUG */
for (i = 0; i < SENSORS_ENTRY_MAX; i++)
if (i2c_clients[i]
&& (i2c_inodes[i] == inode->i_ino)) break;
#ifdef DEBUG
if (i == SENSORS_ENTRY_MAX) {
printk
(KERN_ERR "i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n",
inode->i_ino);
return;
}
#endif /* def DEBUG */
client = i2c_clients[i];
if (fill)
client->driver->inc_use(client);
else
client->driver->dec_use(client);
}
int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
void *buffer, size_t * lenp)
{
......
/*
* Embedded Planet RPX Lite MPC8xx CPM I2C interface.
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
*
* moved into proper i2c interface;
* Brad Parker (brad@heeltoe.com)
*
* RPX lite specific parts of the i2c interface
* Update: There actually isn't anything RPXLite-specific about this module.
* This should work for most any 8xx board. The console messages have been
* changed to eliminate RPXLite references.
*/
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/stddef.h>
#include <linux/parport.h>
#include <asm/mpc8xx.h>
#include <asm/commproc.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-8xx.h>
static void
rpx_iic_init(struct i2c_algo_8xx_data *data)
{
volatile cpm8xx_t *cp;
volatile immap_t *immap;
cp = cpmp; /* Get pointer to Communication Processor */
immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
/* Check for and use a microcode relocation patch.
*/
if ((data->reloc = data->iip->iic_rpbase))
data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
data->i2c = (i2c8xx_t *)&(immap->im_i2c);
data->cp = cp;
/* Initialize Port B IIC pins.
*/
cp->cp_pbpar |= 0x00000030;
cp->cp_pbdir |= 0x00000030;
cp->cp_pbodr |= 0x00000030;
/* Allocate space for two transmit and two receive buffer
* descriptors in the DP ram.
*/
data->dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 4);
/* ptr to i2c area */
data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
}
static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data)
{
/* install interrupt handler */
cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data);
return 0;
}
static int rpx_reg(struct i2c_client *client)
{
return 0;
}
static int rpx_unreg(struct i2c_client *client)
{
return 0;
}
static void rpx_inc_use(struct i2c_adapter *adap)
{
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
}
static void rpx_dec_use(struct i2c_adapter *adap)
{
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
}
static struct i2c_algo_8xx_data rpx_data = {
setisr: rpx_install_isr
};
static struct i2c_adapter rpx_ops = {
"m8xx",
I2C_HW_MPC8XX_EPON,
NULL,
&rpx_data,
rpx_inc_use,
rpx_dec_use,
rpx_reg,
rpx_unreg,
};
int __init i2c_rpx_init(void)
{
printk("i2c-rpx.o: i2c MPC8xx module version %s (%s)\n", I2C_VERSION, I2C_DATE);
/* reset hardware to sane state */
rpx_iic_init(&rpx_data);
if (i2c_8xx_add_bus(&rpx_ops) < 0) {
printk("i2c-rpx: Unable to register with I2C\n");
return -ENODEV;
}
return 0;
}
void __exit i2c_rpx_exit(void)
{
i2c_8xx_del_bus(&rpx_ops);
}
#ifdef MODULE
MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
module_init(i2c_rpx_init);
module_exit(i2c_rpx_exit);
#endif
......@@ -378,7 +378,7 @@ static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_
return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq);
}
static DEVICE_ATTR(irq,"irq",S_IRUGO,pci_show_irq,NULL);
static DEVICE_ATTR(irq,S_IRUGO,pci_show_irq,NULL);
static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off)
{
......@@ -402,7 +402,7 @@ static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count,
return (str - buf);
}
static DEVICE_ATTR(resource,"resource",S_IRUGO,pci_show_resources,NULL);
static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
int pci_proc_attach_device(struct pci_dev *dev)
{
......
......@@ -305,7 +305,7 @@ static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page,
return 0;
}
static DEVICE_ATTR(type,"type",S_IRUGO,scsi_device_type_read,NULL);
static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL);
/* end content handlers */
......
......@@ -1401,14 +1401,14 @@ static ssize_t sg_device_kdev_read(struct device *driverfs_dev, char *page,
Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value);
}
static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sg_device_kdev_read,NULL);
static DEVICE_ATTR(kdev,S_IRUGO,sg_device_kdev_read,NULL);
static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static DEVICE_ATTR(type,"type",S_IRUGO,sg_device_type_read,NULL);
static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL);
static int sg_attach(Scsi_Device * scsidp)
{
......
......@@ -737,14 +737,14 @@ static ssize_t sr_device_kdev_read(struct device *driverfs_dev,
kdev.value=(int)(long)driverfs_dev->driver_data;
return off ? 0 : sprintf(page, "%x\n",kdev.value);
}
static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sr_device_kdev_read,NULL);
static DEVICE_ATTR(kdev,S_IRUGO,sr_device_kdev_read,NULL);
static ssize_t sr_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static DEVICE_ATTR(type,"type",S_IRUGO,sr_device_type_read,NULL);
static DEVICE_ATTR(type,S_IRUGO,sr_device_type_read,NULL);
void sr_finish()
......
......@@ -3533,14 +3533,14 @@ static ssize_t st_device_kdev_read(struct device *driverfs_dev,
kdev.value=(int)(long)driverfs_dev->driver_data;
return off ? 0 : sprintf(page, "%x\n",kdev.value);
}
static DEVICE_ATTR(kdev,"kdev",S_IRUGO,st_device_kdev_read,NULL);
static DEVICE_ATTR(kdev,S_IRUGO,st_device_kdev_read,NULL);
static ssize_t st_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "CHR\n");
}
static DEVICE_ATTR(type,"type",S_IRUGO,st_device_type_read,NULL);
static DEVICE_ATTR(type,S_IRUGO,st_device_type_read,NULL);
static struct file_operations st_fops =
......
......@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/uts.h> /* for UTS_SYSNAME */
#include <linux/pci.h> /* for hcd->pdev and dma addressing */
#include <asm/byteorder.h>
......@@ -1021,6 +1022,24 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
if (status)
return status;
/* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
if (usb_pipecontrol (urb->pipe))
urb->setup_dma = pci_map_single (
hcd->pdev,
urb->setup_packet,
sizeof (struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
if (urb->transfer_buffer_length != 0)
urb->transfer_dma = pci_map_single (
hcd->pdev,
urb->transfer_buffer,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
}
/* increment urb's reference count as part of giving it to the HCD
* (which now controls it). HCD guarantees that it either returns
* an error or calls giveback(), but not both.
......@@ -1289,6 +1308,20 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
dbg ("giveback urb %p status %d len %d",
urb, urb->status, urb->actual_length);
/* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
if (usb_pipecontrol (urb->pipe))
pci_unmap_single (hcd->pdev, urb->setup_dma,
sizeof (struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
if (urb->transfer_buffer_length != 0)
pci_unmap_single (hcd->pdev, urb->transfer_dma,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
}
/* pass ownership to the completion handler */
urb->complete (urb);
usb_put_urb (urb);
......
......@@ -137,7 +137,7 @@ void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf)
driver = intf->driver;
priv = intf->private_data;
if (!driver)
if (!driver || !driver->disconnect)
return;
/* as soon as we increase the module use count we drop the BKL
......@@ -836,7 +836,7 @@ show_config (struct device *dev, char *buf, size_t count, loff_t off)
return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue);
}
static DEVICE_ATTR(config,"configuration",S_IRUGO,show_config,NULL);
static DEVICE_ATTR(configuration,S_IRUGO,show_config,NULL);
/* interfaces have one current setting; alternates
* can have different endpoints and class info.
......@@ -851,7 +851,7 @@ show_altsetting (struct device *dev, char *buf, size_t count, loff_t off)
interface = to_usb_interface (dev);
return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting);
}
static DEVICE_ATTR(altsetting,"altsetting",S_IRUGO,show_altsetting,NULL);
static DEVICE_ATTR(altsetting,S_IRUGO,show_altsetting,NULL);
/* product driverfs file */
static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
......@@ -870,7 +870,7 @@ static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(product,"product",S_IRUGO,show_product,NULL);
static DEVICE_ATTR(product,S_IRUGO,show_product,NULL);
/* manufacturer driverfs file */
static ssize_t
......@@ -890,7 +890,7 @@ show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(manufacturer,"manufacturer",S_IRUGO,show_manufacturer,NULL);
static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL);
/* serial number driverfs file */
static ssize_t
......@@ -910,7 +910,7 @@ show_serial (struct device *dev, char *buf, size_t count, loff_t off)
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(serial,"serial",S_IRUGO,show_serial,NULL);
static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL);
/*
* This entrypoint gets called for each new device.
......@@ -1440,7 +1440,7 @@ int usb_new_device(struct usb_device *dev)
err = device_register (&dev->dev);
if (err)
return err;
device_create_file (&dev->dev, &dev_attr_config);
device_create_file (&dev->dev, &dev_attr_configuration);
if (dev->descriptor.iManufacturer)
device_create_file (&dev->dev, &dev_attr_manufacturer);
if (dev->descriptor.iProduct)
......@@ -1641,10 +1641,10 @@ static int __init usb_init(void)
*/
static void __exit usb_exit(void)
{
put_bus(&usb_bus_type);
usb_major_cleanup();
usbfs_cleanup();
usb_hub_cleanup();
put_bus(&usb_bus_type);
}
subsys_initcall(usb_init);
......
......@@ -163,7 +163,6 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
static void ehci_urb_done (
struct ehci_hcd *ehci,
dma_addr_t addr,
struct urb *urb
) {
#ifdef INTR_AUTOMAGIC
......@@ -171,13 +170,6 @@ static void ehci_urb_done (
struct usb_device *dev = 0;
#endif
if (urb->transfer_buffer_length)
pci_unmap_single (ehci->hcd.pdev,
addr,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
if (likely (urb->hcpriv != 0)) {
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
......@@ -263,7 +255,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (likely (last->urb != urb)) {
/* complete() can reenter this HCD */
spin_unlock_irqrestore (&ehci->lock, flags);
ehci_urb_done (ehci, last->buf_dma, last->urb);
ehci_urb_done (ehci, last->urb);
spin_lock_irqsave (&ehci->lock, flags);
}
......@@ -347,12 +339,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
urb, urb->status, qtd, token,
urb->actual_length);
#endif
/* SETUP for control urb? */
if (unlikely (QTD_PID (token) == 2))
pci_unmap_single (ehci->hcd.pdev,
qtd->buf_dma, sizeof (struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
}
/* patch up list head? */
......@@ -364,7 +350,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* last urb's completion might still need calling */
if (likely (last != 0)) {
ehci_urb_done (ehci, last->buf_dma, last->urb);
ehci_urb_done (ehci, last->urb);
ehci_qtd_free (ehci, last);
}
}
......@@ -405,10 +391,6 @@ static void qtd_list_free (
size = qtd->urb->transfer_buffer_length;
unmapped++;
}
if (qtd->buf_dma)
pci_unmap_single (ehci->hcd.pdev,
qtd->buf_dma,
size, direction);
}
ehci_qtd_free (ehci, qtd);
}
......@@ -425,7 +407,7 @@ qh_urb_transaction (
int flags
) {
struct ehci_qtd *qtd, *qtd_prev;
dma_addr_t buf, map_buf;
dma_addr_t buf;
int len, maxpacket;
int is_input;
u32 token;
......@@ -445,17 +427,8 @@ qh_urb_transaction (
/* for split transactions, SplitXState initialized to zero */
if (usb_pipecontrol (urb->pipe)) {
/* control request data is passed in the "setup" pid */
qtd->buf_dma = pci_map_single (
ehci->hcd.pdev,
urb->setup_packet,
sizeof (struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
if (unlikely (!qtd->buf_dma))
goto cleanup;
/* SETUP pid */
qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest),
qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
token | (2 /* "setup" */ << 8));
/* ... and always at least one more pid */
......@@ -474,16 +447,10 @@ qh_urb_transaction (
*/
len = urb->transfer_buffer_length;
is_input = usb_pipein (urb->pipe);
if (likely (len > 0)) {
buf = map_buf = pci_map_single (ehci->hcd.pdev,
urb->transfer_buffer, len,
is_input
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
if (unlikely (!buf))
goto cleanup;
} else
buf = map_buf = 0;
if (likely (len > 0))
buf = urb->transfer_dma;
else
buf = 0;
if (!buf || is_input)
token |= (1 /* "in" */ << 8);
......@@ -500,7 +467,6 @@ qh_urb_transaction (
int this_qtd_len;
qtd->urb = urb;
qtd->buf_dma = map_buf;
this_qtd_len = qtd_fill (qtd, buf, len, token);
len -= this_qtd_len;
buf += this_qtd_len;
......
......@@ -530,11 +530,6 @@ itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
{
struct ehci_itd *first_itd = urb->hcpriv;
pci_unmap_single (ehci->hcd.pdev,
first_itd->buf_dma, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
while (!list_empty (&first_itd->itd_list)) {
struct ehci_itd *itd;
......@@ -630,16 +625,7 @@ itd_urb_transaction (
int frame_index;
struct ehci_itd *first_itd, *itd;
int status;
dma_addr_t buf_dma, itd_dma;
/* set up one dma mapping for this urb */
buf_dma = pci_map_single (ehci->hcd.pdev,
urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
if (buf_dma == 0)
return -ENOMEM;
dma_addr_t itd_dma;
/* allocate/init ITDs */
for (frame_index = 0, first_itd = 0;
......@@ -653,7 +639,8 @@ itd_urb_transaction (
memset (itd, 0, sizeof *itd);
itd->itd_dma = itd_dma;
status = itd_fill (ehci, itd, urb, frame_index, buf_dma);
status = itd_fill (ehci, itd, urb, frame_index,
urb->transfer_dma);
if (status != 0)
goto fail;
......
......@@ -219,7 +219,6 @@ struct ehci_qtd {
/* dma same in urb's qtds, except 1st control qtd (setup buffer) */
struct urb *urb; /* qtd's urb */
dma_addr_t buf_dma; /* buffer address */
size_t length; /* length of buffer */
} __attribute__ ((aligned (32)));
......
......@@ -14,27 +14,8 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
if (last >= 0) {
int i;
struct td *td = urb_priv->td [0];
int len = td->urb->transfer_buffer_length;
int dir = usb_pipeout (td->urb->pipe)
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE;
/* unmap CTRL URB setup buffer (always td 0) */
if (usb_pipecontrol (td->urb->pipe)) {
pci_unmap_single (hc->hcd.pdev,
td->data_dma, 8, PCI_DMA_TODEVICE);
/* CTRL data buffer starts at td 1 if len > 0 */
if (len && last > 0)
td = urb_priv->td [1];
}
/* else: ISOC, BULK, INTR data buffer starts at td 0 */
struct td *td;
/* unmap data buffer */
if (len && td->data_dma)
pci_unmap_single (hc->hcd.pdev,
td->data_dma, len, dir);
for (i = 0; i <= last; i++) {
td = urb_priv->td [i];
if (td)
......@@ -85,15 +66,8 @@ static inline void intr_resub (struct ohci_hcd *hc, struct urb *urb)
struct urb_priv *urb_priv = urb->hcpriv;
unsigned long flags;
// FIXME rewrite this resubmit path. use pci_dma_sync_single()
// and requeue more cheaply, and only if needed.
// Better yet ... abolish the notion of automagic resubmission.
pci_unmap_single (hc->hcd.pdev,
urb_priv->td [0]->data_dma,
urb->transfer_buffer_length,
usb_pipeout (urb->pipe)
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
// FIXME going away along with the rest of interrrupt automagic...
/* FIXME: MP race. If another CPU partially unlinks
* this URB (urb->status was updated, hasn't yet told
* us to dequeue) before we call complete() here, an
......@@ -612,13 +586,9 @@ static void td_submit_urb (
urb_priv->td_cnt = 0;
if (data_len) {
data = pci_map_single (ohci->hcd.pdev,
urb->transfer_buffer, data_len,
is_out
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
} else
if (data_len)
data = urb->transfer_dma;
else
data = 0;
/* NOTE: TD_CC is set so we can tell which TDs the HC processed by
......@@ -665,11 +635,7 @@ static void td_submit_urb (
*/
case PIPE_CONTROL:
info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
td_fill (info,
pci_map_single (ohci->hcd.pdev,
urb->setup_packet, 8,
PCI_DMA_TODEVICE),
8, urb, cnt++);
td_fill (info, urb->setup_dma, 8, urb, cnt++);
if (data_len > 0) {
info = TD_CC | TD_R | TD_T_DATA1;
info |= is_out ? TD_DP_OUT : TD_DP_IN;
......
......@@ -161,6 +161,12 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
hcd->regs = (void *) &USB_OHCI_OP_BASE;
hcd->pdev = SA1111_FAKE_PCIDEV;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
dbg ("pool alloc fail");
goto err1;
}
set_irq_type(NIRQHCIM, IRQT_RISING);
retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
hcd->description, hcd);
......@@ -193,6 +199,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
return 0;
err2:
hcd_buffer_destroy (hcd);
if (hcd) driver->hcd_free(hcd);
err1:
sa1111_stop_hc();
......@@ -233,6 +240,7 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd)
hcd->state = USB_STATE_HALT;
free_irq (hcd->irq, hcd);
hcd_buffer_destroy (hcd);
usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1)
......
......@@ -646,23 +646,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
urb->hcpriv = urbp;
if (urb->transfer_buffer_length) {
urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
PCI_DMA_TODEVICE);
if (!urbp->transfer_buffer_dma_handle)
return NULL;
}
if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
urb->setup_packet, sizeof(struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
if (!urbp->setup_packet_dma_handle)
return NULL;
}
return urbp;
}
......@@ -721,19 +704,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
uhci_free_td(uhci, td);
}
if (urbp->setup_packet_dma_handle) {
pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
urbp->setup_packet_dma_handle = 0;
}
if (urbp->transfer_buffer_dma_handle) {
pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
urbp->transfer_buffer_dma_handle = 0;
}
urb->hcpriv = NULL;
kmem_cache_free(uhci_up_cachep, urbp);
}
......@@ -813,7 +783,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
unsigned long destination, status;
int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
int len = urb->transfer_buffer_length;
dma_addr_t data = urbp->transfer_buffer_dma_handle;
dma_addr_t data = urb->transfer_dma;
/* The "pipe" thing contains the destination in bits 8--18 */
destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
......@@ -832,7 +802,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(7),
urbp->setup_packet_dma_handle);
urb->setup_dma);
/*
* If direction is "send", change the frame from SETUP (0x2D)
......@@ -1072,7 +1042,6 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb)
{
struct uhci_td *td;
unsigned long destination, status;
struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
return -EINVAL;
......@@ -1094,7 +1063,7 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb)
usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle);
uhci_fill_td(td, status, destination, urb->transfer_dma);
uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
......@@ -1196,7 +1165,7 @@ static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *
int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
int len = urb->transfer_buffer_length;
struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
dma_addr_t data = urbp->transfer_buffer_dma_handle;
dma_addr_t data = urb->transfer_dma;
if (len < 0)
return -EINVAL;
......@@ -1358,7 +1327,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
struct uhci_td *td;
int i, ret, frame;
int status, destination;
struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
......@@ -1378,7 +1346,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset);
urb->transfer_dma + urb->iso_frame_desc[i].offset);
if (i + 1 >= urb->number_of_packets)
td->status |= cpu_to_le32(TD_CTRL_IOC);
......@@ -1832,15 +1800,6 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb)
resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
urb->interval);
if (urbp->transfer_buffer_dma_handle)
pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
if (urbp->setup_packet_dma_handle)
pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
status = urbp->status;
if (!resubmit_interrupt || killed)
/* We don't need urb_priv anymore */
......
......@@ -338,9 +338,6 @@ struct urb_priv {
struct urb *urb;
struct usb_device *dev;
dma_addr_t setup_packet_dma_handle;
dma_addr_t transfer_buffer_dma_handle;
struct uhci_qh *qh; /* QH for this URB */
struct list_head td_list; /* P: urb->lock */
......
......@@ -436,7 +436,10 @@ static void CDCEther_set_multicast( struct net_device *net )
// Tell the kernel to stop sending us frames while we get this
// all set up.
netif_stop_queue(net);
// netif_stop_queue(net);
// FIXME: We hold xmit_lock. If you want to do the queue stuff you need
// to enable it from a completion handler
/* Note: do not reorder, GCC is clever about common statements. */
if (net->flags & IFF_PROMISC) {
......@@ -469,7 +472,7 @@ static void CDCEther_set_multicast( struct net_device *net )
MODE_FLAG_DIRECTED |
MODE_FLAG_BROADCAST |
MODE_FLAG_MULTICAST;
buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
buff = kmalloc(6 * net->mc_count, GFP_ATOMIC);
for (i = 0, mclist = net->mc_list;
mclist && i < net->mc_count;
i++, mclist = mclist->next) {
......@@ -477,6 +480,7 @@ static void CDCEther_set_multicast( struct net_device *net )
}
#if 0
usb_control_msg(ether_dev->usb,
// FIXME: We hold a spinlock. You must not use a synchronous API
usb_sndctrlpipe(ether_dev->usb, 0),
SET_ETHERNET_MULTICAST_FILTER, /* request */
USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
......@@ -493,7 +497,7 @@ static void CDCEther_set_multicast( struct net_device *net )
CDC_SetEthernetPacketFilter(ether_dev);
#endif
// Tell the kernel to start giving frames to us again.
netif_wake_queue(net);
// netif_wake_queue(net);
}
//////////////////////////////////////////////////////////////////////////////
......
......@@ -26,12 +26,12 @@
static sector_t max_block(struct block_device *bdev)
{
sector_t retval = ~0U;
sector_t retval = ~((sector_t)0);
loff_t sz = bdev->bd_inode->i_size;
if (sz) {
sector_t size = block_size(bdev);
unsigned sizebits = blksize_bits(size);
unsigned int size = block_size(bdev);
unsigned int sizebits = blksize_bits(size);
retval = (sz >> sizebits);
}
return retval;
......
......@@ -180,7 +180,10 @@ void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
if (uptodate) {
set_buffer_uptodate(bh);
} else {
buffer_io_error(bh);
/*
* This happens, due to failed READA attempts.
* buffer_io_error(bh);
*/
clear_buffer_uptodate(bh);
}
unlock_buffer(bh);
......@@ -1274,15 +1277,32 @@ __bread_slow(struct block_device *bdev, sector_t block, int size)
*
* This is a transparent caching front-end to sb_bread(), sb_getblk() and
* sb_find_get_block().
*
* The LRUs themselves only need locking against invalidate_bh_lrus. We use
* a local interrupt disable for that.
*/
#define BH_LRU_SIZE 7
#define BH_LRU_SIZE 8
static struct bh_lru {
spinlock_t lock;
struct buffer_head *bhs[BH_LRU_SIZE];
} ____cacheline_aligned_in_smp bh_lrus[NR_CPUS];
#ifdef CONFIG_SMP
#define bh_lru_lock() local_irq_disable()
#define bh_lru_unlock() local_irq_enable()
#else
#define bh_lru_lock() preempt_disable()
#define bh_lru_unlock() preempt_enable()
#endif
static inline void check_irqs_on(void)
{
#ifdef irqs_disabled
BUG_ON(irqs_disabled());
#endif
}
/*
* The LRU management algorithm is dopey-but-simple. Sorry.
*/
......@@ -1294,8 +1314,9 @@ static void bh_lru_install(struct buffer_head *bh)
if (bh == NULL)
return;
lru = &bh_lrus[get_cpu()];
spin_lock(&lru->lock);
check_irqs_on();
bh_lru_lock();
lru = &bh_lrus[smp_processor_id()];
if (lru->bhs[0] != bh) {
struct buffer_head *bhs[BH_LRU_SIZE];
int in;
......@@ -1321,8 +1342,7 @@ static void bh_lru_install(struct buffer_head *bh)
bhs[out++] = NULL;
memcpy(lru->bhs, bhs, sizeof(bhs));
}
spin_unlock(&lru->lock);
put_cpu();
bh_lru_unlock();
if (evictee) {
touch_buffer(evictee);
......@@ -1337,8 +1357,9 @@ lookup_bh(struct block_device *bdev, sector_t block, int size)
struct bh_lru *lru;
int i;
lru = &bh_lrus[get_cpu()];
spin_lock(&lru->lock);
check_irqs_on();
bh_lru_lock();
lru = &bh_lrus[smp_processor_id()];
for (i = 0; i < BH_LRU_SIZE; i++) {
struct buffer_head *bh = lru->bhs[i];
......@@ -1356,8 +1377,7 @@ lookup_bh(struct block_device *bdev, sector_t block, int size)
break;
}
}
spin_unlock(&lru->lock);
put_cpu();
bh_lru_unlock();
return ret;
}
......@@ -1404,25 +1424,32 @@ __bread(struct block_device *bdev, sector_t block, int size)
EXPORT_SYMBOL(__bread);
/*
* This is called rarely - at unmount.
* invalidate_bh_lrus() is called rarely - at unmount. Because it is only for
* unmount it only needs to ensure that all buffers from the target device are
* invalidated on return and it doesn't need to worry about new buffers from
* that device being added - the unmount code has to prevent that.
*/
static void invalidate_bh_lrus(void)
static void invalidate_bh_lru(void *arg)
{
int cpu_idx;
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++)
spin_lock(&bh_lrus[cpu_idx].lock);
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++) {
int i;
const int cpu = get_cpu();
int i;
for (i = 0; i < BH_LRU_SIZE; i++) {
brelse(bh_lrus[cpu_idx].bhs[i]);
bh_lrus[cpu_idx].bhs[i] = NULL;
}
for (i = 0; i < BH_LRU_SIZE; i++) {
brelse(bh_lrus[cpu].bhs[i]);
bh_lrus[cpu].bhs[i] = NULL;
}
for (cpu_idx = 0; cpu_idx < NR_CPUS; cpu_idx++)
spin_unlock(&bh_lrus[cpu_idx].lock);
put_cpu();
}
static void invalidate_bh_lrus(void)
{
preempt_disable();
invalidate_bh_lru(NULL);
smp_call_function(invalidate_bh_lru, NULL, 1, 1);
preempt_enable();
}
void set_bh_page(struct buffer_head *bh,
struct page *page, unsigned long offset)
......@@ -2283,7 +2310,13 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
return -EIO;
}
/* The page straddles i_size */
/*
* The page straddles i_size. It must be zeroed out on each and every
* writepage invokation because it may be mmapped. "A file is mapped
* in multiples of the page size. For a file that is not a multiple of
* the page size, the remaining memory is zeroed when mapped, and
* writes to that region are not written out to the file."
*/
kaddr = kmap(page);
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
flush_dcache_page(page);
......@@ -2545,9 +2578,6 @@ void __init buffer_init(void)
{
int i;
for (i = 0; i < NR_CPUS; i++)
spin_lock_init(&bh_lrus[i].lock);
bh_cachep = kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0,
SLAB_HWCACHE_ALIGN, init_buffer_head, NULL);
......
......@@ -209,11 +209,6 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm)
/* XXX: add architecture specific overflow check here. */
pos = bprm->p;
/*
* The only sleeping function which we are allowed to call in
* this loop is copy_from_user(). Otherwise, copy_user_state
* could get trashed.
*/
while (len > 0) {
int i, new, err;
int offset, bytes_to_copy;
......
......@@ -655,8 +655,8 @@ int ext2_empty_dir (struct inode * inode)
}
struct file_operations ext2_dir_operations = {
read: generic_read_dir,
readdir: ext2_readdir,
ioctl: ext2_ioctl,
fsync: ext2_sync_file,
.read = generic_read_dir,
.readdir = ext2_readdir,
.ioctl = ext2_ioctl,
.fsync = ext2_sync_file,
};
......@@ -38,17 +38,17 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
* the ext2 filesystem.
*/
struct file_operations ext2_file_operations = {
llseek: generic_file_llseek,
read: generic_file_read,
write: generic_file_write,
ioctl: ext2_ioctl,
mmap: generic_file_mmap,
open: generic_file_open,
release: ext2_release_file,
fsync: ext2_sync_file,
sendfile: generic_file_sendfile,
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
.ioctl = ext2_ioctl,
.mmap = generic_file_mmap,
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
.sendfile = generic_file_sendfile,
};
struct inode_operations ext2_file_inode_operations = {
truncate: ext2_truncate,
.truncate = ext2_truncate,
};
......@@ -640,16 +640,16 @@ ext2_writepages(struct address_space *mapping, int *nr_to_write)
}
struct address_space_operations ext2_aops = {
readpage: ext2_readpage,
readpages: ext2_readpages,
writepage: ext2_writepage,
sync_page: block_sync_page,
prepare_write: ext2_prepare_write,
commit_write: generic_commit_write,
bmap: ext2_bmap,
direct_IO: ext2_direct_IO,
writepages: ext2_writepages,
vm_writeback: generic_vm_writeback,
.readpage = ext2_readpage,
.readpages = ext2_readpages,
.writepage = ext2_writepage,
.sync_page = block_sync_page,
.prepare_write = ext2_prepare_write,
.commit_write = generic_commit_write,
.bmap = ext2_bmap,
.direct_IO = ext2_direct_IO,
.writepages = ext2_writepages,
.vm_writeback = generic_vm_writeback,
};
/*
......
......@@ -359,13 +359,13 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
}
struct inode_operations ext2_dir_inode_operations = {
create: ext2_create,
lookup: ext2_lookup,
link: ext2_link,
unlink: ext2_unlink,
symlink: ext2_symlink,
mkdir: ext2_mkdir,
rmdir: ext2_rmdir,
mknod: ext2_mknod,
rename: ext2_rename,
.create = ext2_create,
.lookup = ext2_lookup,
.link = ext2_link,
.unlink = ext2_unlink,
.symlink = ext2_symlink,
.mkdir = ext2_mkdir,
.rmdir = ext2_rmdir,
.mknod = ext2_mknod,
.rename = ext2_rename,
};
......@@ -194,16 +194,16 @@ static void destroy_inodecache(void)
}
static struct super_operations ext2_sops = {
alloc_inode: ext2_alloc_inode,
destroy_inode: ext2_destroy_inode,
read_inode: ext2_read_inode,
write_inode: ext2_write_inode,
put_inode: ext2_put_inode,
delete_inode: ext2_delete_inode,
put_super: ext2_put_super,
write_super: ext2_write_super,
statfs: ext2_statfs,
remount_fs: ext2_remount,
.alloc_inode = ext2_alloc_inode,
.destroy_inode = ext2_destroy_inode,
.read_inode = ext2_read_inode,
.write_inode = ext2_write_inode,
.put_inode = ext2_put_inode,
.delete_inode = ext2_delete_inode,
.put_super = ext2_put_super,
.write_super = ext2_write_super,
.statfs = ext2_statfs,
.remount_fs = ext2_remount,
};
/* Yes, most of these are left as NULL!!
......@@ -213,7 +213,7 @@ static struct super_operations ext2_sops = {
*/
struct dentry *ext2_get_parent(struct dentry *child);
static struct export_operations ext2_export_ops = {
get_parent: ext2_get_parent,
.get_parent = ext2_get_parent,
};
/*
......@@ -698,6 +698,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
printk(KERN_ERR "EXT2-fs: get root inode failed\n");
goto failed_mount2;
}
if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
ext2_warning(sb, __FUNCTION__,
"mounting ext3 filesystem as ext2\n");
ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
return 0;
failed_mount2:
......@@ -871,11 +874,11 @@ static struct super_block *ext2_get_sb(struct file_system_type *fs_type,
}
static struct file_system_type ext2_fs_type = {
owner: THIS_MODULE,
name: "ext2",
get_sb: ext2_get_sb,
kill_sb: kill_block_super,
fs_flags: FS_REQUIRES_DEV,
.owner = THIS_MODULE,
.name = "ext2",
.get_sb = ext2_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
static int __init init_ext2_fs(void)
......
......@@ -32,6 +32,6 @@ static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
}
struct inode_operations ext2_fast_symlink_inode_operations = {
readlink: ext2_readlink,
follow_link: ext2_follow_link,
.readlink = ext2_readlink,
.follow_link = ext2_follow_link,
};
......@@ -221,9 +221,9 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
}
static struct inode_operations ncp_symlink_inode_operations = {
readlink: page_readlink,
follow_link: page_follow_link,
setattr: ncp_notify_change,
.readlink = page_readlink,
.follow_link = page_follow_link,
.setattr = ncp_notify_change,
};
/*
......
......@@ -90,7 +90,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
static struct vm_operations_struct ncp_file_mmap =
{
nopage: ncp_file_mmap_nopage,
.nopage = ncp_file_mmap_nopage,
};
......
......@@ -100,7 +100,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
* symlinks can't do much...
*/
struct address_space_operations ncp_symlink_aops = {
readpage: ncp_symlink_readpage,
.readpage = ncp_symlink_readpage,
};
/* ----- create a new symbolic link -------------------------------------- */
......
......@@ -164,14 +164,14 @@ static ssize_t partition_device_kdev_read(struct device *driverfs_dev,
kdev.value=(int)(long)driverfs_dev->driver_data;
return off ? 0 : sprintf (page, "%x\n",kdev.value);
}
static DEVICE_ATTR(kdev,"kdev",S_IRUGO,partition_device_kdev_read,NULL);
static DEVICE_ATTR(kdev,S_IRUGO,partition_device_kdev_read,NULL);
static ssize_t partition_device_type_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
{
return off ? 0 : sprintf (page, "BLK\n");
}
static DEVICE_ATTR(type,"type",S_IRUGO,partition_device_type_read,NULL);
static DEVICE_ATTR(type,S_IRUGO,partition_device_type_read,NULL);
void driverfs_create_partitions(struct gendisk *hd, int minor)
{
......
......@@ -93,9 +93,9 @@ struct bus_attribute {
ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
};
#define BUS_ATTR(_name,_str,_mode,_show,_store) \
#define BUS_ATTR(_name,_mode,_show,_store) \
struct bus_attribute bus_attr_##_name = { \
.attr = {.name = _str, .mode = _mode }, \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
};
......@@ -150,9 +150,9 @@ struct driver_attribute {
ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
};
#define DRIVER_ATTR(_name,_str,_mode,_show,_store) \
#define DRIVER_ATTR(_name,_mode,_show,_store) \
struct driver_attribute driver_attr_##_name = { \
.attr = {.name = _str, .mode = _mode }, \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
};
......@@ -222,13 +222,14 @@ struct device_attribute {
ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
};
#define DEVICE_ATTR(_name,_str,_mode,_show,_store) \
#define DEVICE_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_name = { \
.attr = {.name = _str, .mode = _mode }, \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
};
extern int device_create_file(struct device *device, struct device_attribute * entry);
extern void device_remove_file(struct device * dev, struct device_attribute * attr);
......@@ -260,12 +261,7 @@ static inline void unlock_device(struct device * dev)
* get_device - atomically increment the reference count for the device.
*
*/
static inline void get_device(struct device * dev)
{
BUG_ON(!atomic_read(&dev->refcount));
atomic_inc(&dev->refcount);
}
extern struct device * get_device(struct device * dev);
extern void put_device(struct device * dev);
/* drivers/base/sys.c */
......
......@@ -19,7 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: i2c-dev.h,v 1.10 2001/11/19 19:01:46 mds Exp $ */
/* $Id: i2c-dev.h,v 1.11 2002/07/07 15:42:47 mds Exp $ */
#ifndef I2C_DEV_H
#define I2C_DEV_H
......@@ -144,7 +144,7 @@ static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
else {
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
return data.block[0];
}
}
......@@ -192,6 +192,27 @@ static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
I2C_SMBUS_I2C_BLOCK_DATA, &data);
}
/* Returns the number of read bytes */
static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
__u8 length, __u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_PROC_CALL,&data))
return -1;
else {
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
}
}
#endif /* ndef __KERNEL__ */
#endif
......@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* $Id: i2c-id.h,v 1.41 2002/03/11 07:18:55 simon Exp $ */
/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
#ifndef I2C_ID_H
#define I2C_ID_H
......@@ -90,8 +90,12 @@
#define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
#define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
#define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */
#define I2C_DRIVERID_ADV717x 48 /* ADV 7175/7176 video encoder */
#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */
#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
......@@ -102,6 +106,8 @@
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_I2CPROC 901
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
These were originally in sensors.h in the lm_sensors package */
......@@ -134,6 +140,9 @@
#define I2C_DRIVERID_FSCPOS 1028
#define I2C_DRIVERID_FSCSCY 1029
#define I2C_DRIVERID_PCF8591 1030
#define I2C_DRIVERID_SMSC47M1 1031
#define I2C_DRIVERID_VT1211 1032
#define I2C_DRIVERID_LM92 1033
/*
* ---- Adapter types ----------------------------------------------------
......@@ -155,6 +164,7 @@
#define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
#define I2C_ALGO_EXP 0x800000 /* experimental */
......@@ -182,9 +192,11 @@
#define I2C_HW_B_I810 0x0a /* Intel I810 */
#define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
#define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
#define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
#define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */
......@@ -200,6 +212,10 @@
/* --- ITE based algorithms */
#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
/* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00
#define I2C_HW_SMBUS_ALI15X3 0x01
......
......@@ -23,13 +23,13 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */
/* $Id: i2c.h,v 1.50 2002/03/23 00:53:38 phil Exp $ */
/* $Id: i2c.h,v 1.59 2002/07/19 20:53:45 phil Exp $ */
#ifndef I2C_H
#define I2C_H
#define I2C_DATE "20020322"
#define I2C_VERSION "2.6.3"
#define I2C_DATE "20020719"
#define I2C_VERSION "2.6.4"
#include <linux/i2c-id.h> /* id values of adapters et. al. */
#include <linux/types.h>
......@@ -280,6 +280,9 @@ struct i2c_adapter {
#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */
/* on an i2c_client */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the
......@@ -395,6 +398,12 @@ struct i2c_msg {
#define I2C_FUNC_I2C 0x00000001
#define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
......@@ -409,6 +418,8 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE
......@@ -422,6 +433,17 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2
#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC
#define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC
#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA
#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA
#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA
#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA
#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA
#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \
I2C_FUNC_SMBUS_BYTE | \
......@@ -429,16 +451,20 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK | \
I2C_FUNC_SMBUS_I2C_BLOCK_2
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_I2C_BLOCK
/*
* Data for SMBus Messages
*/
#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
union i2c_smbus_data {
__u8 byte;
__u16 word;
__u8 block[33]; /* block[0] is used for length */
__u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */
/* one more for read length in block process call */
/* and one more for PEC */
};
/* smbus_access read or write markers */
......@@ -454,6 +480,11 @@ union i2c_smbus_data {
#define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 6
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
#define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */
#define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */
#define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */
#define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */
/* ----- commands for the ioctl like i2c_command call:
......@@ -479,6 +510,7 @@ union i2c_smbus_data {
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
#if 0
#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */
#endif
......
......@@ -26,4 +26,12 @@
# define PR_FPEMU_NOPRINT 1 /* silently emulate fp operations accesses */
# define PR_FPEMU_SIGFPE 2 /* don't emulate fp operations, send SIGFPE instead */
/* Get/set floating-point exception mode (if meaningful) */
#define PR_GET_FPEXC 11
#define PR_SET_FPEXC 12
# define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */
# define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */
# define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */
# define PR_FP_EXC_PRECISE 3 /* precise exception mode */
#endif /* _LINUX_PRCTL_H */
......@@ -39,17 +39,14 @@
*/
#ifndef ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *x) {;}
#endif
#ifndef ARCH_HAS_PREFETCHW
#define ARCH_HAS_PREFETCHW
static inline void prefetchw(const void *x) {;}
#endif
#ifndef ARCH_HAS_SPINLOCK_PREFETCH
#define ARCH_HAS_SPINLOCK_PREFETCH
#define spin_lock_prefetch(x) prefetchw(x)
#endif
......
......@@ -131,9 +131,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
struct thread_info *ti;
ti = alloc_thread_info();
if (!ti) return NULL;
if (!ti)
return NULL;
tsk = kmem_cache_alloc(task_struct_cachep,GFP_ATOMIC);
tsk = kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);
if (!tsk) {
free_thread_info(ti);
return NULL;
......
......@@ -344,7 +344,7 @@ EXPORT_SYMBOL(register_disk);
EXPORT_SYMBOL(read_dev_sector);
EXPORT_SYMBOL(init_buffer);
EXPORT_SYMBOL(wipe_partitions);
EXPORT_SYMBOL(generic_file_direct_IO);
EXPORT_SYMBOL_GPL(generic_file_direct_IO);
/* tty routines */
EXPORT_SYMBOL(tty_hangup);
......@@ -505,6 +505,7 @@ EXPORT_SYMBOL(vsscanf);
EXPORT_SYMBOL(kdevname);
EXPORT_SYMBOL(__bdevname);
EXPORT_SYMBOL(cdevname);
EXPORT_SYMBOL(simple_strtoull);
EXPORT_SYMBOL(simple_strtoul);
EXPORT_SYMBOL(simple_strtol);
EXPORT_SYMBOL(system_utsname); /* UTS data */
......
......@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/interrupt.h> /* For in_interrupt() */
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
......@@ -163,12 +164,15 @@ __setup("console=", console_setup);
* 7 -- Enable printk's to console
* 8 -- Set level of messages printed to console
* 9 -- Return number of unread characters in the log buffer
* 10 -- Printk from userspace. Includes loglevel. Returns number of
* chars printed.
*/
int do_syslog(int type, char * buf, int len)
{
unsigned long i, j, limit, count;
int do_clear = 0;
char c;
char *lbuf = NULL;
int error = 0;
switch (type) {
......@@ -283,11 +287,23 @@ int do_syslog(int type, char * buf, int len)
error = log_end - log_start;
spin_unlock_irq(&logbuf_lock);
break;
case 10:
lbuf = kmalloc(len + 1, GFP_KERNEL);
error = -ENOMEM;
if (lbuf == NULL)
break;
error = -EFAULT;
if (copy_from_user(lbuf, buf, len))
break;
lbuf[len] = '\0';
error = printk("%s", lbuf);
break;
default:
error = -EINVAL;
break;
}
out:
kfree(lbuf);
return error;
}
......
......@@ -37,6 +37,12 @@
#ifndef GET_FPEMU_CTL
# define GET_FPEMU_CTL(a,b) (-EINVAL)
#endif
#ifndef SET_FPEXC_CTL
# define SET_FPEXC_CTL(a,b) (-EINVAL)
#endif
#ifndef GET_FPEXC_CTL
# define GET_FPEXC_CTL(a,b) (-EINVAL)
#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
......@@ -1283,6 +1289,13 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
case PR_GET_FPEMU:
error = GET_FPEMU_CTL(current, arg2);
break;
case PR_SET_FPEXC:
error = SET_FPEXC_CTL(current, arg2);
break;
case PR_GET_FPEXC:
error = GET_FPEXC_CTL(current, arg2);
break;
case PR_GET_KEEPCAPS:
if (current->keep_capabilities)
......
......@@ -189,7 +189,9 @@ void * mempool_alloc(mempool_t *pool, int gfp_mask)
int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
repeat_alloc:
current->flags |= PF_NOWARN;
element = pool->alloc(gfp_nowait, pool->pool_data);
current->flags &= ~PF_NOWARN;
if (likely(element != NULL))
return element;
......
......@@ -22,6 +22,8 @@
#include <linux/sysrq.h>
#include <linux/backing-dev.h>
#include <linux/mpage.h>
#include <linux/notifier.h>
#include <linux/smp.h>
/*
* The maximum number of pages to writeout in a single bdflush/kupdate
......@@ -34,10 +36,9 @@
/*
* After a CPU has dirtied this many pages, balance_dirty_pages_ratelimited
* will look to see if it needs to force writeback or throttling. Probably
* should be scaled by memory size.
* will look to see if it needs to force writeback or throttling.
*/
#define RATELIMIT_PAGES ((512 * 1024) / PAGE_SIZE)
static int ratelimit_pages = 32;
/*
* When balance_dirty_pages decides that the caller needs to perform some
......@@ -45,8 +46,10 @@
* It should be somewhat larger than RATELIMIT_PAGES to ensure that reasonably
* large amounts of I/O are submitted.
*/
#define SYNC_WRITEBACK_PAGES ((RATELIMIT_PAGES * 3) / 2)
static inline int sync_writeback_pages(void)
{
return ratelimit_pages + ratelimit_pages / 2;
}
/* The following parameters are exported via /proc/sys/vm */
......@@ -119,12 +122,12 @@ void balance_dirty_pages(struct address_space *mapping)
bdi = mapping->backing_dev_info;
if (dirty_and_writeback > sync_thresh) {
int nr_to_write = SYNC_WRITEBACK_PAGES;
int nr_to_write = sync_writeback_pages();
writeback_backing_dev(bdi, &nr_to_write, WB_SYNC_LAST, NULL);
get_page_state(&ps);
} else if (dirty_and_writeback > async_thresh) {
int nr_to_write = SYNC_WRITEBACK_PAGES;
int nr_to_write = sync_writeback_pages();
writeback_backing_dev(bdi, &nr_to_write, WB_SYNC_NONE, NULL);
get_page_state(&ps);
......@@ -133,6 +136,7 @@ void balance_dirty_pages(struct address_space *mapping)
if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh)
pdflush_operation(background_writeout, 0);
}
EXPORT_SYMBOL_GPL(balance_dirty_pages);
/**
* balance_dirty_pages_ratelimited - balance dirty memory state
......@@ -152,7 +156,7 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
int cpu;
cpu = get_cpu();
if (ratelimits[cpu].count++ >= RATELIMIT_PAGES) {
if (ratelimits[cpu].count++ >= ratelimit_pages) {
ratelimits[cpu].count = 0;
put_cpu();
balance_dirty_pages(mapping);
......@@ -246,16 +250,56 @@ static void wb_timer_fn(unsigned long unused)
}
static int __init wb_timer_init(void)
/*
* If ratelimit_pages is too high then we can get into dirty-data overload
* if a large number of processes all perform writes at the same time.
* If it is too low then SMP machines will call the (expensive) get_page_state
* too often.
*
* Here we set ratelimit_pages to a level which ensures that when all CPUs are
* dirtying in parallel, we cannot go more than 3% (1/32) over the dirty memory
* thresholds before writeback cuts in.
*
* But the limit should not be set too high. Because it also controls the
* amount of memory which the balance_dirty_pages() caller has to write back.
* If this is too large then the caller will block on the IO queue all the
* time. So limit it to four megabytes - the balance_dirty_pages() caller
* will write six megabyte chunks, max.
*/
static void set_ratelimit(void)
{
ratelimit_pages = nr_free_pagecache_pages() / (num_online_cpus() * 32);
if (ratelimit_pages < 16)
ratelimit_pages = 16;
if (ratelimit_pages * PAGE_CACHE_SIZE > 4096 * 1024)
ratelimit_pages = (4096 * 1024) / PAGE_CACHE_SIZE;
}
static int
ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
{
set_ratelimit();
return 0;
}
static struct notifier_block ratelimit_nb = {
.notifier_call = ratelimit_handler,
.next = NULL,
};
static int __init page_writeback_init(void)
{
init_timer(&wb_timer);
wb_timer.expires = jiffies + (dirty_writeback_centisecs * HZ) / 100;
wb_timer.data = 0;
wb_timer.function = wb_timer_fn;
add_timer(&wb_timer);
set_ratelimit();
register_cpu_notifier(&ratelimit_nb);
return 0;
}
module_init(wb_timer_init);
module_init(page_writeback_init);
/*
* A library function, which implements the vm_writeback a_op. It's fairly
......@@ -480,3 +524,5 @@ int __set_page_dirty_nobuffers(struct page *page)
return ret;
}
EXPORT_SYMBOL(__set_page_dirty_nobuffers);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment