Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (55 commits) ieee1394: sbp2: code formatting around work_struct stuff ieee1394: nodemgr: remove a kcalloc ieee1394: conditionally export ieee1394_bus_type ieee1394: Consolidate driver registering ieee1394: sbp2: convert from PCI DMA to generic DMA ieee1394: nodemgr: spaces to tabs ieee1394: nodemgr: fix deadlock in shutdown ieee1394: nodemgr: remove duplicate assignment sbp2: make 1bit bitfield unsigned ieee1394: schedule *_oui sysfs attributes for removal ieee1394: schedule unused symbol exports for removal ieee1394: dv1394: schedule for feature removal ieee1394: raw1394: defer feature removal of old isoch interface ieee1394: ohci1394: call PMac code in shutdown only for proper machines ieee1394: ohci1394: reformat PPC_PMAC platform code ieee1394: ohci1394: add PPC_PMAC platform code to driver probe ieee1394: sbp2: wrap two functions into one ieee1394: sbp2: update comment on things to do ieee1394: sbp2: use list_move_tail() ieee1394: sbp2: more concise names for types and variables ...
This commit is contained in:
commit
c99767974e
18 changed files with 1448 additions and 1914 deletions
|
@ -30,11 +30,39 @@ Who: Adrian Bunk <bunk@stusta.de>
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
|
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
|
||||||
When: November 2006
|
When: June 2007
|
||||||
Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
|
Why: Deprecated in favour of the more efficient and robust rawiso interface.
|
||||||
more efficient. You should really be using libraw1394 for raw1394
|
Affected are applications which use the deprecated part of libraw1394
|
||||||
access anyway.
|
(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
|
||||||
Who: Jody McIntyre <scjody@modernduck.com>
|
raw1394_stop_iso_rcv) or bypass libraw1394.
|
||||||
|
Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: dv1394 driver (CONFIG_IEEE1394_DV1394)
|
||||||
|
When: June 2007
|
||||||
|
Why: Replaced by raw1394 + userspace libraries, notably libiec61883. This
|
||||||
|
shift of application support has been indicated on www.linux1394.org
|
||||||
|
and developers' mailinglists for quite some time. Major applications
|
||||||
|
have been converted, with the exception of ffmpeg and hence xine.
|
||||||
|
Piped output of dvgrab2 is a partial equivalent to dv1394.
|
||||||
|
Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API)
|
||||||
|
When: January 2007
|
||||||
|
Why: There are no projects known to use these exported symbols, except
|
||||||
|
dfg1394 (uses one symbol whose functionality is core-internal now).
|
||||||
|
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB)
|
||||||
|
When: January 2007
|
||||||
|
Files: drivers/ieee1394/: oui.db, oui2c.sh
|
||||||
|
Why: big size, little value
|
||||||
|
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ config IEEE1394_VERBOSEDEBUG
|
||||||
else says N.
|
else says N.
|
||||||
|
|
||||||
config IEEE1394_OUI_DB
|
config IEEE1394_OUI_DB
|
||||||
bool "OUI Database built-in"
|
bool "OUI Database built-in (deprecated)"
|
||||||
depends on IEEE1394
|
depends on IEEE1394
|
||||||
help
|
help
|
||||||
If you say Y here, then an OUI list (vendor unique ID's) will be
|
If you say Y here, then an OUI list (vendor unique ID's) will be
|
||||||
|
@ -67,16 +67,11 @@ config IEEE1394_CONFIG_ROM_IP1394
|
||||||
eth1394 option below.
|
eth1394 option below.
|
||||||
|
|
||||||
config IEEE1394_EXPORT_FULL_API
|
config IEEE1394_EXPORT_FULL_API
|
||||||
bool "Export all symbols of ieee1394's API"
|
bool "Export all symbols of ieee1394's API (deprecated)"
|
||||||
depends on IEEE1394
|
depends on IEEE1394
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Export all symbols of ieee1394's driver programming interface, even
|
This option will be removed soon. Don't worry, say N.
|
||||||
those that are not currently used by the standard IEEE 1394 drivers.
|
|
||||||
|
|
||||||
This option does not affect the interface to userspace applications.
|
|
||||||
Say Y here if you want to compile externally developed drivers that
|
|
||||||
make extended use of ieee1394's API. It is otherwise safe to say N.
|
|
||||||
|
|
||||||
comment "Device Drivers"
|
comment "Device Drivers"
|
||||||
depends on IEEE1394
|
depends on IEEE1394
|
||||||
|
@ -125,7 +120,7 @@ comment "SBP-2 support (for storage devices) requires SCSI"
|
||||||
|
|
||||||
config IEEE1394_SBP2
|
config IEEE1394_SBP2
|
||||||
tristate "SBP-2 support (Harddisks etc.)"
|
tristate "SBP-2 support (Harddisks etc.)"
|
||||||
depends on IEEE1394 && SCSI && (PCI || BROKEN)
|
depends on IEEE1394 && SCSI
|
||||||
help
|
help
|
||||||
This option enables you to use SBP-2 devices connected to an IEEE
|
This option enables you to use SBP-2 devices connected to an IEEE
|
||||||
1394 bus. SBP-2 devices include storage devices like harddisks and
|
1394 bus. SBP-2 devices include storage devices like harddisks and
|
||||||
|
@ -161,17 +156,12 @@ config IEEE1394_ETH1394
|
||||||
MCAP, therefore multicast support is significantly limited.
|
MCAP, therefore multicast support is significantly limited.
|
||||||
|
|
||||||
config IEEE1394_DV1394
|
config IEEE1394_DV1394
|
||||||
tristate "OHCI-DV I/O support"
|
tristate "OHCI-DV I/O support (deprecated)"
|
||||||
depends on IEEE1394 && IEEE1394_OHCI1394
|
depends on IEEE1394 && IEEE1394_OHCI1394
|
||||||
help
|
help
|
||||||
This driver allows you to transmit and receive DV (digital video)
|
The dv1394 driver will be removed from Linux in a future release.
|
||||||
streams on an OHCI-1394 card using a simple frame-oriented
|
Its functionality is now provided by raw1394 together with libraries
|
||||||
interface.
|
such as libiec61883.
|
||||||
|
|
||||||
The user-space API for dv1394 is documented in dv1394.h.
|
|
||||||
|
|
||||||
To compile this driver as a module, say M here: the
|
|
||||||
module will be called dv1394.
|
|
||||||
|
|
||||||
config IEEE1394_RAWIO
|
config IEEE1394_RAWIO
|
||||||
tristate "Raw IEEE1394 I/O support"
|
tristate "Raw IEEE1394 I/O support"
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
|
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
|
||||||
highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
|
highlevel.o csr.o nodemgr.o dma.o iso.o \
|
||||||
csr1212.o config_roms.o
|
csr1212.o config_roms.o
|
||||||
|
ifdef CONFIG_IEEE1394_OUI_DB
|
||||||
|
ieee1394-objs += oui.o
|
||||||
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_IEEE1394) += ieee1394.o
|
obj-$(CONFIG_IEEE1394) += ieee1394.o
|
||||||
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
|
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
|
||||||
|
|
|
@ -158,12 +158,10 @@ static void host_reset(struct hpsb_host *host)
|
||||||
*/
|
*/
|
||||||
static inline void calculate_expire(struct csr_control *csr)
|
static inline void calculate_expire(struct csr_control *csr)
|
||||||
{
|
{
|
||||||
unsigned long usecs =
|
unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 +
|
||||||
(csr->split_timeout_hi & 0x07) * USEC_PER_SEC +
|
(csr->split_timeout_lo >> 19) * 125;
|
||||||
(csr->split_timeout_lo >> 19) * 125L;
|
|
||||||
|
|
||||||
csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L);
|
|
||||||
|
|
||||||
|
csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000);
|
||||||
HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
|
HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1536,28 +1536,21 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count
|
||||||
|
|
||||||
static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct video_card *video;
|
struct video_card *video = file_to_video_card(file);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
|
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
video = file_to_video_card(file);
|
|
||||||
|
|
||||||
/* serialize this to prevent multi-threaded mayhem */
|
/* serialize this to prevent multi-threaded mayhem */
|
||||||
if (file->f_flags & O_NONBLOCK) {
|
if (file->f_flags & O_NONBLOCK) {
|
||||||
if (!mutex_trylock(&video->mtx)) {
|
if (!mutex_trylock(&video->mtx))
|
||||||
unlock_kernel();
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (mutex_lock_interruptible(&video->mtx)) {
|
if (mutex_lock_interruptible(&video->mtx))
|
||||||
unlock_kernel();
|
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch(cmd)
|
switch(cmd)
|
||||||
{
|
{
|
||||||
|
@ -1780,7 +1773,6 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&video->mtx);
|
mutex_unlock(&video->mtx);
|
||||||
unlock_kernel();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2188,12 +2180,8 @@ static struct ieee1394_device_id dv1394_id_table[] = {
|
||||||
MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
|
MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
|
||||||
|
|
||||||
static struct hpsb_protocol_driver dv1394_driver = {
|
static struct hpsb_protocol_driver dv1394_driver = {
|
||||||
.name = "DV/1394 Driver",
|
|
||||||
.id_table = dv1394_id_table,
|
|
||||||
.driver = {
|
|
||||||
.name = "dv1394",
|
.name = "dv1394",
|
||||||
.bus = &ieee1394_bus_type,
|
.id_table = dv1394_id_table,
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2587,6 +2575,10 @@ static int __init dv1394_init_module(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"WARNING: The dv1394 driver is unsupported and will be removed "
|
||||||
|
"from Linux soon. Use raw1394 instead.\n");
|
||||||
|
|
||||||
cdev_init(&dv1394_cdev, &dv1394_fops);
|
cdev_init(&dv1394_cdev, &dv1394_fops);
|
||||||
dv1394_cdev.owner = THIS_MODULE;
|
dv1394_cdev.owner = THIS_MODULE;
|
||||||
kobject_set_name(&dv1394_cdev.kobj, "dv1394");
|
kobject_set_name(&dv1394_cdev.kobj, "dv1394");
|
||||||
|
|
|
@ -474,12 +474,10 @@ static struct ieee1394_device_id eth1394_id_table[] = {
|
||||||
MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
|
MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
|
||||||
|
|
||||||
static struct hpsb_protocol_driver eth1394_proto_driver = {
|
static struct hpsb_protocol_driver eth1394_proto_driver = {
|
||||||
.name = "IPv4 over 1394 Driver",
|
.name = ETH1394_DRIVER_NAME,
|
||||||
.id_table = eth1394_id_table,
|
.id_table = eth1394_id_table,
|
||||||
.update = eth1394_update,
|
.update = eth1394_update,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = ETH1394_DRIVER_NAME,
|
|
||||||
.bus = &ieee1394_bus_type,
|
|
||||||
.probe = eth1394_probe,
|
.probe = eth1394_probe,
|
||||||
.remove = eth1394_remove,
|
.remove = eth1394_remove,
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,7 +24,6 @@ struct hpsb_address_serve {
|
||||||
/* Only the following structures are of interest to actual highlevel drivers. */
|
/* Only the following structures are of interest to actual highlevel drivers. */
|
||||||
|
|
||||||
struct hpsb_highlevel {
|
struct hpsb_highlevel {
|
||||||
struct module *owner;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
/* Any of the following pointers can legally be NULL, except for
|
/* Any of the following pointers can legally be NULL, except for
|
||||||
|
|
|
@ -44,9 +44,10 @@ static void delayed_reset_bus(struct work_struct *work)
|
||||||
|
|
||||||
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
|
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
|
||||||
if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
|
if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
|
||||||
/* CSR image creation failed, reset generation field and do not
|
/* CSR image creation failed.
|
||||||
* issue a bus reset. */
|
* Reset generation field and do not issue a bus reset. */
|
||||||
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation);
|
CSR_SET_BUS_INFO_GENERATION(host->csr.rom,
|
||||||
|
host->csr.generation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +55,8 @@ static void delayed_reset_bus(struct work_struct *work)
|
||||||
|
|
||||||
host->update_config_rom = 0;
|
host->update_config_rom = 0;
|
||||||
if (host->driver->set_hw_config_rom)
|
if (host->driver->set_hw_config_rom)
|
||||||
host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
|
host->driver->set_hw_config_rom(host,
|
||||||
|
host->csr.rom->bus_info_data);
|
||||||
|
|
||||||
host->csr.gen_timestamp[host->csr.generation] = jiffies;
|
host->csr.gen_timestamp[host->csr.generation] = jiffies;
|
||||||
hpsb_reset_bus(host, SHORT_RESET);
|
hpsb_reset_bus(host, SHORT_RESET);
|
||||||
|
@ -70,7 +72,8 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
|
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -128,10 +131,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
|
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
|
||||||
if (!h->csr.rom) {
|
if (!h->csr.rom)
|
||||||
kfree(h);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
h->hostdata = h + 1;
|
h->hostdata = h + 1;
|
||||||
h->driver = drv;
|
h->driver = drv;
|
||||||
|
@ -151,16 +152,15 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
|
||||||
init_timer(&h->timeout);
|
init_timer(&h->timeout);
|
||||||
h->timeout.data = (unsigned long) h;
|
h->timeout.data = (unsigned long) h;
|
||||||
h->timeout.function = abort_timedouts;
|
h->timeout.function = abort_timedouts;
|
||||||
h->timeout_interval = HZ / 20; // 50ms by default
|
h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */
|
||||||
|
|
||||||
h->topology_map = h->csr.topology_map + 3;
|
h->topology_map = h->csr.topology_map + 3;
|
||||||
h->speed_map = (u8 *)(h->csr.speed_map + 2);
|
h->speed_map = (u8 *)(h->csr.speed_map + 2);
|
||||||
|
|
||||||
mutex_lock(&host_num_alloc);
|
mutex_lock(&host_num_alloc);
|
||||||
|
|
||||||
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
|
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
|
||||||
hostnum++;
|
hostnum++;
|
||||||
|
mutex_unlock(&host_num_alloc);
|
||||||
h->id = hostnum;
|
h->id = hostnum;
|
||||||
|
|
||||||
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
|
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
|
||||||
|
@ -171,13 +171,19 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
|
||||||
h->class_dev.class = &hpsb_host_class;
|
h->class_dev.class = &hpsb_host_class;
|
||||||
snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
|
snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
|
||||||
|
|
||||||
device_register(&h->device);
|
if (device_register(&h->device))
|
||||||
class_device_register(&h->class_dev);
|
goto fail;
|
||||||
|
if (class_device_register(&h->class_dev)) {
|
||||||
|
device_unregister(&h->device);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
get_device(&h->device);
|
get_device(&h->device);
|
||||||
|
|
||||||
mutex_unlock(&host_num_alloc);
|
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
kfree(h);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hpsb_add_host(struct hpsb_host *host)
|
int hpsb_add_host(struct hpsb_host *host)
|
||||||
|
@ -229,7 +235,8 @@ int hpsb_update_config_rom_image(struct hpsb_host *host)
|
||||||
if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
|
if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
|
||||||
/* Wait 60 seconds from the last time this generation number was
|
/* Wait 60 seconds from the last time this generation number was
|
||||||
* used. */
|
* used. */
|
||||||
reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
|
reset_delay =
|
||||||
|
(60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
|
||||||
else
|
else
|
||||||
/* Wait 1 second in case some other code wants to change the
|
/* Wait 1 second in case some other code wants to change the
|
||||||
* Config ROM in the near future. */
|
* Config ROM in the near future. */
|
||||||
|
|
|
@ -1237,10 +1237,10 @@ EXPORT_SYMBOL(highlevel_remove_host);
|
||||||
/** nodemgr.c **/
|
/** nodemgr.c **/
|
||||||
EXPORT_SYMBOL(hpsb_node_fill_packet);
|
EXPORT_SYMBOL(hpsb_node_fill_packet);
|
||||||
EXPORT_SYMBOL(hpsb_node_write);
|
EXPORT_SYMBOL(hpsb_node_write);
|
||||||
EXPORT_SYMBOL(hpsb_register_protocol);
|
EXPORT_SYMBOL(__hpsb_register_protocol);
|
||||||
EXPORT_SYMBOL(hpsb_unregister_protocol);
|
EXPORT_SYMBOL(hpsb_unregister_protocol);
|
||||||
EXPORT_SYMBOL(ieee1394_bus_type);
|
|
||||||
#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
|
#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
|
||||||
|
EXPORT_SYMBOL(ieee1394_bus_type);
|
||||||
EXPORT_SYMBOL(nodemgr_for_each_host);
|
EXPORT_SYMBOL(nodemgr_for_each_host);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
|
@ -67,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
||||||
{
|
{
|
||||||
quadlet_t q;
|
quadlet_t q;
|
||||||
u8 i, *speed, old_speed, good_speed;
|
u8 i, *speed, old_speed, good_speed;
|
||||||
int ret;
|
int error;
|
||||||
|
|
||||||
speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
|
speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
|
||||||
old_speed = *speed;
|
old_speed = *speed;
|
||||||
|
@ -79,9 +80,9 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
||||||
* just finished its initialization. */
|
* just finished its initialization. */
|
||||||
for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
|
for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
|
||||||
*speed = i;
|
*speed = i;
|
||||||
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||||
&q, sizeof(quadlet_t));
|
&q, sizeof(quadlet_t));
|
||||||
if (ret)
|
if (error)
|
||||||
break;
|
break;
|
||||||
*buffer = q;
|
*buffer = q;
|
||||||
good_speed = i;
|
good_speed = i;
|
||||||
|
@ -95,19 +96,19 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*speed = old_speed;
|
*speed = old_speed;
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
|
static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
|
||||||
void *buffer, void *__ci)
|
void *buffer, void *__ci)
|
||||||
{
|
{
|
||||||
struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
|
struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
|
||||||
int i, ret;
|
int i, error;
|
||||||
|
|
||||||
for (i = 1; ; i++) {
|
for (i = 1; ; i++) {
|
||||||
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||||
buffer, length);
|
buffer, length);
|
||||||
if (!ret) {
|
if (!error) {
|
||||||
ci->speed_unverified = 0;
|
ci->speed_unverified = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -118,14 +119,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
|
||||||
/* The ieee1394_core guessed the node's speed capability from
|
/* The ieee1394_core guessed the node's speed capability from
|
||||||
* the self ID. Check whether a lower speed works. */
|
* the self ID. Check whether a lower speed works. */
|
||||||
if (ci->speed_unverified && length == sizeof(quadlet_t)) {
|
if (ci->speed_unverified && length == sizeof(quadlet_t)) {
|
||||||
ret = nodemgr_check_speed(ci, addr, buffer);
|
error = nodemgr_check_speed(ci, addr, buffer);
|
||||||
if (!ret)
|
if (!error)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (msleep_interruptible(334))
|
if (msleep_interruptible(334))
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
|
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
|
||||||
|
@ -260,9 +261,20 @@ static struct device nodemgr_dev_template_ne = {
|
||||||
.release = nodemgr_release_ne,
|
.release = nodemgr_release_ne,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This dummy driver prevents the host devices from being scanned. We have no
|
||||||
|
* useful drivers for them yet, and there would be a deadlock possible if the
|
||||||
|
* driver core scans the host device while the host's low-level driver (i.e.
|
||||||
|
* the host's parent device) is being removed. */
|
||||||
|
static struct device_driver nodemgr_mid_layer_driver = {
|
||||||
|
.bus = &ieee1394_bus_type,
|
||||||
|
.name = "nodemgr",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
struct device nodemgr_dev_template_host = {
|
struct device nodemgr_dev_template_host = {
|
||||||
.bus = &ieee1394_bus_type,
|
.bus = &ieee1394_bus_type,
|
||||||
.release = nodemgr_release_host,
|
.release = nodemgr_release_host,
|
||||||
|
.driver = &nodemgr_mid_layer_driver,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,7 +374,7 @@ static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
|
||||||
#endif
|
#endif
|
||||||
spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
|
spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
|
||||||
|
|
||||||
return sprintf(buf, "0x%016llx\n", tm);
|
return sprintf(buf, "0x%016llx\n", (unsigned long long)tm);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
|
static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
|
||||||
#endif /* HPSB_DEBUG_TLABELS */
|
#endif /* HPSB_DEBUG_TLABELS */
|
||||||
|
@ -374,11 +386,11 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute
|
||||||
int state = simple_strtoul(buf, NULL, 10);
|
int state = simple_strtoul(buf, NULL, 10);
|
||||||
|
|
||||||
if (state == 1) {
|
if (state == 1) {
|
||||||
down_write(&dev->bus->subsys.rwsem);
|
|
||||||
device_release_driver(dev);
|
|
||||||
ud->ignore_driver = 1;
|
ud->ignore_driver = 1;
|
||||||
up_write(&dev->bus->subsys.rwsem);
|
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
} else if (!state)
|
device_release_driver(dev);
|
||||||
|
up_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
|
} else if (state == 0)
|
||||||
ud->ignore_driver = 0;
|
ud->ignore_driver = 0;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -413,11 +425,14 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
|
||||||
static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
|
static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
|
||||||
|
|
||||||
|
|
||||||
static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count)
|
static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if (simple_strtoul(buf, NULL, 10) == 1)
|
if (simple_strtoul(buf, NULL, 10) == 1)
|
||||||
bus_rescan_devices(&ieee1394_bus_type);
|
error = bus_rescan_devices(&ieee1394_bus_type);
|
||||||
return count;
|
return error ? error : count;
|
||||||
}
|
}
|
||||||
static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
|
static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -433,7 +448,7 @@ static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size
|
||||||
|
|
||||||
if (state == 1)
|
if (state == 1)
|
||||||
ignore_drivers = 1;
|
ignore_drivers = 1;
|
||||||
else if (!state)
|
else if (state == 0)
|
||||||
ignore_drivers = 0;
|
ignore_drivers = 0;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -583,7 +598,11 @@ static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
|
||||||
driver_create_file(drv, fw_drv_attrs[i]);
|
if (driver_create_file(drv, fw_drv_attrs[i]))
|
||||||
|
goto fail;
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to add sysfs attribute for driver %s", driver->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -603,7 +622,12 @@ static void nodemgr_create_ne_dev_files(struct node_entry *ne)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
|
||||||
device_create_file(dev, fw_ne_attrs[i]);
|
if (device_create_file(dev, fw_ne_attrs[i]))
|
||||||
|
goto fail;
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
|
||||||
|
(unsigned long long)ne->guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -613,11 +637,16 @@ static void nodemgr_create_host_dev_files(struct hpsb_host *host)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++)
|
||||||
device_create_file(dev, fw_host_attrs[i]);
|
if (device_create_file(dev, fw_host_attrs[i]))
|
||||||
|
goto fail;
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to add sysfs attribute for host %d", host->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid);
|
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
|
||||||
|
nodeid_t nodeid);
|
||||||
|
|
||||||
static void nodemgr_update_host_dev_links(struct hpsb_host *host)
|
static void nodemgr_update_host_dev_links(struct hpsb_host *host)
|
||||||
{
|
{
|
||||||
|
@ -628,12 +657,18 @@ static void nodemgr_update_host_dev_links(struct hpsb_host *host)
|
||||||
sysfs_remove_link(&dev->kobj, "busmgr_id");
|
sysfs_remove_link(&dev->kobj, "busmgr_id");
|
||||||
sysfs_remove_link(&dev->kobj, "host_id");
|
sysfs_remove_link(&dev->kobj, "host_id");
|
||||||
|
|
||||||
if ((ne = find_entry_by_nodeid(host, host->irm_id)))
|
if ((ne = find_entry_by_nodeid(host, host->irm_id)) &&
|
||||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id");
|
sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"))
|
||||||
if ((ne = find_entry_by_nodeid(host, host->busmgr_id)))
|
goto fail;
|
||||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id");
|
if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) &&
|
||||||
if ((ne = find_entry_by_nodeid(host, host->node_id)))
|
sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"))
|
||||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id");
|
goto fail;
|
||||||
|
if ((ne = find_entry_by_nodeid(host, host->node_id)) &&
|
||||||
|
sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"))
|
||||||
|
goto fail;
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to update sysfs attributes for host %d", host->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
|
static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
|
||||||
|
@ -642,25 +677,32 @@ static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
|
||||||
device_create_file(dev, fw_ud_attrs[i]);
|
if (device_create_file(dev, fw_ud_attrs[i]))
|
||||||
|
goto fail;
|
||||||
if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
|
if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
|
||||||
device_create_file(dev, &dev_attr_ud_specifier_id);
|
if (device_create_file(dev, &dev_attr_ud_specifier_id))
|
||||||
|
goto fail;
|
||||||
if (ud->flags & UNIT_DIRECTORY_VERSION)
|
if (ud->flags & UNIT_DIRECTORY_VERSION)
|
||||||
device_create_file(dev, &dev_attr_ud_version);
|
if (device_create_file(dev, &dev_attr_ud_version))
|
||||||
|
goto fail;
|
||||||
if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
|
if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
|
||||||
device_create_file(dev, &dev_attr_ud_vendor_id);
|
if (device_create_file(dev, &dev_attr_ud_vendor_id))
|
||||||
if (ud->vendor_name_kv)
|
goto fail;
|
||||||
device_create_file(dev, &dev_attr_ud_vendor_name_kv);
|
if (ud->vendor_name_kv &&
|
||||||
|
device_create_file(dev, &dev_attr_ud_vendor_name_kv))
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
|
if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
|
||||||
device_create_file(dev, &dev_attr_ud_model_id);
|
if (device_create_file(dev, &dev_attr_ud_model_id))
|
||||||
if (ud->model_name_kv)
|
goto fail;
|
||||||
device_create_file(dev, &dev_attr_ud_model_name_kv);
|
if (ud->model_name_kv &&
|
||||||
|
device_create_file(dev, &dev_attr_ud_model_name_kv))
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to add sysfs attributes for unit %s",
|
||||||
|
ud->device.bus_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -675,11 +717,14 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ud = container_of(dev, struct unit_directory, device);
|
ud = container_of(dev, struct unit_directory, device);
|
||||||
driver = container_of(drv, struct hpsb_protocol_driver, driver);
|
|
||||||
|
|
||||||
if (ud->ne->in_limbo || ud->ignore_driver)
|
if (ud->ne->in_limbo || ud->ignore_driver)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* We only match drivers of type hpsb_protocol_driver */
|
||||||
|
if (drv == &nodemgr_mid_layer_driver)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
driver = container_of(drv, struct hpsb_protocol_driver, driver);
|
||||||
for (id = driver->id_table; id->match_flags != 0; id++) {
|
for (id = driver->id_table; id->match_flags != 0; id++) {
|
||||||
if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
|
if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
|
||||||
id->vendor_id != ud->vendor_id)
|
id->vendor_id != ud->vendor_id)
|
||||||
|
@ -704,26 +749,45 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
|
||||||
|
|
||||||
static void nodemgr_remove_uds(struct node_entry *ne)
|
static void nodemgr_remove_uds(struct node_entry *ne)
|
||||||
{
|
{
|
||||||
struct class_device *cdev, *next;
|
struct class_device *cdev;
|
||||||
struct unit_directory *ud;
|
struct unit_directory *tmp, *ud;
|
||||||
|
|
||||||
list_for_each_entry_safe(cdev, next, &nodemgr_ud_class.children, node) {
|
|
||||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
|
||||||
|
|
||||||
if (ud->ne != ne)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
/* Iteration over nodemgr_ud_class.children has to be protected by
|
||||||
|
* nodemgr_ud_class.sem, but class_device_unregister() will eventually
|
||||||
|
* take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
|
||||||
|
* release the semaphore, and then unregister the ud. Since this code
|
||||||
|
* may be called from other contexts besides the knodemgrds, protect the
|
||||||
|
* gap after release of the semaphore by nodemgr_serialize_remove_uds.
|
||||||
|
*/
|
||||||
|
mutex_lock(&nodemgr_serialize_remove_uds);
|
||||||
|
for (;;) {
|
||||||
|
ud = NULL;
|
||||||
|
down(&nodemgr_ud_class.sem);
|
||||||
|
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||||
|
tmp = container_of(cdev, struct unit_directory,
|
||||||
|
class_dev);
|
||||||
|
if (tmp->ne == ne) {
|
||||||
|
ud = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
up(&nodemgr_ud_class.sem);
|
||||||
|
if (ud == NULL)
|
||||||
|
break;
|
||||||
class_device_unregister(&ud->class_dev);
|
class_device_unregister(&ud->class_dev);
|
||||||
device_unregister(&ud->device);
|
device_unregister(&ud->device);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&nodemgr_serialize_remove_uds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nodemgr_remove_ne(struct node_entry *ne)
|
static void nodemgr_remove_ne(struct node_entry *ne)
|
||||||
{
|
{
|
||||||
struct device *dev = &ne->device;
|
struct device *dev;
|
||||||
|
|
||||||
dev = get_device(&ne->device);
|
dev = get_device(&ne->device);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
@ -748,7 +812,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data)
|
||||||
|
|
||||||
static void nodemgr_remove_host_dev(struct device *dev)
|
static void nodemgr_remove_host_dev(struct device *dev)
|
||||||
{
|
{
|
||||||
device_for_each_child(dev, NULL, __nodemgr_remove_host_dev);
|
WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev));
|
||||||
sysfs_remove_link(&dev->kobj, "irm_id");
|
sysfs_remove_link(&dev->kobj, "irm_id");
|
||||||
sysfs_remove_link(&dev->kobj, "busmgr_id");
|
sysfs_remove_link(&dev->kobj, "busmgr_id");
|
||||||
sysfs_remove_link(&dev->kobj, "host_id");
|
sysfs_remove_link(&dev->kobj, "host_id");
|
||||||
|
@ -792,7 +856,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
|
||||||
|
|
||||||
ne = kzalloc(sizeof(*ne), GFP_KERNEL);
|
ne = kzalloc(sizeof(*ne), GFP_KERNEL);
|
||||||
if (!ne)
|
if (!ne)
|
||||||
return NULL;
|
goto fail_alloc;
|
||||||
|
|
||||||
ne->host = host;
|
ne->host = host;
|
||||||
ne->nodeid = nodeid;
|
ne->nodeid = nodeid;
|
||||||
|
@ -815,12 +879,15 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
|
||||||
snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
|
snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
|
||||||
(unsigned long long)(ne->guid));
|
(unsigned long long)(ne->guid));
|
||||||
|
|
||||||
device_register(&ne->device);
|
if (device_register(&ne->device))
|
||||||
class_device_register(&ne->class_dev);
|
goto fail_devreg;
|
||||||
|
if (class_device_register(&ne->class_dev))
|
||||||
|
goto fail_classdevreg;
|
||||||
get_device(&ne->device);
|
get_device(&ne->device);
|
||||||
|
|
||||||
if (ne->guid_vendor_oui)
|
if (ne->guid_vendor_oui &&
|
||||||
device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui);
|
device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui))
|
||||||
|
goto fail_addoiu;
|
||||||
nodemgr_create_ne_dev_files(ne);
|
nodemgr_create_ne_dev_files(ne);
|
||||||
|
|
||||||
nodemgr_update_bus_options(ne);
|
nodemgr_update_bus_options(ne);
|
||||||
|
@ -830,17 +897,28 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
|
||||||
NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
|
NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
|
||||||
|
|
||||||
return ne;
|
return ne;
|
||||||
|
|
||||||
|
fail_addoiu:
|
||||||
|
put_device(&ne->device);
|
||||||
|
fail_classdevreg:
|
||||||
|
device_unregister(&ne->device);
|
||||||
|
fail_devreg:
|
||||||
|
kfree(ne);
|
||||||
|
fail_alloc:
|
||||||
|
HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
|
||||||
|
NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct node_entry *find_entry_by_guid(u64 guid)
|
static struct node_entry *find_entry_by_guid(u64 guid)
|
||||||
{
|
{
|
||||||
struct class *class = &nodemgr_ne_class;
|
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
struct node_entry *ne, *ret_ne = NULL;
|
struct node_entry *ne, *ret_ne = NULL;
|
||||||
|
|
||||||
down_read(&class->subsys.rwsem);
|
down(&nodemgr_ne_class.sem);
|
||||||
list_for_each_entry(cdev, &class->children, node) {
|
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||||
ne = container_of(cdev, struct node_entry, class_dev);
|
ne = container_of(cdev, struct node_entry, class_dev);
|
||||||
|
|
||||||
if (ne->guid == guid) {
|
if (ne->guid == guid) {
|
||||||
|
@ -848,20 +926,20 @@ static struct node_entry *find_entry_by_guid(u64 guid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_read(&class->subsys.rwsem);
|
up(&nodemgr_ne_class.sem);
|
||||||
|
|
||||||
return ret_ne;
|
return ret_ne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid)
|
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
|
||||||
|
nodeid_t nodeid)
|
||||||
{
|
{
|
||||||
struct class *class = &nodemgr_ne_class;
|
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
struct node_entry *ne, *ret_ne = NULL;
|
struct node_entry *ne, *ret_ne = NULL;
|
||||||
|
|
||||||
down_read(&class->subsys.rwsem);
|
down(&nodemgr_ne_class.sem);
|
||||||
list_for_each_entry(cdev, &class->children, node) {
|
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||||
ne = container_of(cdev, struct node_entry, class_dev);
|
ne = container_of(cdev, struct node_entry, class_dev);
|
||||||
|
|
||||||
if (ne->host == host && ne->nodeid == nodeid) {
|
if (ne->host == host && ne->nodeid == nodeid) {
|
||||||
|
@ -869,7 +947,7 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_read(&class->subsys.rwsem);
|
up(&nodemgr_ne_class.sem);
|
||||||
|
|
||||||
return ret_ne;
|
return ret_ne;
|
||||||
}
|
}
|
||||||
|
@ -891,13 +969,25 @@ static void nodemgr_register_device(struct node_entry *ne,
|
||||||
snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
|
snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
|
||||||
ne->device.bus_id, ud->id);
|
ne->device.bus_id, ud->id);
|
||||||
|
|
||||||
device_register(&ud->device);
|
if (device_register(&ud->device))
|
||||||
class_device_register(&ud->class_dev);
|
goto fail_devreg;
|
||||||
|
if (class_device_register(&ud->class_dev))
|
||||||
|
goto fail_classdevreg;
|
||||||
get_device(&ud->device);
|
get_device(&ud->device);
|
||||||
|
|
||||||
if (ud->vendor_oui)
|
if (ud->vendor_oui &&
|
||||||
device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
|
device_create_file(&ud->device, &dev_attr_ud_vendor_oui))
|
||||||
|
goto fail_addoui;
|
||||||
nodemgr_create_ud_dev_files(ud);
|
nodemgr_create_ud_dev_files(ud);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail_addoui:
|
||||||
|
put_device(&ud->device);
|
||||||
|
fail_classdevreg:
|
||||||
|
device_unregister(&ud->device);
|
||||||
|
fail_devreg:
|
||||||
|
HPSB_ERR("Failed to create unit %s", ud->device.bus_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -977,10 +1067,9 @@ static struct unit_directory *nodemgr_process_unit_directory
|
||||||
/* Logical Unit Number */
|
/* Logical Unit Number */
|
||||||
if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
|
if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
|
||||||
if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
|
if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
|
||||||
ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL);
|
ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL);
|
||||||
if (!ud_child)
|
if (!ud_child)
|
||||||
goto unit_directory_error;
|
goto unit_directory_error;
|
||||||
memcpy(ud_child, ud, sizeof(*ud_child));
|
|
||||||
nodemgr_register_device(ne, ud_child, &ne->device);
|
nodemgr_register_device(ne, ud_child, &ne->device);
|
||||||
ud_child = NULL;
|
ud_child = NULL;
|
||||||
|
|
||||||
|
@ -1094,10 +1183,16 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
|
||||||
last_key_id = kv->key.id;
|
last_key_id = kv->key.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ne->vendor_oui)
|
if (ne->vendor_oui &&
|
||||||
device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
|
device_create_file(&ne->device, &dev_attr_ne_vendor_oui))
|
||||||
if (ne->vendor_name_kv)
|
goto fail;
|
||||||
device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv);
|
if (ne->vendor_name_kv &&
|
||||||
|
device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv))
|
||||||
|
goto fail;
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
|
||||||
|
(unsigned long long)ne->guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
@ -1161,16 +1256,20 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
|
||||||
#endif /* CONFIG_HOTPLUG */
|
#endif /* CONFIG_HOTPLUG */
|
||||||
|
|
||||||
|
|
||||||
int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
|
int __hpsb_register_protocol(struct hpsb_protocol_driver *drv,
|
||||||
|
struct module *owner)
|
||||||
{
|
{
|
||||||
int ret;
|
int error;
|
||||||
|
|
||||||
|
drv->driver.bus = &ieee1394_bus_type;
|
||||||
|
drv->driver.owner = owner;
|
||||||
|
drv->driver.name = drv->name;
|
||||||
|
|
||||||
/* This will cause a probe for devices */
|
/* This will cause a probe for devices */
|
||||||
ret = driver_register(&driver->driver);
|
error = driver_register(&drv->driver);
|
||||||
if (!ret)
|
if (!error)
|
||||||
nodemgr_create_drv_files(driver);
|
nodemgr_create_drv_files(drv);
|
||||||
|
return error;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
|
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
|
||||||
|
@ -1317,7 +1416,6 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
|
|
||||||
static void nodemgr_suspend_ne(struct node_entry *ne)
|
static void nodemgr_suspend_ne(struct node_entry *ne)
|
||||||
{
|
{
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
|
@ -1327,21 +1425,22 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
|
||||||
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
|
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
|
||||||
|
|
||||||
ne->in_limbo = 1;
|
ne->in_limbo = 1;
|
||||||
device_create_file(&ne->device, &dev_attr_ne_in_limbo);
|
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
|
||||||
|
|
||||||
down_write(&ne->device.bus->subsys.rwsem);
|
down(&nodemgr_ud_class.sem);
|
||||||
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||||
|
|
||||||
if (ud->ne != ne)
|
if (ud->ne != ne)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
if (ud->device.driver &&
|
if (ud->device.driver &&
|
||||||
(!ud->device.driver->suspend ||
|
(!ud->device.driver->suspend ||
|
||||||
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
|
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
|
||||||
device_release_driver(&ud->device);
|
device_release_driver(&ud->device);
|
||||||
|
up_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
}
|
}
|
||||||
up_write(&ne->device.bus->subsys.rwsem);
|
up(&nodemgr_ud_class.sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1353,45 +1452,47 @@ static void nodemgr_resume_ne(struct node_entry *ne)
|
||||||
ne->in_limbo = 0;
|
ne->in_limbo = 0;
|
||||||
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
|
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
|
||||||
|
|
||||||
down_read(&nodemgr_ud_class.subsys.rwsem);
|
down(&nodemgr_ud_class.sem);
|
||||||
down_read(&ne->device.bus->subsys.rwsem);
|
|
||||||
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||||
|
|
||||||
if (ud->ne != ne)
|
if (ud->ne != ne)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
down_read(&ieee1394_bus_type.subsys.rwsem);
|
||||||
if (ud->device.driver && ud->device.driver->resume)
|
if (ud->device.driver && ud->device.driver->resume)
|
||||||
ud->device.driver->resume(&ud->device);
|
ud->device.driver->resume(&ud->device);
|
||||||
|
up_read(&ieee1394_bus_type.subsys.rwsem);
|
||||||
}
|
}
|
||||||
up_read(&ne->device.bus->subsys.rwsem);
|
up(&nodemgr_ud_class.sem);
|
||||||
up_read(&nodemgr_ud_class.subsys.rwsem);
|
|
||||||
|
|
||||||
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
|
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
|
||||||
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
|
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
|
|
||||||
static void nodemgr_update_pdrv(struct node_entry *ne)
|
static void nodemgr_update_pdrv(struct node_entry *ne)
|
||||||
{
|
{
|
||||||
struct unit_directory *ud;
|
struct unit_directory *ud;
|
||||||
struct hpsb_protocol_driver *pdrv;
|
struct hpsb_protocol_driver *pdrv;
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
|
|
||||||
|
down(&nodemgr_ud_class.sem);
|
||||||
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||||
if (ud->ne != ne || !ud->device.driver)
|
if (ud->ne != ne)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
|
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
|
if (ud->device.driver) {
|
||||||
if (pdrv->update && pdrv->update(ud)) {
|
pdrv = container_of(ud->device.driver,
|
||||||
down_write(&ud->device.bus->subsys.rwsem);
|
struct hpsb_protocol_driver,
|
||||||
|
driver);
|
||||||
|
if (pdrv->update && pdrv->update(ud))
|
||||||
device_release_driver(&ud->device);
|
device_release_driver(&ud->device);
|
||||||
up_write(&ud->device.bus->subsys.rwsem);
|
|
||||||
}
|
}
|
||||||
|
up_write(&ieee1394_bus_type.subsys.rwsem);
|
||||||
}
|
}
|
||||||
|
up(&nodemgr_ud_class.sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1405,7 +1506,7 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
|
||||||
{
|
{
|
||||||
const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
|
const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
|
||||||
quadlet_t bc_remote, bc_local;
|
quadlet_t bc_remote, bc_local;
|
||||||
int ret;
|
int error;
|
||||||
|
|
||||||
if (!ne->host->is_irm || ne->generation != generation ||
|
if (!ne->host->is_irm || ne->generation != generation ||
|
||||||
ne->nodeid == ne->host->node_id)
|
ne->nodeid == ne->host->node_id)
|
||||||
|
@ -1414,16 +1515,14 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
|
||||||
bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
|
bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
|
||||||
|
|
||||||
/* Check if the register is implemented and 1394a compliant. */
|
/* Check if the register is implemented and 1394a compliant. */
|
||||||
ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
|
error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
|
||||||
sizeof(bc_remote));
|
sizeof(bc_remote));
|
||||||
if (!ret && bc_remote & cpu_to_be32(0x80000000) &&
|
if (!error && bc_remote & cpu_to_be32(0x80000000) &&
|
||||||
bc_remote != bc_local)
|
bc_remote != bc_local)
|
||||||
hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
|
hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the
|
|
||||||
* calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */
|
|
||||||
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
|
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@ -1456,7 +1555,6 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
|
||||||
static void nodemgr_node_probe(struct host_info *hi, int generation)
|
static void nodemgr_node_probe(struct host_info *hi, int generation)
|
||||||
{
|
{
|
||||||
struct hpsb_host *host = hi->host;
|
struct hpsb_host *host = hi->host;
|
||||||
struct class *class = &nodemgr_ne_class;
|
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
struct node_entry *ne;
|
struct node_entry *ne;
|
||||||
|
|
||||||
|
@ -1469,18 +1567,18 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
|
||||||
* while probes are time-consuming. (Well, those probes need some
|
* while probes are time-consuming. (Well, those probes need some
|
||||||
* improvement...) */
|
* improvement...) */
|
||||||
|
|
||||||
down_read(&class->subsys.rwsem);
|
down(&nodemgr_ne_class.sem);
|
||||||
list_for_each_entry(cdev, &class->children, node) {
|
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||||
ne = container_of(cdev, struct node_entry, class_dev);
|
ne = container_of(cdev, struct node_entry, class_dev);
|
||||||
if (!ne->needs_probe)
|
if (!ne->needs_probe)
|
||||||
nodemgr_probe_ne(hi, ne, generation);
|
nodemgr_probe_ne(hi, ne, generation);
|
||||||
}
|
}
|
||||||
list_for_each_entry(cdev, &class->children, node) {
|
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||||
ne = container_of(cdev, struct node_entry, class_dev);
|
ne = container_of(cdev, struct node_entry, class_dev);
|
||||||
if (ne->needs_probe)
|
if (ne->needs_probe)
|
||||||
nodemgr_probe_ne(hi, ne, generation);
|
nodemgr_probe_ne(hi, ne, generation);
|
||||||
}
|
}
|
||||||
up_read(&class->subsys.rwsem);
|
up(&nodemgr_ne_class.sem);
|
||||||
|
|
||||||
|
|
||||||
/* If we had a bus reset while we were scanning the bus, it is
|
/* If we had a bus reset while we were scanning the bus, it is
|
||||||
|
@ -1498,15 +1596,14 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
|
||||||
* just removed. */
|
* just removed. */
|
||||||
|
|
||||||
if (generation == get_hpsb_generation(host))
|
if (generation == get_hpsb_generation(host))
|
||||||
bus_rescan_devices(&ieee1394_bus_type);
|
if (bus_rescan_devices(&ieee1394_bus_type))
|
||||||
|
HPSB_DEBUG("bus_rescan_devices had an error");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nodemgr_send_resume_packet(struct hpsb_host *host)
|
static int nodemgr_send_resume_packet(struct hpsb_host *host)
|
||||||
{
|
{
|
||||||
struct hpsb_packet *packet;
|
struct hpsb_packet *packet;
|
||||||
int ret = 1;
|
int error = -ENOMEM;
|
||||||
|
|
||||||
packet = hpsb_make_phypacket(host,
|
packet = hpsb_make_phypacket(host,
|
||||||
EXTPHYPACKET_TYPE_RESUME |
|
EXTPHYPACKET_TYPE_RESUME |
|
||||||
|
@ -1514,12 +1611,12 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
|
||||||
if (packet) {
|
if (packet) {
|
||||||
packet->no_waiter = 1;
|
packet->no_waiter = 1;
|
||||||
packet->generation = get_hpsb_generation(host);
|
packet->generation = get_hpsb_generation(host);
|
||||||
ret = hpsb_send_packet(packet);
|
error = hpsb_send_packet(packet);
|
||||||
}
|
}
|
||||||
if (ret)
|
if (error)
|
||||||
HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
|
HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
|
||||||
host->id);
|
host->id);
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform a few high-level IRM responsibilities. */
|
/* Perform a few high-level IRM responsibilities. */
|
||||||
|
@ -1692,19 +1789,18 @@ exit:
|
||||||
|
|
||||||
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
|
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
|
||||||
{
|
{
|
||||||
struct class *class = &hpsb_host_class;
|
|
||||||
struct class_device *cdev;
|
struct class_device *cdev;
|
||||||
struct hpsb_host *host;
|
struct hpsb_host *host;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
down_read(&class->subsys.rwsem);
|
down(&hpsb_host_class.sem);
|
||||||
list_for_each_entry(cdev, &class->children, node) {
|
list_for_each_entry(cdev, &hpsb_host_class.children, node) {
|
||||||
host = container_of(cdev, struct hpsb_host, class_dev);
|
host = container_of(cdev, struct hpsb_host, class_dev);
|
||||||
|
|
||||||
if ((error = cb(host, __data)))
|
if ((error = cb(host, __data)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
up_read(&class->subsys.rwsem);
|
up(&hpsb_host_class.sem);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -1789,20 +1885,19 @@ static struct hpsb_highlevel nodemgr_highlevel = {
|
||||||
|
|
||||||
int init_ieee1394_nodemgr(void)
|
int init_ieee1394_nodemgr(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int error;
|
||||||
|
|
||||||
ret = class_register(&nodemgr_ne_class);
|
error = class_register(&nodemgr_ne_class);
|
||||||
if (ret < 0)
|
if (error)
|
||||||
return ret;
|
return error;
|
||||||
|
|
||||||
ret = class_register(&nodemgr_ud_class);
|
error = class_register(&nodemgr_ud_class);
|
||||||
if (ret < 0) {
|
if (error) {
|
||||||
class_unregister(&nodemgr_ne_class);
|
class_unregister(&nodemgr_ne_class);
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
error = driver_register(&nodemgr_mid_layer_driver);
|
||||||
hpsb_register_highlevel(&nodemgr_highlevel);
|
hpsb_register_highlevel(&nodemgr_highlevel);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,12 @@ struct hpsb_protocol_driver {
|
||||||
struct device_driver driver;
|
struct device_driver driver;
|
||||||
};
|
};
|
||||||
|
|
||||||
int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
|
int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *);
|
||||||
|
static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
|
||||||
|
{
|
||||||
|
return __hpsb_register_protocol(driver, THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
|
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
|
||||||
|
|
||||||
static inline int hpsb_node_entry_valid(struct node_entry *ne)
|
static inline int hpsb_node_entry_valid(struct node_entry *ne)
|
||||||
|
|
|
@ -468,7 +468,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
|
||||||
/* Global initialization */
|
/* Global initialization */
|
||||||
static void ohci_initialize(struct ti_ohci *ohci)
|
static void ohci_initialize(struct ti_ohci *ohci)
|
||||||
{
|
{
|
||||||
char irq_buf[16];
|
|
||||||
quadlet_t buf;
|
quadlet_t buf;
|
||||||
int num_ports, i;
|
int num_ports, i;
|
||||||
|
|
||||||
|
@ -586,11 +585,10 @@ static void ohci_initialize(struct ti_ohci *ohci)
|
||||||
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
|
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
|
||||||
|
|
||||||
buf = reg_read(ohci, OHCI1394_Version);
|
buf = reg_read(ohci, OHCI1394_Version);
|
||||||
sprintf (irq_buf, "%d", ohci->dev->irq);
|
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] "
|
||||||
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
|
|
||||||
"MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
|
"MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
|
||||||
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
|
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
|
||||||
((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
|
((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
|
||||||
(unsigned long long)pci_resource_start(ohci->dev, 0),
|
(unsigned long long)pci_resource_start(ohci->dev, 0),
|
||||||
(unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
|
(unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
|
||||||
ohci->max_packet_size,
|
ohci->max_packet_size,
|
||||||
|
@ -3217,6 +3215,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
|
||||||
struct ti_ohci *ohci; /* shortcut to currently handled device */
|
struct ti_ohci *ohci; /* shortcut to currently handled device */
|
||||||
resource_size_t ohci_base;
|
resource_size_t ohci_base;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC_PMAC
|
||||||
|
/* Necessary on some machines if ohci1394 was loaded/ unloaded before */
|
||||||
|
if (machine_is(powermac)) {
|
||||||
|
struct device_node *ofn = pci_device_to_OF_node(dev);
|
||||||
|
|
||||||
|
if (ofn) {
|
||||||
|
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
|
||||||
|
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
|
||||||
if (pci_enable_device(dev))
|
if (pci_enable_device(dev))
|
||||||
FAIL(-ENXIO, "Failed to enable OHCI hardware");
|
FAIL(-ENXIO, "Failed to enable OHCI hardware");
|
||||||
pci_set_master(dev);
|
pci_set_master(dev);
|
||||||
|
@ -3505,17 +3515,14 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
/* On UniNorth, power down the cable and turn off the chip
|
/* On UniNorth, power down the cable and turn off the chip clock
|
||||||
* clock when the module is removed to save power on
|
* to save power on laptops */
|
||||||
* laptops. Turning it back ON is done by the arch code when
|
if (machine_is(powermac)) {
|
||||||
* pci_enable_device() is called */
|
struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
|
||||||
{
|
|
||||||
struct device_node* of_node;
|
|
||||||
|
|
||||||
of_node = pci_device_to_OF_node(ohci->dev);
|
if (ofn) {
|
||||||
if (of_node) {
|
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
|
||||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
|
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
|
||||||
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_PMAC */
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
@ -3529,56 +3536,99 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int ohci1394_pci_resume (struct pci_dev *pdev)
|
static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
struct ti_ohci *ohci = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
|
printk(KERN_INFO "%s does not fully support suspend and resume yet\n",
|
||||||
|
OHCI1394_DRIVER_NAME);
|
||||||
|
|
||||||
|
if (!ohci) {
|
||||||
|
printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
|
||||||
|
OHCI1394_DRIVER_NAME);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
DBGMSG("suspend called");
|
||||||
|
|
||||||
|
/* Clear the async DMA contexts and stop using the controller */
|
||||||
|
hpsb_bus_reset(ohci->host);
|
||||||
|
|
||||||
|
/* See ohci1394_pci_remove() for comments on this sequence */
|
||||||
|
reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
|
||||||
|
reg_write(ohci, OHCI1394_BusOptions,
|
||||||
|
(reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
|
||||||
|
0x00ff0000);
|
||||||
|
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
|
||||||
|
set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
|
||||||
|
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
|
||||||
|
ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
|
||||||
|
ohci_soft_reset(ohci);
|
||||||
|
|
||||||
|
err = pci_save_state(pdev);
|
||||||
|
if (err) {
|
||||||
|
PRINT(KERN_ERR, "pci_save_state failed with %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||||
|
if (err)
|
||||||
|
DBGMSG("pci_set_power_state failed with %d", err);
|
||||||
|
|
||||||
|
/* PowerMac suspend code comes last */
|
||||||
|
#ifdef CONFIG_PPC_PMAC
|
||||||
|
if (machine_is(powermac)) {
|
||||||
|
struct device_node *ofn = pci_device_to_OF_node(pdev);
|
||||||
|
|
||||||
|
if (ofn)
|
||||||
|
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ohci1394_pci_resume(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct ti_ohci *ohci = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (!ohci) {
|
||||||
|
printk(KERN_ERR "%s: tried to resume nonexisting host\n",
|
||||||
|
OHCI1394_DRIVER_NAME);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
DBGMSG("resume called");
|
||||||
|
|
||||||
/* PowerMac resume code comes first */
|
/* PowerMac resume code comes first */
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
if (machine_is(powermac)) {
|
if (machine_is(powermac)) {
|
||||||
struct device_node *of_node;
|
struct device_node *ofn = pci_device_to_OF_node(pdev);
|
||||||
|
|
||||||
/* Re-enable 1394 */
|
if (ofn)
|
||||||
of_node = pci_device_to_OF_node (pdev);
|
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
|
||||||
if (of_node)
|
|
||||||
pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_PMAC */
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
|
||||||
pci_set_power_state(pdev, PCI_D0);
|
pci_set_power_state(pdev, PCI_D0);
|
||||||
pci_restore_state(pdev);
|
pci_restore_state(pdev);
|
||||||
return pci_enable_device(pdev);
|
err = pci_enable_device(pdev);
|
||||||
}
|
|
||||||
|
|
||||||
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
printk(KERN_INFO "%s does not fully support suspend and resume yet\n",
|
|
||||||
OHCI1394_DRIVER_NAME);
|
|
||||||
|
|
||||||
err = pci_save_state(pdev);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "%s: pci_save_state failed with %d\n",
|
PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
|
||||||
OHCI1394_DRIVER_NAME, err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
|
||||||
#ifdef OHCI1394_DEBUG
|
|
||||||
if (err)
|
|
||||||
printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n",
|
|
||||||
OHCI1394_DRIVER_NAME, err);
|
|
||||||
#endif /* OHCI1394_DEBUG */
|
|
||||||
|
|
||||||
/* PowerMac suspend code comes last */
|
/* See ohci1394_pci_probe() for comments on this sequence */
|
||||||
#ifdef CONFIG_PPC_PMAC
|
ohci_soft_reset(ohci);
|
||||||
if (machine_is(powermac)) {
|
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
|
||||||
struct device_node *of_node;
|
reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
|
||||||
|
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
|
||||||
/* Disable 1394 */
|
mdelay(50);
|
||||||
of_node = pci_device_to_OF_node (pdev);
|
ohci_initialize(ohci);
|
||||||
if (of_node)
|
|
||||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_PPC_PMAC */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1428,10 +1428,9 @@ static int __devinit add_card(struct pci_dev *dev,
|
||||||
struct i2c_algo_bit_data i2c_adapter_data;
|
struct i2c_algo_bit_data i2c_adapter_data;
|
||||||
|
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
i2c_ad = kmalloc(sizeof(*i2c_ad), GFP_KERNEL);
|
i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL);
|
||||||
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
|
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
|
||||||
|
|
||||||
memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
|
|
||||||
i2c_adapter_data = bit_data;
|
i2c_adapter_data = bit_data;
|
||||||
i2c_ad->algo_data = &i2c_adapter_data;
|
i2c_ad->algo_data = &i2c_adapter_data;
|
||||||
i2c_adapter_data.data = lynx;
|
i2c_adapter_data.data = lynx;
|
||||||
|
|
|
@ -27,12 +27,12 @@ struct file_info {
|
||||||
|
|
||||||
struct hpsb_host *host;
|
struct hpsb_host *host;
|
||||||
|
|
||||||
struct list_head req_pending;
|
struct list_head req_pending; /* protected by reqlists_lock */
|
||||||
struct list_head req_complete;
|
struct list_head req_complete; /* protected by reqlists_lock */
|
||||||
spinlock_t reqlists_lock;
|
spinlock_t reqlists_lock;
|
||||||
wait_queue_head_t wait_complete;
|
wait_queue_head_t wait_complete;
|
||||||
|
|
||||||
struct list_head addr_list;
|
struct list_head addr_list; /* protected by host_info_lock */
|
||||||
|
|
||||||
u8 __user *fcp_buffer;
|
u8 __user *fcp_buffer;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ struct arm_addr {
|
||||||
u8 client_transactions;
|
u8 client_transactions;
|
||||||
u64 recvb;
|
u64 recvb;
|
||||||
u16 rec_length;
|
u16 rec_length;
|
||||||
u8 *addr_space_buffer; /* accessed by read/write/lock */
|
u8 *addr_space_buffer; /* accessed by read/write/lock requests */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pending_request {
|
struct pending_request {
|
||||||
|
@ -79,7 +79,7 @@ struct pending_request {
|
||||||
struct host_info {
|
struct host_info {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct hpsb_host *host;
|
struct hpsb_host *host;
|
||||||
struct list_head file_info_list;
|
struct list_head file_info_list; /* protected by host_info_lock */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* IEEE1394_RAW1394_PRIVATE_H */
|
#endif /* IEEE1394_RAW1394_PRIVATE_H */
|
||||||
|
|
|
@ -99,6 +99,21 @@ static struct hpsb_address_ops arm_ops = {
|
||||||
|
|
||||||
static void queue_complete_cb(struct pending_request *req);
|
static void queue_complete_cb(struct pending_request *req);
|
||||||
|
|
||||||
|
#include <asm/current.h>
|
||||||
|
static void print_old_iso_deprecation(void)
|
||||||
|
{
|
||||||
|
static pid_t p;
|
||||||
|
|
||||||
|
if (p == current->pid)
|
||||||
|
return;
|
||||||
|
p = current->pid;
|
||||||
|
printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
|
||||||
|
" isochronous request types which will be removed in a next"
|
||||||
|
" kernel release\n", current->comm);
|
||||||
|
printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
|
||||||
|
" newer interface\n");
|
||||||
|
}
|
||||||
|
|
||||||
static struct pending_request *__alloc_pending_request(gfp_t flags)
|
static struct pending_request *__alloc_pending_request(gfp_t flags)
|
||||||
{
|
{
|
||||||
struct pending_request *req;
|
struct pending_request *req;
|
||||||
|
@ -2292,6 +2307,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
|
||||||
return sizeof(struct raw1394_request);
|
return sizeof(struct raw1394_request);
|
||||||
|
|
||||||
case RAW1394_REQ_ISO_SEND:
|
case RAW1394_REQ_ISO_SEND:
|
||||||
|
print_old_iso_deprecation();
|
||||||
return handle_iso_send(fi, req, node);
|
return handle_iso_send(fi, req, node);
|
||||||
|
|
||||||
case RAW1394_REQ_ARM_REGISTER:
|
case RAW1394_REQ_ARM_REGISTER:
|
||||||
|
@ -2310,6 +2326,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
|
||||||
return reset_notification(fi, req);
|
return reset_notification(fi, req);
|
||||||
|
|
||||||
case RAW1394_REQ_ISO_LISTEN:
|
case RAW1394_REQ_ISO_LISTEN:
|
||||||
|
print_old_iso_deprecation();
|
||||||
handle_iso_listen(fi, req);
|
handle_iso_listen(fi, req);
|
||||||
return sizeof(struct raw1394_request);
|
return sizeof(struct raw1394_request);
|
||||||
|
|
||||||
|
@ -2970,12 +2987,8 @@ static struct ieee1394_device_id raw1394_id_table[] = {
|
||||||
MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
|
MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
|
||||||
|
|
||||||
static struct hpsb_protocol_driver raw1394_driver = {
|
static struct hpsb_protocol_driver raw1394_driver = {
|
||||||
.name = "raw1394 Driver",
|
|
||||||
.id_table = raw1394_id_table,
|
|
||||||
.driver = {
|
|
||||||
.name = "raw1394",
|
.name = "raw1394",
|
||||||
.bus = &ieee1394_bus_type,
|
.id_table = raw1394_id_table,
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,25 +25,25 @@
|
||||||
#define SBP2_DEVICE_NAME "sbp2"
|
#define SBP2_DEVICE_NAME "sbp2"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SBP2 specific structures and defines
|
* SBP-2 specific definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0
|
#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0
|
||||||
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
|
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
|
||||||
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
|
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
|
||||||
|
|
||||||
#define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31)
|
#define ORB_SET_NULL_PTR(v) (((v) & 0x1) << 31)
|
||||||
#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31)
|
#define ORB_SET_NOTIFY(v) (((v) & 0x1) << 31)
|
||||||
#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */
|
#define ORB_SET_RQ_FMT(v) (((v) & 0x3) << 29)
|
||||||
#define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16)
|
#define ORB_SET_NODE_ID(v) (((v) & 0xffff) << 16)
|
||||||
#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id))
|
#define ORB_SET_STATUS_FIFO_HI(v, id) ((v) >> 32 | ORB_SET_NODE_ID(id))
|
||||||
#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff)
|
#define ORB_SET_STATUS_FIFO_LO(v) ((v) & 0xffffffff)
|
||||||
#define ORB_SET_DATA_SIZE(value) (value & 0xffff)
|
#define ORB_SET_DATA_SIZE(v) ((v) & 0xffff)
|
||||||
#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16)
|
#define ORB_SET_PAGE_SIZE(v) (((v) & 0x7) << 16)
|
||||||
#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19)
|
#define ORB_SET_PAGE_TABLE_PRESENT(v) (((v) & 0x1) << 19)
|
||||||
#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20)
|
#define ORB_SET_MAX_PAYLOAD(v) (((v) & 0xf) << 20)
|
||||||
#define ORB_SET_SPEED(value) ((value & 0x7) << 24)
|
#define ORB_SET_SPEED(v) (((v) & 0x7) << 24)
|
||||||
#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27)
|
#define ORB_SET_DIRECTION(v) (((v) & 0x1) << 27)
|
||||||
|
|
||||||
struct sbp2_command_orb {
|
struct sbp2_command_orb {
|
||||||
u32 next_ORB_hi;
|
u32 next_ORB_hi;
|
||||||
|
@ -64,12 +64,12 @@ struct sbp2_command_orb {
|
||||||
#define SBP2_LOGICAL_UNIT_RESET 0xe
|
#define SBP2_LOGICAL_UNIT_RESET 0xe
|
||||||
#define SBP2_TARGET_RESET_REQUEST 0xf
|
#define SBP2_TARGET_RESET_REQUEST 0xf
|
||||||
|
|
||||||
#define ORB_SET_LUN(value) (value & 0xffff)
|
#define ORB_SET_LUN(v) ((v) & 0xffff)
|
||||||
#define ORB_SET_FUNCTION(value) ((value & 0xf) << 16)
|
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
|
||||||
#define ORB_SET_RECONNECT(value) ((value & 0xf) << 20)
|
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
|
||||||
#define ORB_SET_EXCLUSIVE(value) ((value & 0x1) << 28)
|
#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28)
|
||||||
#define ORB_SET_LOGIN_RESP_LENGTH(value) (value & 0xffff)
|
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
|
||||||
#define ORB_SET_PASSWD_LENGTH(value) ((value & 0xffff) << 16)
|
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
|
||||||
|
|
||||||
struct sbp2_login_orb {
|
struct sbp2_login_orb {
|
||||||
u32 password_hi;
|
u32 password_hi;
|
||||||
|
@ -82,9 +82,9 @@ struct sbp2_login_orb {
|
||||||
u32 status_fifo_lo;
|
u32 status_fifo_lo;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff)
|
#define RESPONSE_GET_LOGIN_ID(v) ((v) & 0xffff)
|
||||||
#define RESPONSE_GET_LENGTH(value) ((value >> 16) & 0xffff)
|
#define RESPONSE_GET_LENGTH(v) (((v) >> 16) & 0xffff)
|
||||||
#define RESPONSE_GET_RECONNECT_HOLD(value) (value & 0xffff)
|
#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff)
|
||||||
|
|
||||||
struct sbp2_login_response {
|
struct sbp2_login_response {
|
||||||
u32 length_login_ID;
|
u32 length_login_ID;
|
||||||
|
@ -93,9 +93,8 @@ struct sbp2_login_response {
|
||||||
u32 reconnect_hold;
|
u32 reconnect_hold;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define ORB_SET_LOGIN_ID(value) (value & 0xffff)
|
#define ORB_SET_LOGIN_ID(v) ((v) & 0xffff)
|
||||||
|
#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff)
|
||||||
#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff)
|
|
||||||
|
|
||||||
struct sbp2_query_logins_orb {
|
struct sbp2_query_logins_orb {
|
||||||
u32 reserved1;
|
u32 reserved1;
|
||||||
|
@ -108,8 +107,8 @@ struct sbp2_query_logins_orb {
|
||||||
u32 status_fifo_lo;
|
u32 status_fifo_lo;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff)
|
#define RESPONSE_GET_MAX_LOGINS(v) ((v) & 0xffff)
|
||||||
#define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12)
|
#define RESPONSE_GET_ACTIVE_LOGINS(v) ((RESPONSE_GET_LENGTH((v)) - 4) / 12)
|
||||||
|
|
||||||
struct sbp2_query_logins_response {
|
struct sbp2_query_logins_response {
|
||||||
u32 length_max_logins;
|
u32 length_max_logins;
|
||||||
|
@ -140,8 +139,8 @@ struct sbp2_logout_orb {
|
||||||
u32 status_fifo_lo;
|
u32 status_fifo_lo;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff)
|
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff)
|
||||||
#define PAGE_TABLE_SET_SEGMENT_LENGTH(value) ((value & 0xffff) << 16)
|
#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16)
|
||||||
|
|
||||||
struct sbp2_unrestricted_page_table {
|
struct sbp2_unrestricted_page_table {
|
||||||
u32 length_segment_base_hi;
|
u32 length_segment_base_hi;
|
||||||
|
@ -171,23 +170,14 @@ struct sbp2_unrestricted_page_table {
|
||||||
#define SFMT_DEFERRED_ERROR 0x1
|
#define SFMT_DEFERRED_ERROR 0x1
|
||||||
#define SFMT_VENDOR_DEPENDENT_STATUS 0x3
|
#define SFMT_VENDOR_DEPENDENT_STATUS 0x3
|
||||||
|
|
||||||
#define SBP2_SCSI_STATUS_GOOD 0x0
|
#define STATUS_GET_SRC(v) (((v) >> 30) & 0x3)
|
||||||
#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2
|
#define STATUS_GET_RESP(v) (((v) >> 28) & 0x3)
|
||||||
#define SBP2_SCSI_STATUS_CONDITION_MET 0x4
|
#define STATUS_GET_LEN(v) (((v) >> 24) & 0x7)
|
||||||
#define SBP2_SCSI_STATUS_BUSY 0x8
|
#define STATUS_GET_SBP_STATUS(v) (((v) >> 16) & 0xff)
|
||||||
#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18
|
#define STATUS_GET_ORB_OFFSET_HI(v) ((v) & 0x0000ffff)
|
||||||
#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22
|
#define STATUS_TEST_DEAD(v) ((v) & 0x08000000)
|
||||||
|
|
||||||
#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff
|
|
||||||
|
|
||||||
#define STATUS_GET_SRC(value) (((value) >> 30) & 0x3)
|
|
||||||
#define STATUS_GET_RESP(value) (((value) >> 28) & 0x3)
|
|
||||||
#define STATUS_GET_LEN(value) (((value) >> 24) & 0x7)
|
|
||||||
#define STATUS_GET_SBP_STATUS(value) (((value) >> 16) & 0xff)
|
|
||||||
#define STATUS_GET_ORB_OFFSET_HI(value) ((value) & 0x0000ffff)
|
|
||||||
#define STATUS_TEST_DEAD(value) ((value) & 0x08000000)
|
|
||||||
/* test 'resp' | 'dead' | 'sbp2_status' */
|
/* test 'resp' | 'dead' | 'sbp2_status' */
|
||||||
#define STATUS_TEST_RDS(value) ((value) & 0x38ff0000)
|
#define STATUS_TEST_RDS(v) ((v) & 0x38ff0000)
|
||||||
|
|
||||||
struct sbp2_status_block {
|
struct sbp2_status_block {
|
||||||
u32 ORB_offset_hi_misc;
|
u32 ORB_offset_hi_misc;
|
||||||
|
@ -195,8 +185,9 @@ struct sbp2_status_block {
|
||||||
u8 command_set_dependent[24];
|
u8 command_set_dependent[24];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Miscellaneous SBP2 related config rom defines
|
* SBP2 related configuration ROM definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1
|
#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1
|
||||||
|
@ -217,44 +208,47 @@ struct sbp2_status_block {
|
||||||
#define SBP2_UNSOLICITED_STATUS_VALUE 0xf
|
#define SBP2_UNSOLICITED_STATUS_VALUE 0xf
|
||||||
|
|
||||||
#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL
|
#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL
|
||||||
|
/* biggest possible value for Single Phase Retry count is 0xf */
|
||||||
#define SBP2_BUSY_TIMEOUT_VALUE 0xf
|
#define SBP2_BUSY_TIMEOUT_VALUE 0xf
|
||||||
|
|
||||||
#define SBP2_AGENT_RESET_DATA 0xf
|
#define SBP2_AGENT_RESET_DATA 0xf
|
||||||
|
|
||||||
/*
|
|
||||||
* Unit spec id and sw version entry for SBP-2 devices
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
|
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
|
||||||
#define SBP2_SW_VERSION_ENTRY 0x00010483
|
#define SBP2_SW_VERSION_ENTRY 0x00010483
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SCSI specific stuff
|
* SCSI specific definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
|
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
|
||||||
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
|
#define SBP2_MAX_SECTORS 255
|
||||||
#define SBP2_MAX_CMDS 8 /* This should be safe */
|
/* There is no real limitation of the queue depth (i.e. length of the linked
|
||||||
|
* list of command ORBs) at the target. The chosen depth is merely an
|
||||||
|
* implementation detail of the sbp2 driver. */
|
||||||
|
#define SBP2_MAX_CMDS 8
|
||||||
|
|
||||||
/* Flags for detected oddities and brokeness */
|
#define SBP2_SCSI_STATUS_GOOD 0x0
|
||||||
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
|
#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2
|
||||||
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
#define SBP2_SCSI_STATUS_CONDITION_MET 0x4
|
||||||
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
#define SBP2_SCSI_STATUS_BUSY 0x8
|
||||||
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18
|
||||||
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22
|
||||||
|
#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff
|
||||||
|
|
||||||
/* This is the two dma types we use for cmd_dma below */
|
|
||||||
enum cmd_dma_types {
|
/*
|
||||||
|
* Representations of commands and devices
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum sbp2_dma_types {
|
||||||
CMD_DMA_NONE,
|
CMD_DMA_NONE,
|
||||||
CMD_DMA_PAGE,
|
CMD_DMA_PAGE,
|
||||||
CMD_DMA_SINGLE
|
CMD_DMA_SINGLE
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/* Per SCSI command */
|
||||||
* Encapsulates all the info necessary for an outstanding command.
|
|
||||||
*/
|
|
||||||
struct sbp2_command_info {
|
struct sbp2_command_info {
|
||||||
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct sbp2_command_orb command_orb ____cacheline_aligned;
|
struct sbp2_command_orb command_orb ____cacheline_aligned;
|
||||||
dma_addr_t command_orb_dma ____cacheline_aligned;
|
dma_addr_t command_orb_dma ____cacheline_aligned;
|
||||||
|
@ -262,25 +256,25 @@ struct sbp2_command_info {
|
||||||
void (*Current_done)(struct scsi_cmnd *);
|
void (*Current_done)(struct scsi_cmnd *);
|
||||||
|
|
||||||
/* Also need s/g structure for each sbp2 command */
|
/* Also need s/g structure for each sbp2 command */
|
||||||
struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned;
|
struct sbp2_unrestricted_page_table
|
||||||
|
scatter_gather_element[SG_ALL] ____cacheline_aligned;
|
||||||
dma_addr_t sge_dma ____cacheline_aligned;
|
dma_addr_t sge_dma ____cacheline_aligned;
|
||||||
void *sge_buffer;
|
void *sge_buffer;
|
||||||
dma_addr_t cmd_dma;
|
dma_addr_t cmd_dma;
|
||||||
enum cmd_dma_types dma_type;
|
enum sbp2_dma_types dma_type;
|
||||||
unsigned long dma_size;
|
unsigned long dma_size;
|
||||||
int dma_dir;
|
enum dma_data_direction dma_dir;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sbp2scsi_host_info;
|
/* Per FireWire host */
|
||||||
|
struct sbp2_fwhost_info {
|
||||||
|
struct hpsb_host *host;
|
||||||
|
struct list_head logical_units;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/* Per logical unit */
|
||||||
* Information needed on a per scsi id basis (one for each sbp2 device)
|
struct sbp2_lu {
|
||||||
*/
|
/* Operation request blocks */
|
||||||
struct scsi_id_instance_data {
|
|
||||||
/*
|
|
||||||
* Various sbp2 specific structures
|
|
||||||
*/
|
|
||||||
struct sbp2_command_orb *last_orb;
|
struct sbp2_command_orb *last_orb;
|
||||||
dma_addr_t last_orb_dma;
|
dma_addr_t last_orb_dma;
|
||||||
struct sbp2_login_orb *login_orb;
|
struct sbp2_login_orb *login_orb;
|
||||||
|
@ -297,116 +291,59 @@ struct scsi_id_instance_data {
|
||||||
dma_addr_t logout_orb_dma;
|
dma_addr_t logout_orb_dma;
|
||||||
struct sbp2_status_block status_block;
|
struct sbp2_status_block status_block;
|
||||||
|
|
||||||
/*
|
/* How to talk to the unit */
|
||||||
* Stuff we need to know about the sbp2 device itself
|
u64 management_agent_addr;
|
||||||
*/
|
u64 command_block_agent_addr;
|
||||||
u64 sbp2_management_agent_addr;
|
|
||||||
u64 sbp2_command_block_agent_addr;
|
|
||||||
u32 speed_code;
|
u32 speed_code;
|
||||||
u32 max_payload_size;
|
u32 max_payload_size;
|
||||||
|
u16 lun;
|
||||||
|
|
||||||
/*
|
/* Address for the unit to write status blocks to */
|
||||||
* Values pulled from the device's unit directory
|
|
||||||
*/
|
|
||||||
u32 sbp2_command_set_spec_id;
|
|
||||||
u32 sbp2_command_set;
|
|
||||||
u32 sbp2_unit_characteristics;
|
|
||||||
u32 sbp2_lun;
|
|
||||||
u32 sbp2_firmware_revision;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Address for the device to write status blocks to
|
|
||||||
*/
|
|
||||||
u64 status_fifo_addr;
|
u64 status_fifo_addr;
|
||||||
|
|
||||||
/*
|
/* Waitqueue flag for logins, reconnects, logouts, query logins */
|
||||||
* Waitqueue flag for logins, reconnects, logouts, query logins
|
unsigned int access_complete:1;
|
||||||
*/
|
|
||||||
int access_complete:1;
|
|
||||||
|
|
||||||
/*
|
/* Pool of command ORBs for this logical unit */
|
||||||
* Pool of command orbs, so we can have more than overlapped command per id
|
spinlock_t cmd_orb_lock;
|
||||||
*/
|
struct list_head cmd_orb_inuse;
|
||||||
spinlock_t sbp2_command_orb_lock;
|
struct list_head cmd_orb_completed;
|
||||||
struct list_head sbp2_command_orb_inuse;
|
|
||||||
struct list_head sbp2_command_orb_completed;
|
|
||||||
|
|
||||||
struct list_head scsi_list;
|
/* Backlink to FireWire host; list of units attached to the host */
|
||||||
|
struct sbp2_fwhost_info *hi;
|
||||||
|
struct list_head lu_list;
|
||||||
|
|
||||||
/* Node entry, as retrieved from NodeMgr entries */
|
/* IEEE 1394 core's device representations */
|
||||||
struct node_entry *ne;
|
struct node_entry *ne;
|
||||||
struct unit_directory *ud;
|
struct unit_directory *ud;
|
||||||
|
|
||||||
/* A backlink to our host_info */
|
/* SCSI core's device representations */
|
||||||
struct sbp2scsi_host_info *hi;
|
|
||||||
|
|
||||||
/* SCSI related pointers */
|
|
||||||
struct scsi_device *sdev;
|
struct scsi_device *sdev;
|
||||||
struct Scsi_Host *scsi_host;
|
struct Scsi_Host *shost;
|
||||||
|
|
||||||
/* Device specific workarounds/brokeness */
|
/* Device specific workarounds/brokeness */
|
||||||
unsigned workarounds;
|
unsigned workarounds;
|
||||||
|
|
||||||
|
/* Connection state */
|
||||||
atomic_t state;
|
atomic_t state;
|
||||||
struct delayed_work protocol_work;
|
|
||||||
|
/* For deferred requests to the fetch agent */
|
||||||
|
struct work_struct protocol_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* For use in scsi_id_instance_data.state */
|
/* For use in sbp2_lu.state */
|
||||||
enum sbp2lu_state_types {
|
enum sbp2lu_state_types {
|
||||||
SBP2LU_STATE_RUNNING, /* all normal */
|
SBP2LU_STATE_RUNNING, /* all normal */
|
||||||
SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */
|
SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */
|
||||||
SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */
|
SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Sbp2 host data structure (one per IEEE1394 host) */
|
/* For use in sbp2_lu.workarounds and in the corresponding
|
||||||
struct sbp2scsi_host_info {
|
* module load parameter */
|
||||||
struct hpsb_host *host; /* IEEE1394 host */
|
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
|
||||||
struct list_head scsi_ids; /* List of scsi ids on this host */
|
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
||||||
};
|
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
||||||
|
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
||||||
/*
|
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
||||||
* Function prototypes
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Various utility prototypes
|
|
||||||
*/
|
|
||||||
static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb);
|
|
||||||
static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt);
|
|
||||||
static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
|
|
||||||
struct scsi_cmnd *Current_SCpnt,
|
|
||||||
void (*Current_done)(struct scsi_cmnd *));
|
|
||||||
static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
|
|
||||||
struct sbp2_command_info *command);
|
|
||||||
|
|
||||||
|
|
||||||
static int sbp2_start_device(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id);
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
|
|
||||||
static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
|
|
||||||
u64 addr, size_t length, u16 flags);
|
|
||||||
static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
|
|
||||||
u64 addr, size_t length, u16 flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SBP-2 protocol related prototypes
|
|
||||||
*/
|
|
||||||
static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static int sbp2_login_device(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
|
|
||||||
quadlet_t *data, u64 addr, size_t length, u16 flags);
|
|
||||||
static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
|
|
||||||
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
|
|
||||||
unchar *sense_data);
|
|
||||||
static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
|
|
||||||
struct unit_directory *ud);
|
|
||||||
static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
|
|
||||||
static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
|
|
||||||
|
|
||||||
#endif /* SBP2_H */
|
#endif /* SBP2_H */
|
||||||
|
|
|
@ -714,7 +714,7 @@ static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __video1394_ioctl(struct file *file,
|
static long video1394_ioctl(struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
||||||
|
@ -884,13 +884,14 @@ static int __video1394_ioctl(struct file *file,
|
||||||
struct dma_iso_ctx *d;
|
struct dma_iso_ctx *d;
|
||||||
int next_prg;
|
int next_prg;
|
||||||
|
|
||||||
if (copy_from_user(&v, argp, sizeof(v)))
|
if (unlikely(copy_from_user(&v, argp, sizeof(v))))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
|
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
|
||||||
if (d == NULL) return -EFAULT;
|
if (unlikely(d == NULL))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
|
if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) {
|
||||||
PRINT(KERN_ERR, ohci->host->id,
|
PRINT(KERN_ERR, ohci->host->id,
|
||||||
"Buffer %d out of range",v.buffer);
|
"Buffer %d out of range",v.buffer);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -898,7 +899,7 @@ static int __video1394_ioctl(struct file *file,
|
||||||
|
|
||||||
spin_lock_irqsave(&d->lock,flags);
|
spin_lock_irqsave(&d->lock,flags);
|
||||||
|
|
||||||
if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
|
if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) {
|
||||||
PRINT(KERN_ERR, ohci->host->id,
|
PRINT(KERN_ERR, ohci->host->id,
|
||||||
"Buffer %d is already used",v.buffer);
|
"Buffer %d is already used",v.buffer);
|
||||||
spin_unlock_irqrestore(&d->lock,flags);
|
spin_unlock_irqrestore(&d->lock,flags);
|
||||||
|
@ -949,13 +950,14 @@ static int __video1394_ioctl(struct file *file,
|
||||||
struct dma_iso_ctx *d;
|
struct dma_iso_ctx *d;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (copy_from_user(&v, argp, sizeof(v)))
|
if (unlikely(copy_from_user(&v, argp, sizeof(v))))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
|
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
|
||||||
if (d == NULL) return -EFAULT;
|
if (unlikely(d == NULL))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
|
if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) {
|
||||||
PRINT(KERN_ERR, ohci->host->id,
|
PRINT(KERN_ERR, ohci->host->id,
|
||||||
"Buffer %d out of range",v.buffer);
|
"Buffer %d out of range",v.buffer);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1008,7 +1010,7 @@ static int __video1394_ioctl(struct file *file,
|
||||||
spin_unlock_irqrestore(&d->lock, flags);
|
spin_unlock_irqrestore(&d->lock, flags);
|
||||||
|
|
||||||
v.buffer=i;
|
v.buffer=i;
|
||||||
if (copy_to_user(argp, &v, sizeof(v)))
|
if (unlikely(copy_to_user(argp, &v, sizeof(v))))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1156,15 +1158,6 @@ static int __video1394_ioctl(struct file *file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
lock_kernel();
|
|
||||||
err = __video1394_ioctl(file, cmd, arg);
|
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This maps the vmalloced and reserved buffer to user space.
|
* This maps the vmalloced and reserved buffer to user space.
|
||||||
*
|
*
|
||||||
|
@ -1177,17 +1170,14 @@ static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long a
|
||||||
static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
|
static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
||||||
int res = -EINVAL;
|
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (ctx->current_ctx == NULL) {
|
if (ctx->current_ctx == NULL) {
|
||||||
PRINT(KERN_ERR, ctx->ohci->host->id,
|
PRINT(KERN_ERR, ctx->ohci->host->id,
|
||||||
"Current iso context not set");
|
"Current iso context not set");
|
||||||
} else
|
return -EINVAL;
|
||||||
res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
|
}
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return res;
|
return dma_region_mmap(&ctx->current_ctx->dma, file, vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int video1394_poll(struct file *file, poll_table *pt)
|
static unsigned int video1394_poll(struct file *file, poll_table *pt)
|
||||||
|
@ -1198,14 +1188,12 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt)
|
||||||
struct dma_iso_ctx *d;
|
struct dma_iso_ctx *d;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
ctx = file->private_data;
|
ctx = file->private_data;
|
||||||
d = ctx->current_ctx;
|
d = ctx->current_ctx;
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
PRINT(KERN_ERR, ctx->ohci->host->id,
|
PRINT(KERN_ERR, ctx->ohci->host->id,
|
||||||
"Current iso context not set");
|
"Current iso context not set");
|
||||||
mask = POLLERR;
|
return POLLERR;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
poll_wait(file, &d->waitq, pt);
|
poll_wait(file, &d->waitq, pt);
|
||||||
|
@ -1218,8 +1206,6 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&d->lock, flags);
|
spin_unlock_irqrestore(&d->lock, flags);
|
||||||
done:
|
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
@ -1255,7 +1241,6 @@ static int video1394_release(struct inode *inode, struct file *file)
|
||||||
struct list_head *lh, *next;
|
struct list_head *lh, *next;
|
||||||
u64 mask;
|
u64 mask;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
list_for_each_safe(lh, next, &ctx->context_list) {
|
list_for_each_safe(lh, next, &ctx->context_list) {
|
||||||
struct dma_iso_ctx *d;
|
struct dma_iso_ctx *d;
|
||||||
d = list_entry(lh, struct dma_iso_ctx, link);
|
d = list_entry(lh, struct dma_iso_ctx, link);
|
||||||
|
@ -1276,7 +1261,6 @@ static int video1394_release(struct inode *inode, struct file *file)
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,12 +1308,8 @@ static struct ieee1394_device_id video1394_id_table[] = {
|
||||||
MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
|
MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
|
||||||
|
|
||||||
static struct hpsb_protocol_driver video1394_driver = {
|
static struct hpsb_protocol_driver video1394_driver = {
|
||||||
.name = "1394 Digital Camera Driver",
|
|
||||||
.id_table = video1394_id_table,
|
|
||||||
.driver = {
|
|
||||||
.name = VIDEO1394_DRIVER_NAME,
|
.name = VIDEO1394_DRIVER_NAME,
|
||||||
.bus = &ieee1394_bus_type,
|
.id_table = video1394_id_table,
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue