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:
Коммит
c99767974e
|
@ -30,11 +30,39 @@ Who: Adrian Bunk <bunk@stusta.de>
|
|||
---------------------------
|
||||
|
||||
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
|
||||
When: November 2006
|
||||
Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
|
||||
more efficient. You should really be using libraw1394 for raw1394
|
||||
access anyway.
|
||||
Who: Jody McIntyre <scjody@modernduck.com>
|
||||
When: June 2007
|
||||
Why: Deprecated in favour of the more efficient and robust rawiso interface.
|
||||
Affected are applications which use the deprecated part of libraw1394
|
||||
(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
|
||||
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.
|
||||
|
||||
config IEEE1394_OUI_DB
|
||||
bool "OUI Database built-in"
|
||||
bool "OUI Database built-in (deprecated)"
|
||||
depends on IEEE1394
|
||||
help
|
||||
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.
|
||||
|
||||
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
|
||||
default n
|
||||
help
|
||||
Export all symbols of ieee1394's driver programming interface, even
|
||||
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.
|
||||
This option will be removed soon. Don't worry, say N.
|
||||
|
||||
comment "Device Drivers"
|
||||
depends on IEEE1394
|
||||
|
@ -125,7 +120,7 @@ comment "SBP-2 support (for storage devices) requires SCSI"
|
|||
|
||||
config IEEE1394_SBP2
|
||||
tristate "SBP-2 support (Harddisks etc.)"
|
||||
depends on IEEE1394 && SCSI && (PCI || BROKEN)
|
||||
depends on IEEE1394 && SCSI
|
||||
help
|
||||
This option enables you to use SBP-2 devices connected to an IEEE
|
||||
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.
|
||||
|
||||
config IEEE1394_DV1394
|
||||
tristate "OHCI-DV I/O support"
|
||||
tristate "OHCI-DV I/O support (deprecated)"
|
||||
depends on IEEE1394 && IEEE1394_OHCI1394
|
||||
help
|
||||
This driver allows you to transmit and receive DV (digital video)
|
||||
streams on an OHCI-1394 card using a simple frame-oriented
|
||||
interface.
|
||||
|
||||
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.
|
||||
The dv1394 driver will be removed from Linux in a future release.
|
||||
Its functionality is now provided by raw1394 together with libraries
|
||||
such as libiec61883.
|
||||
|
||||
config IEEE1394_RAWIO
|
||||
tristate "Raw IEEE1394 I/O support"
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
#
|
||||
|
||||
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
|
||||
ifdef CONFIG_IEEE1394_OUI_DB
|
||||
ieee1394-objs += oui.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_IEEE1394) += ieee1394.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)
|
||||
{
|
||||
unsigned long usecs =
|
||||
(csr->split_timeout_hi & 0x07) * USEC_PER_SEC +
|
||||
(csr->split_timeout_lo >> 19) * 125L;
|
||||
|
||||
csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L);
|
||||
unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 +
|
||||
(csr->split_timeout_lo >> 19) * 125;
|
||||
|
||||
csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000);
|
||||
HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
|
||||
}
|
||||
|
||||
|
|
|
@ -1536,27 +1536,20 @@ 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)
|
||||
{
|
||||
struct video_card *video;
|
||||
struct video_card *video = file_to_video_card(file);
|
||||
unsigned long flags;
|
||||
int ret = -EINVAL;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
lock_kernel();
|
||||
video = file_to_video_card(file);
|
||||
|
||||
/* serialize this to prevent multi-threaded mayhem */
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
if (!mutex_trylock(&video->mtx)) {
|
||||
unlock_kernel();
|
||||
if (!mutex_trylock(&video->mtx))
|
||||
return -EAGAIN;
|
||||
}
|
||||
} else {
|
||||
if (mutex_lock_interruptible(&video->mtx)) {
|
||||
unlock_kernel();
|
||||
if (mutex_lock_interruptible(&video->mtx))
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cmd)
|
||||
|
@ -1780,7 +1773,6 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
|
||||
out:
|
||||
mutex_unlock(&video->mtx);
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2188,12 +2180,8 @@ static struct ieee1394_device_id dv1394_id_table[] = {
|
|||
MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
|
||||
|
||||
static struct hpsb_protocol_driver dv1394_driver = {
|
||||
.name = "DV/1394 Driver",
|
||||
.name = "dv1394",
|
||||
.id_table = dv1394_id_table,
|
||||
.driver = {
|
||||
.name = "dv1394",
|
||||
.bus = &ieee1394_bus_type,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -2587,6 +2575,10 @@ static int __init dv1394_init_module(void)
|
|||
{
|
||||
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);
|
||||
dv1394_cdev.owner = THIS_MODULE;
|
||||
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);
|
||||
|
||||
static struct hpsb_protocol_driver eth1394_proto_driver = {
|
||||
.name = "IPv4 over 1394 Driver",
|
||||
.name = ETH1394_DRIVER_NAME,
|
||||
.id_table = eth1394_id_table,
|
||||
.update = eth1394_update,
|
||||
.driver = {
|
||||
.name = ETH1394_DRIVER_NAME,
|
||||
.bus = &ieee1394_bus_type,
|
||||
.probe = eth1394_probe,
|
||||
.remove = eth1394_remove,
|
||||
},
|
||||
|
|
|
@ -24,7 +24,6 @@ struct hpsb_address_serve {
|
|||
/* Only the following structures are of interest to actual highlevel drivers. */
|
||||
|
||||
struct hpsb_highlevel {
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
|
||||
/* 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);
|
||||
if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
|
||||
/* CSR image creation failed, reset generation field and do not
|
||||
* issue a bus reset. */
|
||||
CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation);
|
||||
/* CSR image creation failed.
|
||||
* Reset generation field and do not issue a bus reset. */
|
||||
CSR_SET_BUS_INFO_GENERATION(host->csr.rom,
|
||||
host->csr.generation);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,7 +55,8 @@ static void delayed_reset_bus(struct work_struct *work)
|
|||
|
||||
host->update_config_rom = 0;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -128,10 +131,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
|
|||
return NULL;
|
||||
|
||||
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
|
||||
if (!h->csr.rom) {
|
||||
kfree(h);
|
||||
return NULL;
|
||||
}
|
||||
if (!h->csr.rom)
|
||||
goto fail;
|
||||
|
||||
h->hostdata = h + 1;
|
||||
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);
|
||||
h->timeout.data = (unsigned long) h;
|
||||
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->speed_map = (u8 *)(h->csr.speed_map + 2);
|
||||
|
||||
mutex_lock(&host_num_alloc);
|
||||
|
||||
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
|
||||
hostnum++;
|
||||
|
||||
mutex_unlock(&host_num_alloc);
|
||||
h->id = hostnum;
|
||||
|
||||
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;
|
||||
snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
|
||||
|
||||
device_register(&h->device);
|
||||
class_device_register(&h->class_dev);
|
||||
if (device_register(&h->device))
|
||||
goto fail;
|
||||
if (class_device_register(&h->class_dev)) {
|
||||
device_unregister(&h->device);
|
||||
goto fail;
|
||||
}
|
||||
get_device(&h->device);
|
||||
|
||||
mutex_unlock(&host_num_alloc);
|
||||
|
||||
return h;
|
||||
|
||||
fail:
|
||||
kfree(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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))
|
||||
/* Wait 60 seconds from the last time this generation number was
|
||||
* used. */
|
||||
reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
|
||||
reset_delay =
|
||||
(60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
|
||||
else
|
||||
/* Wait 1 second in case some other code wants to change the
|
||||
* Config ROM in the near future. */
|
||||
|
|
|
@ -1237,10 +1237,10 @@ EXPORT_SYMBOL(highlevel_remove_host);
|
|||
/** nodemgr.c **/
|
||||
EXPORT_SYMBOL(hpsb_node_fill_packet);
|
||||
EXPORT_SYMBOL(hpsb_node_write);
|
||||
EXPORT_SYMBOL(hpsb_register_protocol);
|
||||
EXPORT_SYMBOL(__hpsb_register_protocol);
|
||||
EXPORT_SYMBOL(hpsb_unregister_protocol);
|
||||
EXPORT_SYMBOL(ieee1394_bus_type);
|
||||
#ifdef CONFIG_IEEE1394_EXPORT_FULL_API
|
||||
EXPORT_SYMBOL(ieee1394_bus_type);
|
||||
EXPORT_SYMBOL(nodemgr_for_each_host);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <asm/atomic.h>
|
||||
|
@ -67,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
|||
{
|
||||
quadlet_t q;
|
||||
u8 i, *speed, old_speed, good_speed;
|
||||
int ret;
|
||||
int error;
|
||||
|
||||
speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
|
||||
old_speed = *speed;
|
||||
|
@ -79,9 +80,9 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
|||
* just finished its initialization. */
|
||||
for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
|
||||
*speed = i;
|
||||
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||
&q, sizeof(quadlet_t));
|
||||
if (ret)
|
||||
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||
&q, sizeof(quadlet_t));
|
||||
if (error)
|
||||
break;
|
||||
*buffer = q;
|
||||
good_speed = i;
|
||||
|
@ -95,19 +96,19 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
|
|||
return 0;
|
||||
}
|
||||
*speed = old_speed;
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
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;
|
||||
int i, ret;
|
||||
int i, error;
|
||||
|
||||
for (i = 1; ; i++) {
|
||||
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||
buffer, length);
|
||||
if (!ret) {
|
||||
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
|
||||
buffer, length);
|
||||
if (!error) {
|
||||
ci->speed_unverified = 0;
|
||||
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 self ID. Check whether a lower speed works. */
|
||||
if (ci->speed_unverified && length == sizeof(quadlet_t)) {
|
||||
ret = nodemgr_check_speed(ci, addr, buffer);
|
||||
if (!ret)
|
||||
error = nodemgr_check_speed(ci, addr, buffer);
|
||||
if (!error)
|
||||
break;
|
||||
}
|
||||
if (msleep_interruptible(334))
|
||||
return -EINTR;
|
||||
}
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/* 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 = {
|
||||
.bus = &ieee1394_bus_type,
|
||||
.release = nodemgr_release_host,
|
||||
.driver = &nodemgr_mid_layer_driver,
|
||||
};
|
||||
|
||||
|
||||
|
@ -307,8 +319,8 @@ static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \
|
|||
return sprintf(buf, format_string, (type)driver->field);\
|
||||
} \
|
||||
static struct driver_attribute driver_attr_drv_##field = { \
|
||||
.attr = {.name = __stringify(field), .mode = S_IRUGO }, \
|
||||
.show = fw_drv_show_##field, \
|
||||
.attr = {.name = __stringify(field), .mode = S_IRUGO }, \
|
||||
.show = fw_drv_show_##field, \
|
||||
};
|
||||
|
||||
|
||||
|
@ -362,7 +374,7 @@ static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
|
|||
#endif
|
||||
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);
|
||||
#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);
|
||||
|
||||
if (state == 1) {
|
||||
down_write(&dev->bus->subsys.rwsem);
|
||||
device_release_driver(dev);
|
||||
ud->ignore_driver = 1;
|
||||
up_write(&dev->bus->subsys.rwsem);
|
||||
} else if (!state)
|
||||
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||
device_release_driver(dev);
|
||||
up_write(&ieee1394_bus_type.subsys.rwsem);
|
||||
} else if (state == 0)
|
||||
ud->ignore_driver = 0;
|
||||
|
||||
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 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)
|
||||
bus_rescan_devices(&ieee1394_bus_type);
|
||||
return count;
|
||||
error = bus_rescan_devices(&ieee1394_bus_type);
|
||||
return error ? error : count;
|
||||
}
|
||||
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)
|
||||
ignore_drivers = 1;
|
||||
else if (!state)
|
||||
else if (state == 0)
|
||||
ignore_drivers = 0;
|
||||
|
||||
return count;
|
||||
|
@ -526,7 +541,7 @@ static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf)
|
|||
int length = 0;
|
||||
char *scratch = buf;
|
||||
|
||||
driver = container_of(drv, struct hpsb_protocol_driver, driver);
|
||||
driver = container_of(drv, struct hpsb_protocol_driver, driver);
|
||||
|
||||
for (id = driver->id_table; id->match_flags != 0; id++) {
|
||||
int need_coma = 0;
|
||||
|
@ -583,7 +598,11 @@ static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
|
|||
int 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;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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, "host_id");
|
||||
|
||||
if ((ne = find_entry_by_nodeid(host, host->irm_id)))
|
||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id");
|
||||
if ((ne = find_entry_by_nodeid(host, host->busmgr_id)))
|
||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id");
|
||||
if ((ne = find_entry_by_nodeid(host, host->node_id)))
|
||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id");
|
||||
if ((ne = find_entry_by_nodeid(host, host->irm_id)) &&
|
||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"))
|
||||
goto fail;
|
||||
if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) &&
|
||||
sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_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)
|
||||
|
@ -642,32 +677,39 @@ static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
|
|||
int 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)
|
||||
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)
|
||||
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) {
|
||||
device_create_file(dev, &dev_attr_ud_vendor_id);
|
||||
if (ud->vendor_name_kv)
|
||||
device_create_file(dev, &dev_attr_ud_vendor_name_kv);
|
||||
if (device_create_file(dev, &dev_attr_ud_vendor_id))
|
||||
goto fail;
|
||||
if (ud->vendor_name_kv &&
|
||||
device_create_file(dev, &dev_attr_ud_vendor_name_kv))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
|
||||
device_create_file(dev, &dev_attr_ud_model_id);
|
||||
if (ud->model_name_kv)
|
||||
device_create_file(dev, &dev_attr_ud_model_name_kv);
|
||||
if (device_create_file(dev, &dev_attr_ud_model_id))
|
||||
goto fail;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
|
||||
{
|
||||
struct hpsb_protocol_driver *driver;
|
||||
struct unit_directory *ud;
|
||||
struct hpsb_protocol_driver *driver;
|
||||
struct unit_directory *ud;
|
||||
struct ieee1394_device_id *id;
|
||||
|
||||
/* We only match unit directories */
|
||||
|
@ -675,55 +717,77 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
|
|||
return 0;
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
for (id = driver->id_table; id->match_flags != 0; id++) {
|
||||
if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
|
||||
id->vendor_id != ud->vendor_id)
|
||||
continue;
|
||||
/* We only match drivers of type hpsb_protocol_driver */
|
||||
if (drv == &nodemgr_mid_layer_driver)
|
||||
return 0;
|
||||
|
||||
if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
|
||||
id->model_id != ud->model_id)
|
||||
continue;
|
||||
driver = container_of(drv, struct hpsb_protocol_driver, driver);
|
||||
for (id = driver->id_table; id->match_flags != 0; id++) {
|
||||
if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
|
||||
id->vendor_id != ud->vendor_id)
|
||||
continue;
|
||||
|
||||
if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
|
||||
id->specifier_id != ud->specifier_id)
|
||||
continue;
|
||||
if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
|
||||
id->model_id != ud->model_id)
|
||||
continue;
|
||||
|
||||
if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
|
||||
id->version != ud->version)
|
||||
continue;
|
||||
if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
|
||||
id->specifier_id != ud->specifier_id)
|
||||
continue;
|
||||
|
||||
if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
|
||||
id->version != ud->version)
|
||||
continue;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
|
||||
|
||||
static void nodemgr_remove_uds(struct node_entry *ne)
|
||||
{
|
||||
struct class_device *cdev, *next;
|
||||
struct unit_directory *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;
|
||||
struct class_device *cdev;
|
||||
struct unit_directory *tmp, *ud;
|
||||
|
||||
/* 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);
|
||||
device_unregister(&ud->device);
|
||||
}
|
||||
mutex_unlock(&nodemgr_serialize_remove_uds);
|
||||
}
|
||||
|
||||
|
||||
static void nodemgr_remove_ne(struct node_entry *ne)
|
||||
{
|
||||
struct device *dev = &ne->device;
|
||||
struct device *dev;
|
||||
|
||||
dev = get_device(&ne->device);
|
||||
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)
|
||||
{
|
||||
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, "busmgr_id");
|
||||
sysfs_remove_link(&dev->kobj, "host_id");
|
||||
|
@ -762,16 +826,16 @@ static void nodemgr_update_bus_options(struct node_entry *ne)
|
|||
#endif
|
||||
quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]);
|
||||
|
||||
ne->busopt.irmc = (busoptions >> 31) & 1;
|
||||
ne->busopt.cmc = (busoptions >> 30) & 1;
|
||||
ne->busopt.isc = (busoptions >> 29) & 1;
|
||||
ne->busopt.bmc = (busoptions >> 28) & 1;
|
||||
ne->busopt.pmc = (busoptions >> 27) & 1;
|
||||
ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
|
||||
ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
|
||||
ne->busopt.irmc = (busoptions >> 31) & 1;
|
||||
ne->busopt.cmc = (busoptions >> 30) & 1;
|
||||
ne->busopt.isc = (busoptions >> 29) & 1;
|
||||
ne->busopt.bmc = (busoptions >> 28) & 1;
|
||||
ne->busopt.pmc = (busoptions >> 27) & 1;
|
||||
ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
|
||||
ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
|
||||
ne->busopt.max_rom = (busoptions >> 8) & 0x3;
|
||||
ne->busopt.generation = (busoptions >> 4) & 0xf;
|
||||
ne->busopt.lnkspd = busoptions & 0x7;
|
||||
ne->busopt.generation = (busoptions >> 4) & 0xf;
|
||||
ne->busopt.lnkspd = busoptions & 0x7;
|
||||
|
||||
HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
|
||||
"cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d",
|
||||
|
@ -792,7 +856,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
|
|||
|
||||
ne = kzalloc(sizeof(*ne), GFP_KERNEL);
|
||||
if (!ne)
|
||||
return NULL;
|
||||
goto fail_alloc;
|
||||
|
||||
ne->host = host;
|
||||
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",
|
||||
(unsigned long long)(ne->guid));
|
||||
|
||||
device_register(&ne->device);
|
||||
class_device_register(&ne->class_dev);
|
||||
if (device_register(&ne->device))
|
||||
goto fail_devreg;
|
||||
if (class_device_register(&ne->class_dev))
|
||||
goto fail_classdevreg;
|
||||
get_device(&ne->device);
|
||||
|
||||
if (ne->guid_vendor_oui)
|
||||
device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui);
|
||||
if (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_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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct class *class = &nodemgr_ne_class;
|
||||
struct class_device *cdev;
|
||||
struct node_entry *ne, *ret_ne = NULL;
|
||||
|
||||
down_read(&class->subsys.rwsem);
|
||||
list_for_each_entry(cdev, &class->children, node) {
|
||||
down(&nodemgr_ne_class.sem);
|
||||
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||
ne = container_of(cdev, struct node_entry, class_dev);
|
||||
|
||||
if (ne->guid == guid) {
|
||||
|
@ -848,20 +926,20 @@ static struct node_entry *find_entry_by_guid(u64 guid)
|
|||
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 node_entry *ne, *ret_ne = NULL;
|
||||
|
||||
down_read(&class->subsys.rwsem);
|
||||
list_for_each_entry(cdev, &class->children, node) {
|
||||
down(&nodemgr_ne_class.sem);
|
||||
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||
ne = container_of(cdev, struct node_entry, class_dev);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
up_read(&class->subsys.rwsem);
|
||||
up(&nodemgr_ne_class.sem);
|
||||
|
||||
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",
|
||||
ne->device.bus_id, ud->id);
|
||||
|
||||
device_register(&ud->device);
|
||||
class_device_register(&ud->class_dev);
|
||||
if (device_register(&ud->device))
|
||||
goto fail_devreg;
|
||||
if (class_device_register(&ud->class_dev))
|
||||
goto fail_classdevreg;
|
||||
get_device(&ud->device);
|
||||
|
||||
if (ud->vendor_oui)
|
||||
device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
|
||||
if (ud->vendor_oui &&
|
||||
device_create_file(&ud->device, &dev_attr_ud_vendor_oui))
|
||||
goto fail_addoui;
|
||||
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 */
|
||||
if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
|
||||
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)
|
||||
goto unit_directory_error;
|
||||
memcpy(ud_child, ud, sizeof(*ud_child));
|
||||
nodemgr_register_device(ne, ud_child, &ne->device);
|
||||
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;
|
||||
}
|
||||
|
||||
if (ne->vendor_oui)
|
||||
device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
|
||||
if (ne->vendor_name_kv)
|
||||
device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv);
|
||||
if (ne->vendor_oui &&
|
||||
device_create_file(&ne->device, &dev_attr_ne_vendor_oui))
|
||||
goto fail;
|
||||
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
|
||||
|
@ -1161,16 +1256,20 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
|
|||
#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 */
|
||||
ret = driver_register(&driver->driver);
|
||||
if (!ret)
|
||||
nodemgr_create_drv_files(driver);
|
||||
|
||||
return ret;
|
||||
error = driver_register(&drv->driver);
|
||||
if (!error)
|
||||
nodemgr_create_drv_files(drv);
|
||||
return error;
|
||||
}
|
||||
|
||||
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
|
||||
|
@ -1298,26 +1397,25 @@ static void nodemgr_node_scan_one(struct host_info *hi,
|
|||
|
||||
static void nodemgr_node_scan(struct host_info *hi, int generation)
|
||||
{
|
||||
int count;
|
||||
struct hpsb_host *host = hi->host;
|
||||
struct selfid *sid = (struct selfid *)host->topology_map;
|
||||
nodeid_t nodeid = LOCAL_BUS;
|
||||
int count;
|
||||
struct hpsb_host *host = hi->host;
|
||||
struct selfid *sid = (struct selfid *)host->topology_map;
|
||||
nodeid_t nodeid = LOCAL_BUS;
|
||||
|
||||
/* Scan each node on the bus */
|
||||
for (count = host->selfid_count; count; count--, sid++) {
|
||||
if (sid->extended)
|
||||
continue;
|
||||
/* Scan each node on the bus */
|
||||
for (count = host->selfid_count; count; count--, sid++) {
|
||||
if (sid->extended)
|
||||
continue;
|
||||
|
||||
if (!sid->link_active) {
|
||||
nodeid++;
|
||||
continue;
|
||||
}
|
||||
nodemgr_node_scan_one(hi, nodeid++, generation);
|
||||
}
|
||||
if (!sid->link_active) {
|
||||
nodeid++;
|
||||
continue;
|
||||
}
|
||||
nodemgr_node_scan_one(hi, nodeid++, generation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
|
||||
static void nodemgr_suspend_ne(struct node_entry *ne)
|
||||
{
|
||||
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);
|
||||
|
||||
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) {
|
||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||
|
||||
if (ud->ne != ne)
|
||||
continue;
|
||||
|
||||
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||
if (ud->device.driver &&
|
||||
(!ud->device.driver->suspend ||
|
||||
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
|
||||
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;
|
||||
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
|
||||
|
||||
down_read(&nodemgr_ud_class.subsys.rwsem);
|
||||
down_read(&ne->device.bus->subsys.rwsem);
|
||||
down(&nodemgr_ud_class.sem);
|
||||
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||
|
||||
if (ud->ne != ne)
|
||||
continue;
|
||||
|
||||
down_read(&ieee1394_bus_type.subsys.rwsem);
|
||||
if (ud->device.driver && ud->device.driver->resume)
|
||||
ud->device.driver->resume(&ud->device);
|
||||
up_read(&ieee1394_bus_type.subsys.rwsem);
|
||||
}
|
||||
up_read(&ne->device.bus->subsys.rwsem);
|
||||
up_read(&nodemgr_ud_class.subsys.rwsem);
|
||||
up(&nodemgr_ud_class.sem);
|
||||
|
||||
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
|
||||
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)
|
||||
{
|
||||
struct unit_directory *ud;
|
||||
struct hpsb_protocol_driver *pdrv;
|
||||
struct class_device *cdev;
|
||||
|
||||
down(&nodemgr_ud_class.sem);
|
||||
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
|
||||
ud = container_of(cdev, struct unit_directory, class_dev);
|
||||
if (ud->ne != ne || !ud->device.driver)
|
||||
if (ud->ne != ne)
|
||||
continue;
|
||||
|
||||
pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
|
||||
|
||||
if (pdrv->update && pdrv->update(ud)) {
|
||||
down_write(&ud->device.bus->subsys.rwsem);
|
||||
device_release_driver(&ud->device);
|
||||
up_write(&ud->device.bus->subsys.rwsem);
|
||||
down_write(&ieee1394_bus_type.subsys.rwsem);
|
||||
if (ud->device.driver) {
|
||||
pdrv = container_of(ud->device.driver,
|
||||
struct hpsb_protocol_driver,
|
||||
driver);
|
||||
if (pdrv->update && pdrv->update(ud))
|
||||
device_release_driver(&ud->device);
|
||||
}
|
||||
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);
|
||||
quadlet_t bc_remote, bc_local;
|
||||
int ret;
|
||||
int error;
|
||||
|
||||
if (!ne->host->is_irm || ne->generation != generation ||
|
||||
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);
|
||||
|
||||
/* Check if the register is implemented and 1394a compliant. */
|
||||
ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
|
||||
sizeof(bc_remote));
|
||||
if (!ret && bc_remote & cpu_to_be32(0x80000000) &&
|
||||
error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
|
||||
sizeof(bc_remote));
|
||||
if (!error && bc_remote & cpu_to_be32(0x80000000) &&
|
||||
bc_remote != 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct hpsb_host *host = hi->host;
|
||||
struct class *class = &nodemgr_ne_class;
|
||||
struct class_device *cdev;
|
||||
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
|
||||
* improvement...) */
|
||||
|
||||
down_read(&class->subsys.rwsem);
|
||||
list_for_each_entry(cdev, &class->children, node) {
|
||||
down(&nodemgr_ne_class.sem);
|
||||
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
|
||||
ne = container_of(cdev, struct node_entry, class_dev);
|
||||
if (!ne->needs_probe)
|
||||
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);
|
||||
if (ne->needs_probe)
|
||||
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
|
||||
|
@ -1498,15 +1596,14 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
|
|||
* just removed. */
|
||||
|
||||
if (generation == get_hpsb_generation(host))
|
||||
bus_rescan_devices(&ieee1394_bus_type);
|
||||
|
||||
return;
|
||||
if (bus_rescan_devices(&ieee1394_bus_type))
|
||||
HPSB_DEBUG("bus_rescan_devices had an error");
|
||||
}
|
||||
|
||||
static int nodemgr_send_resume_packet(struct hpsb_host *host)
|
||||
{
|
||||
struct hpsb_packet *packet;
|
||||
int ret = 1;
|
||||
int error = -ENOMEM;
|
||||
|
||||
packet = hpsb_make_phypacket(host,
|
||||
EXTPHYPACKET_TYPE_RESUME |
|
||||
|
@ -1514,12 +1611,12 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
|
|||
if (packet) {
|
||||
packet->no_waiter = 1;
|
||||
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",
|
||||
host->id);
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* 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 *))
|
||||
{
|
||||
struct class *class = &hpsb_host_class;
|
||||
struct class_device *cdev;
|
||||
struct hpsb_host *host;
|
||||
int error = 0;
|
||||
|
||||
down_read(&class->subsys.rwsem);
|
||||
list_for_each_entry(cdev, &class->children, node) {
|
||||
down(&hpsb_host_class.sem);
|
||||
list_for_each_entry(cdev, &hpsb_host_class.children, node) {
|
||||
host = container_of(cdev, struct hpsb_host, class_dev);
|
||||
|
||||
if ((error = cb(host, __data)))
|
||||
break;
|
||||
}
|
||||
up_read(&class->subsys.rwsem);
|
||||
up(&hpsb_host_class.sem);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1726,10 +1822,10 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
|
|||
|
||||
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
|
||||
{
|
||||
pkt->host = ne->host;
|
||||
pkt->generation = ne->generation;
|
||||
pkt->host = ne->host;
|
||||
pkt->generation = ne->generation;
|
||||
barrier();
|
||||
pkt->node_id = ne->nodeid;
|
||||
pkt->node_id = ne->nodeid;
|
||||
}
|
||||
|
||||
int hpsb_node_write(struct node_entry *ne, u64 addr,
|
||||
|
@ -1789,26 +1885,25 @@ static struct hpsb_highlevel nodemgr_highlevel = {
|
|||
|
||||
int init_ieee1394_nodemgr(void)
|
||||
{
|
||||
int ret;
|
||||
int error;
|
||||
|
||||
ret = class_register(&nodemgr_ne_class);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
error = class_register(&nodemgr_ne_class);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ret = class_register(&nodemgr_ud_class);
|
||||
if (ret < 0) {
|
||||
error = class_register(&nodemgr_ud_class);
|
||||
if (error) {
|
||||
class_unregister(&nodemgr_ne_class);
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = driver_register(&nodemgr_mid_layer_driver);
|
||||
hpsb_register_highlevel(&nodemgr_highlevel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_ieee1394_nodemgr(void)
|
||||
{
|
||||
hpsb_unregister_highlevel(&nodemgr_highlevel);
|
||||
hpsb_unregister_highlevel(&nodemgr_highlevel);
|
||||
|
||||
class_unregister(&nodemgr_ud_class);
|
||||
class_unregister(&nodemgr_ne_class);
|
||||
|
|
|
@ -144,7 +144,12 @@ struct hpsb_protocol_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);
|
||||
|
||||
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 */
|
||||
static void ohci_initialize(struct ti_ohci *ohci)
|
||||
{
|
||||
char irq_buf[16];
|
||||
quadlet_t buf;
|
||||
int num_ports, i;
|
||||
|
||||
|
@ -586,11 +585,10 @@ static void ohci_initialize(struct ti_ohci *ohci)
|
|||
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
|
||||
|
||||
buf = reg_read(ohci, OHCI1394_Version);
|
||||
sprintf (irq_buf, "%d", ohci->dev->irq);
|
||||
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
|
||||
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] "
|
||||
"MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
|
||||
((((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) + OHCI1394_REGISTER_SIZE - 1,
|
||||
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 */
|
||||
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))
|
||||
FAIL(-ENXIO, "Failed to enable OHCI hardware");
|
||||
pci_set_master(dev);
|
||||
|
@ -3505,17 +3515,14 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
/* On UniNorth, power down the cable and turn off the chip
|
||||
* clock when the module is removed to save power on
|
||||
* laptops. Turning it back ON is done by the arch code when
|
||||
* pci_enable_device() is called */
|
||||
{
|
||||
struct device_node* of_node;
|
||||
/* On UniNorth, power down the cable and turn off the chip clock
|
||||
* to save power on laptops */
|
||||
if (machine_is(powermac)) {
|
||||
struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
|
||||
|
||||
of_node = pci_device_to_OF_node(ohci->dev);
|
||||
if (of_node) {
|
||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
|
||||
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
|
||||
if (ofn) {
|
||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
|
||||
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
@ -3529,56 +3536,99 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
#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 */
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
if (machine_is(powermac)) {
|
||||
struct device_node *of_node;
|
||||
struct device_node *ofn = pci_device_to_OF_node(pdev);
|
||||
|
||||
/* Re-enable 1394 */
|
||||
of_node = pci_device_to_OF_node (pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
|
||||
if (ofn)
|
||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
|
||||
}
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
return 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);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: pci_save_state failed with %d\n",
|
||||
OHCI1394_DRIVER_NAME, err);
|
||||
PRINT(KERN_ERR, "pci_enable_device failed with %d", 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 */
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
if (machine_is(powermac)) {
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Disable 1394 */
|
||||
of_node = pci_device_to_OF_node (pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
|
||||
}
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
/* See ohci1394_pci_probe() for comments on this sequence */
|
||||
ohci_soft_reset(ohci);
|
||||
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
|
||||
reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
|
||||
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
|
||||
mdelay(50);
|
||||
ohci_initialize(ohci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1428,10 +1428,9 @@ static int __devinit add_card(struct pci_dev *dev,
|
|||
struct i2c_algo_bit_data i2c_adapter_data;
|
||||
|
||||
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");
|
||||
|
||||
memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
|
||||
i2c_adapter_data = bit_data;
|
||||
i2c_ad->algo_data = &i2c_adapter_data;
|
||||
i2c_adapter_data.data = lynx;
|
||||
|
|
|
@ -27,12 +27,12 @@ struct file_info {
|
|||
|
||||
struct hpsb_host *host;
|
||||
|
||||
struct list_head req_pending;
|
||||
struct list_head req_complete;
|
||||
struct list_head req_pending; /* protected by reqlists_lock */
|
||||
struct list_head req_complete; /* protected by reqlists_lock */
|
||||
spinlock_t reqlists_lock;
|
||||
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;
|
||||
|
||||
|
@ -63,7 +63,7 @@ struct arm_addr {
|
|||
u8 client_transactions;
|
||||
u64 recvb;
|
||||
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 {
|
||||
|
@ -79,7 +79,7 @@ struct pending_request {
|
|||
struct host_info {
|
||||
struct list_head list;
|
||||
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 */
|
||||
|
|
|
@ -99,6 +99,21 @@ static struct hpsb_address_ops arm_ops = {
|
|||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
case RAW1394_REQ_ISO_SEND:
|
||||
print_old_iso_deprecation();
|
||||
return handle_iso_send(fi, req, node);
|
||||
|
||||
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);
|
||||
|
||||
case RAW1394_REQ_ISO_LISTEN:
|
||||
print_old_iso_deprecation();
|
||||
handle_iso_listen(fi, req);
|
||||
return sizeof(struct raw1394_request);
|
||||
|
||||
|
@ -2970,12 +2987,8 @@ static struct ieee1394_device_id raw1394_id_table[] = {
|
|||
MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
|
||||
|
||||
static struct hpsb_protocol_driver raw1394_driver = {
|
||||
.name = "raw1394 Driver",
|
||||
.name = "raw1394",
|
||||
.id_table = raw1394_id_table,
|
||||
.driver = {
|
||||
.name = "raw1394",
|
||||
.bus = &ieee1394_bus_type,
|
||||
},
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,25 +25,25 @@
|
|||
#define SBP2_DEVICE_NAME "sbp2"
|
||||
|
||||
/*
|
||||
* SBP2 specific structures and defines
|
||||
* SBP-2 specific definitions
|
||||
*/
|
||||
|
||||
#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0
|
||||
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
|
||||
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
|
||||
#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0
|
||||
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
|
||||
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
|
||||
|
||||
#define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31)
|
||||
#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31)
|
||||
#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */
|
||||
#define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16)
|
||||
#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id))
|
||||
#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff)
|
||||
#define ORB_SET_DATA_SIZE(value) (value & 0xffff)
|
||||
#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16)
|
||||
#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19)
|
||||
#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20)
|
||||
#define ORB_SET_SPEED(value) ((value & 0x7) << 24)
|
||||
#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27)
|
||||
#define ORB_SET_NULL_PTR(v) (((v) & 0x1) << 31)
|
||||
#define ORB_SET_NOTIFY(v) (((v) & 0x1) << 31)
|
||||
#define ORB_SET_RQ_FMT(v) (((v) & 0x3) << 29)
|
||||
#define ORB_SET_NODE_ID(v) (((v) & 0xffff) << 16)
|
||||
#define ORB_SET_STATUS_FIFO_HI(v, id) ((v) >> 32 | ORB_SET_NODE_ID(id))
|
||||
#define ORB_SET_STATUS_FIFO_LO(v) ((v) & 0xffffffff)
|
||||
#define ORB_SET_DATA_SIZE(v) ((v) & 0xffff)
|
||||
#define ORB_SET_PAGE_SIZE(v) (((v) & 0x7) << 16)
|
||||
#define ORB_SET_PAGE_TABLE_PRESENT(v) (((v) & 0x1) << 19)
|
||||
#define ORB_SET_MAX_PAYLOAD(v) (((v) & 0xf) << 20)
|
||||
#define ORB_SET_SPEED(v) (((v) & 0x7) << 24)
|
||||
#define ORB_SET_DIRECTION(v) (((v) & 0x1) << 27)
|
||||
|
||||
struct sbp2_command_orb {
|
||||
u32 next_ORB_hi;
|
||||
|
@ -64,12 +64,12 @@ struct sbp2_command_orb {
|
|||
#define SBP2_LOGICAL_UNIT_RESET 0xe
|
||||
#define SBP2_TARGET_RESET_REQUEST 0xf
|
||||
|
||||
#define ORB_SET_LUN(value) (value & 0xffff)
|
||||
#define ORB_SET_FUNCTION(value) ((value & 0xf) << 16)
|
||||
#define ORB_SET_RECONNECT(value) ((value & 0xf) << 20)
|
||||
#define ORB_SET_EXCLUSIVE(value) ((value & 0x1) << 28)
|
||||
#define ORB_SET_LOGIN_RESP_LENGTH(value) (value & 0xffff)
|
||||
#define ORB_SET_PASSWD_LENGTH(value) ((value & 0xffff) << 16)
|
||||
#define ORB_SET_LUN(v) ((v) & 0xffff)
|
||||
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
|
||||
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
|
||||
#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28)
|
||||
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
|
||||
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
|
||||
|
||||
struct sbp2_login_orb {
|
||||
u32 password_hi;
|
||||
|
@ -82,9 +82,9 @@ struct sbp2_login_orb {
|
|||
u32 status_fifo_lo;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff)
|
||||
#define RESPONSE_GET_LENGTH(value) ((value >> 16) & 0xffff)
|
||||
#define RESPONSE_GET_RECONNECT_HOLD(value) (value & 0xffff)
|
||||
#define RESPONSE_GET_LOGIN_ID(v) ((v) & 0xffff)
|
||||
#define RESPONSE_GET_LENGTH(v) (((v) >> 16) & 0xffff)
|
||||
#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff)
|
||||
|
||||
struct sbp2_login_response {
|
||||
u32 length_login_ID;
|
||||
|
@ -93,9 +93,8 @@ struct sbp2_login_response {
|
|||
u32 reconnect_hold;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ORB_SET_LOGIN_ID(value) (value & 0xffff)
|
||||
|
||||
#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff)
|
||||
#define ORB_SET_LOGIN_ID(v) ((v) & 0xffff)
|
||||
#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff)
|
||||
|
||||
struct sbp2_query_logins_orb {
|
||||
u32 reserved1;
|
||||
|
@ -108,8 +107,8 @@ struct sbp2_query_logins_orb {
|
|||
u32 status_fifo_lo;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff)
|
||||
#define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12)
|
||||
#define RESPONSE_GET_MAX_LOGINS(v) ((v) & 0xffff)
|
||||
#define RESPONSE_GET_ACTIVE_LOGINS(v) ((RESPONSE_GET_LENGTH((v)) - 4) / 12)
|
||||
|
||||
struct sbp2_query_logins_response {
|
||||
u32 length_max_logins;
|
||||
|
@ -140,8 +139,8 @@ struct sbp2_logout_orb {
|
|||
u32 status_fifo_lo;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff)
|
||||
#define PAGE_TABLE_SET_SEGMENT_LENGTH(value) ((value & 0xffff) << 16)
|
||||
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff)
|
||||
#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16)
|
||||
|
||||
struct sbp2_unrestricted_page_table {
|
||||
u32 length_segment_base_hi;
|
||||
|
@ -171,23 +170,14 @@ struct sbp2_unrestricted_page_table {
|
|||
#define SFMT_DEFERRED_ERROR 0x1
|
||||
#define SFMT_VENDOR_DEPENDENT_STATUS 0x3
|
||||
|
||||
#define SBP2_SCSI_STATUS_GOOD 0x0
|
||||
#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2
|
||||
#define SBP2_SCSI_STATUS_CONDITION_MET 0x4
|
||||
#define SBP2_SCSI_STATUS_BUSY 0x8
|
||||
#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18
|
||||
#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22
|
||||
|
||||
#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)
|
||||
#define STATUS_GET_SRC(v) (((v) >> 30) & 0x3)
|
||||
#define STATUS_GET_RESP(v) (((v) >> 28) & 0x3)
|
||||
#define STATUS_GET_LEN(v) (((v) >> 24) & 0x7)
|
||||
#define STATUS_GET_SBP_STATUS(v) (((v) >> 16) & 0xff)
|
||||
#define STATUS_GET_ORB_OFFSET_HI(v) ((v) & 0x0000ffff)
|
||||
#define STATUS_TEST_DEAD(v) ((v) & 0x08000000)
|
||||
/* test 'resp' | 'dead' | 'sbp2_status' */
|
||||
#define STATUS_TEST_RDS(value) ((value) & 0x38ff0000)
|
||||
#define STATUS_TEST_RDS(v) ((v) & 0x38ff0000)
|
||||
|
||||
struct sbp2_status_block {
|
||||
u32 ORB_offset_hi_misc;
|
||||
|
@ -195,66 +185,70 @@ struct sbp2_status_block {
|
|||
u8 command_set_dependent[24];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Miscellaneous SBP2 related config rom defines
|
||||
*/
|
||||
|
||||
#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1
|
||||
#define SBP2_CSR_OFFSET_KEY 0x54
|
||||
#define SBP2_UNIT_SPEC_ID_KEY 0x12
|
||||
#define SBP2_UNIT_SW_VERSION_KEY 0x13
|
||||
#define SBP2_COMMAND_SET_SPEC_ID_KEY 0x38
|
||||
#define SBP2_COMMAND_SET_KEY 0x39
|
||||
#define SBP2_UNIT_CHARACTERISTICS_KEY 0x3a
|
||||
#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14
|
||||
#define SBP2_FIRMWARE_REVISION_KEY 0x3c
|
||||
|
||||
#define SBP2_AGENT_STATE_OFFSET 0x00ULL
|
||||
#define SBP2_AGENT_RESET_OFFSET 0x04ULL
|
||||
#define SBP2_ORB_POINTER_OFFSET 0x08ULL
|
||||
#define SBP2_DOORBELL_OFFSET 0x10ULL
|
||||
#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14ULL
|
||||
#define SBP2_UNSOLICITED_STATUS_VALUE 0xf
|
||||
|
||||
#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL
|
||||
#define SBP2_BUSY_TIMEOUT_VALUE 0xf
|
||||
|
||||
#define SBP2_AGENT_RESET_DATA 0xf
|
||||
|
||||
/*
|
||||
* Unit spec id and sw version entry for SBP-2 devices
|
||||
* SBP2 related configuration ROM definitions
|
||||
*/
|
||||
|
||||
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
|
||||
#define SBP2_SW_VERSION_ENTRY 0x00010483
|
||||
#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1
|
||||
#define SBP2_CSR_OFFSET_KEY 0x54
|
||||
#define SBP2_UNIT_SPEC_ID_KEY 0x12
|
||||
#define SBP2_UNIT_SW_VERSION_KEY 0x13
|
||||
#define SBP2_COMMAND_SET_SPEC_ID_KEY 0x38
|
||||
#define SBP2_COMMAND_SET_KEY 0x39
|
||||
#define SBP2_UNIT_CHARACTERISTICS_KEY 0x3a
|
||||
#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14
|
||||
#define SBP2_FIRMWARE_REVISION_KEY 0x3c
|
||||
|
||||
#define SBP2_AGENT_STATE_OFFSET 0x00ULL
|
||||
#define SBP2_AGENT_RESET_OFFSET 0x04ULL
|
||||
#define SBP2_ORB_POINTER_OFFSET 0x08ULL
|
||||
#define SBP2_DOORBELL_OFFSET 0x10ULL
|
||||
#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14ULL
|
||||
#define SBP2_UNSOLICITED_STATUS_VALUE 0xf
|
||||
|
||||
#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL
|
||||
/* biggest possible value for Single Phase Retry count is 0xf */
|
||||
#define SBP2_BUSY_TIMEOUT_VALUE 0xf
|
||||
|
||||
#define SBP2_AGENT_RESET_DATA 0xf
|
||||
|
||||
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
|
||||
#define SBP2_SW_VERSION_ENTRY 0x00010483
|
||||
|
||||
|
||||
/*
|
||||
* SCSI specific stuff
|
||||
* SCSI specific definitions
|
||||
*/
|
||||
|
||||
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
|
||||
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
|
||||
#define SBP2_MAX_CMDS 8 /* This should be safe */
|
||||
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
|
||||
#define SBP2_MAX_SECTORS 255
|
||||
/* 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_WORKAROUND_128K_MAX_TRANS 0x1
|
||||
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
||||
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
||||
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
||||
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
||||
#define SBP2_SCSI_STATUS_GOOD 0x0
|
||||
#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2
|
||||
#define SBP2_SCSI_STATUS_CONDITION_MET 0x4
|
||||
#define SBP2_SCSI_STATUS_BUSY 0x8
|
||||
#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18
|
||||
#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_PAGE,
|
||||
CMD_DMA_SINGLE
|
||||
};
|
||||
|
||||
/*
|
||||
* Encapsulates all the info necessary for an outstanding command.
|
||||
*/
|
||||
/* Per SCSI command */
|
||||
struct sbp2_command_info {
|
||||
|
||||
struct list_head list;
|
||||
struct sbp2_command_orb command_orb ____cacheline_aligned;
|
||||
dma_addr_t command_orb_dma ____cacheline_aligned;
|
||||
|
@ -262,25 +256,25 @@ struct sbp2_command_info {
|
|||
void (*Current_done)(struct scsi_cmnd *);
|
||||
|
||||
/* 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;
|
||||
void *sge_buffer;
|
||||
dma_addr_t cmd_dma;
|
||||
enum cmd_dma_types dma_type;
|
||||
enum sbp2_dma_types dma_type;
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
* Information needed on a per scsi id basis (one for each sbp2 device)
|
||||
*/
|
||||
struct scsi_id_instance_data {
|
||||
/*
|
||||
* Various sbp2 specific structures
|
||||
*/
|
||||
/* Per logical unit */
|
||||
struct sbp2_lu {
|
||||
/* Operation request blocks */
|
||||
struct sbp2_command_orb *last_orb;
|
||||
dma_addr_t last_orb_dma;
|
||||
struct sbp2_login_orb *login_orb;
|
||||
|
@ -297,116 +291,59 @@ struct scsi_id_instance_data {
|
|||
dma_addr_t logout_orb_dma;
|
||||
struct sbp2_status_block status_block;
|
||||
|
||||
/*
|
||||
* Stuff we need to know about the sbp2 device itself
|
||||
*/
|
||||
u64 sbp2_management_agent_addr;
|
||||
u64 sbp2_command_block_agent_addr;
|
||||
/* How to talk to the unit */
|
||||
u64 management_agent_addr;
|
||||
u64 command_block_agent_addr;
|
||||
u32 speed_code;
|
||||
u32 max_payload_size;
|
||||
u16 lun;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
/* Address for the unit to write status blocks to */
|
||||
u64 status_fifo_addr;
|
||||
|
||||
/*
|
||||
* Waitqueue flag for logins, reconnects, logouts, query logins
|
||||
*/
|
||||
int access_complete:1;
|
||||
/* Waitqueue flag for logins, reconnects, logouts, query logins */
|
||||
unsigned int access_complete:1;
|
||||
|
||||
/*
|
||||
* Pool of command orbs, so we can have more than overlapped command per id
|
||||
*/
|
||||
spinlock_t sbp2_command_orb_lock;
|
||||
struct list_head sbp2_command_orb_inuse;
|
||||
struct list_head sbp2_command_orb_completed;
|
||||
/* Pool of command ORBs for this logical unit */
|
||||
spinlock_t cmd_orb_lock;
|
||||
struct list_head cmd_orb_inuse;
|
||||
struct list_head cmd_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 unit_directory *ud;
|
||||
|
||||
/* A backlink to our host_info */
|
||||
struct sbp2scsi_host_info *hi;
|
||||
|
||||
/* SCSI related pointers */
|
||||
/* SCSI core's device representations */
|
||||
struct scsi_device *sdev;
|
||||
struct Scsi_Host *scsi_host;
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
/* Device specific workarounds/brokeness */
|
||||
unsigned workarounds;
|
||||
|
||||
/* Connection 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 {
|
||||
SBP2LU_STATE_RUNNING, /* all normal */
|
||||
SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */
|
||||
SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */
|
||||
};
|
||||
|
||||
/* Sbp2 host data structure (one per IEEE1394 host) */
|
||||
struct sbp2scsi_host_info {
|
||||
struct hpsb_host *host; /* IEEE1394 host */
|
||||
struct list_head scsi_ids; /* List of scsi ids on this host */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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);
|
||||
/* For use in sbp2_lu.workarounds and in the corresponding
|
||||
* module load parameter */
|
||||
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
|
||||
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
||||
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
||||
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
||||
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
||||
|
||||
#endif /* SBP2_H */
|
||||
|
|
|
@ -714,8 +714,8 @@ static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __video1394_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long video1394_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
||||
struct ti_ohci *ohci = ctx->ohci;
|
||||
|
@ -884,13 +884,14 @@ static int __video1394_ioctl(struct file *file,
|
|||
struct dma_iso_ctx *d;
|
||||
int next_prg;
|
||||
|
||||
if (copy_from_user(&v, argp, sizeof(v)))
|
||||
if (unlikely(copy_from_user(&v, argp, sizeof(v))))
|
||||
return -EFAULT;
|
||||
|
||||
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,
|
||||
"Buffer %d out of range",v.buffer);
|
||||
return -EINVAL;
|
||||
|
@ -898,7 +899,7 @@ static int __video1394_ioctl(struct file *file,
|
|||
|
||||
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,
|
||||
"Buffer %d is already used",v.buffer);
|
||||
spin_unlock_irqrestore(&d->lock,flags);
|
||||
|
@ -949,13 +950,14 @@ static int __video1394_ioctl(struct file *file,
|
|||
struct dma_iso_ctx *d;
|
||||
int i = 0;
|
||||
|
||||
if (copy_from_user(&v, argp, sizeof(v)))
|
||||
if (unlikely(copy_from_user(&v, argp, sizeof(v))))
|
||||
return -EFAULT;
|
||||
|
||||
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,
|
||||
"Buffer %d out of range",v.buffer);
|
||||
return -EINVAL;
|
||||
|
@ -1008,7 +1010,7 @@ static int __video1394_ioctl(struct file *file,
|
|||
spin_unlock_irqrestore(&d->lock, flags);
|
||||
|
||||
v.buffer=i;
|
||||
if (copy_to_user(argp, &v, sizeof(v)))
|
||||
if (unlikely(copy_to_user(argp, &v, sizeof(v))))
|
||||
return -EFAULT;
|
||||
|
||||
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.
|
||||
*
|
||||
|
@ -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)
|
||||
{
|
||||
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
|
||||
int res = -EINVAL;
|
||||
|
||||
lock_kernel();
|
||||
if (ctx->current_ctx == NULL) {
|
||||
PRINT(KERN_ERR, ctx->ohci->host->id,
|
||||
"Current iso context not set");
|
||||
} else
|
||||
res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
|
||||
unlock_kernel();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return res;
|
||||
return dma_region_mmap(&ctx->current_ctx->dma, file, vma);
|
||||
}
|
||||
|
||||
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;
|
||||
int i;
|
||||
|
||||
lock_kernel();
|
||||
ctx = file->private_data;
|
||||
d = ctx->current_ctx;
|
||||
if (d == NULL) {
|
||||
PRINT(KERN_ERR, ctx->ohci->host->id,
|
||||
"Current iso context not set");
|
||||
mask = POLLERR;
|
||||
goto done;
|
||||
return POLLERR;
|
||||
}
|
||||
|
||||
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);
|
||||
done:
|
||||
unlock_kernel();
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
@ -1255,7 +1241,6 @@ static int video1394_release(struct inode *inode, struct file *file)
|
|||
struct list_head *lh, *next;
|
||||
u64 mask;
|
||||
|
||||
lock_kernel();
|
||||
list_for_each_safe(lh, next, &ctx->context_list) {
|
||||
struct dma_iso_ctx *d;
|
||||
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);
|
||||
file->private_data = NULL;
|
||||
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1324,12 +1308,8 @@ static struct ieee1394_device_id video1394_id_table[] = {
|
|||
MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
|
||||
|
||||
static struct hpsb_protocol_driver video1394_driver = {
|
||||
.name = "1394 Digital Camera Driver",
|
||||
.name = VIDEO1394_DRIVER_NAME,
|
||||
.id_table = video1394_id_table,
|
||||
.driver = {
|
||||
.name = VIDEO1394_DRIVER_NAME,
|
||||
.bus = &ieee1394_bus_type,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче