Commit f50d5e03 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.linux1394.org/ieee1394-2.6

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents 6a59dff3 55387c40
......@@ -47,6 +47,23 @@ config IEEE1394_OUI_DB
This option is not needed for userspace programs like gscanbus
to show this information.
config IEEE1394_EXTRA_CONFIG_ROMS
bool "Build in extra config rom entries for certain functionality"
depends on IEEE1394
help
Some IEEE1394 functionality depends on extra config rom entries
being available in the host adapters CSR. These options will
allow you to choose which ones.
config IEEE1394_CONFIG_ROM_IP1394
bool "IP-1394 Entry"
depends on IEEE1394_EXTRA_CONFIG_ROMS && IEEE1394
help
Adds an entry for using IP-over-1394. If you want to use your
IEEE1394 bus as a network for IP systems (including interacting
with MacOSX and WinXP IP-over-1394), enable this option and the
eth1394 option below.
comment "Device Drivers"
depends on IEEE1394
......@@ -108,6 +125,8 @@ config IEEE1394_SBP2_PHYS_DMA
config IEEE1394_ETH1394
tristate "Ethernet over 1394"
depends on IEEE1394 && EXPERIMENTAL
select IEEE1394_CONFIG_ROM_IP1394
select IEEE1394_EXTRA_CONFIG_ROMS
help
This driver implements a functional majority of RFC 2734: IPv4 over
1394. It will provide IP connectivity with implementations of RFC
......
......@@ -4,7 +4,7 @@
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
csr1212.o
csr1212.o config_roms.o
obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
......
......@@ -1227,15 +1227,15 @@ static void amdtp_add_host(struct hpsb_host *host)
ah->host = host;
ah->ohci = host->hostdata;
hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->ohci->id);
hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id);
minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id;
minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id;
INIT_LIST_HEAD(&ah->stream_list);
spin_lock_init(&ah->stream_list_lock);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id);
S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id);
}
static void amdtp_remove_host(struct hpsb_host *host)
......@@ -1243,7 +1243,7 @@ static void amdtp_remove_host(struct hpsb_host *host)
struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host);
if (ah)
devfs_remove("amdtp/%d", ah->ohci->id);
devfs_remove("amdtp/%d", ah->host->id);
return;
}
......
/*
* IEEE 1394 for Linux
*
* ConfigROM entries
*
* Copyright (C) 2004 Ben Collins
*
* This code is licensed under the GPL. See the file COPYING in the root
* directory of the kernel sources for details.
*/
#include <linux/config.h>
#include <linux/types.h>
#include "csr1212.h"
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "csr.h"
#include "config_roms.h"
struct hpsb_config_rom_entry {
const char *name;
/* Base initialization, called at module load */
int (*init)(void);
/* Add entry to specified host */
int (*add)(struct hpsb_host *host);
/* Remove entry from specified host */
void (*remove)(struct hpsb_host *host);
/* Cleanup called at module exit */
void (*cleanup)(void);
/* The flag added to host->config_roms */
unsigned int flag;
};
int hpsb_default_host_entry(struct hpsb_host *host)
{
struct csr1212_keyval *root;
struct csr1212_keyval *vend_id = NULL;
struct csr1212_keyval *text = NULL;
char csr_name[128];
int ret;
sprintf(csr_name, "Linux - %s", host->driver->name);
root = host->csr.rom->root_kv;
vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
text = csr1212_new_string_descriptor_leaf(csr_name);
if (!vend_id || !text) {
if (vend_id)
csr1212_release_keyval(vend_id);
if (text)
csr1212_release_keyval(text);
csr1212_destroy_csr(host->csr.rom);
return -ENOMEM;
}
ret = csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text);
ret |= csr1212_attach_keyval_to_directory(root, vend_id);
if (ret != CSR1212_SUCCESS) {
csr1212_release_keyval(vend_id);
csr1212_destroy_csr(host->csr.rom);
return -ENOMEM;
}
host->update_config_rom = 1;
return 0;
}
#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
#include "eth1394.h"
static struct csr1212_keyval *ip1394_ud;
static int config_rom_ip1394_init(void)
{
struct csr1212_keyval *spec_id = NULL;
struct csr1212_keyval *spec_desc = NULL;
struct csr1212_keyval *ver = NULL;
struct csr1212_keyval *ver_desc = NULL;
int ret = -ENOMEM;
ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
ETHER1394_GASP_SPECIFIER_ID);
spec_desc = csr1212_new_string_descriptor_leaf("IANA");
ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
ETHER1394_GASP_VERSION);
ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
goto ip1394_fail;
if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS &&
csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS)
ret = 0;
ip1394_fail:
if (ret && ip1394_ud) {
csr1212_release_keyval(ip1394_ud);
ip1394_ud = NULL;
}
if (spec_id)
csr1212_release_keyval(spec_id);
if (spec_desc)
csr1212_release_keyval(spec_desc);
if (ver)
csr1212_release_keyval(ver);
if (ver_desc)
csr1212_release_keyval(ver_desc);
return ret;
}
static void config_rom_ip1394_cleanup(void)
{
if (ip1394_ud) {
csr1212_release_keyval(ip1394_ud);
ip1394_ud = NULL;
}
}
static int config_rom_ip1394_add(struct hpsb_host *host)
{
if (!ip1394_ud)
return -ENODEV;
if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
ip1394_ud) != CSR1212_SUCCESS)
return -ENOMEM;
return 0;
}
static void config_rom_ip1394_remove(struct hpsb_host *host)
{
csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
}
static struct hpsb_config_rom_entry ip1394_entry = {
.name = "ip1394",
.init = config_rom_ip1394_init,
.add = config_rom_ip1394_add,
.remove = config_rom_ip1394_remove,
.cleanup = config_rom_ip1394_cleanup,
.flag = HPSB_CONFIG_ROM_ENTRY_IP1394,
};
#endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */
static struct hpsb_config_rom_entry *const config_rom_entries[] = {
#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
&ip1394_entry,
#endif
NULL,
};
int hpsb_init_config_roms(void)
{
int i, error = 0;
for (i = 0; config_rom_entries[i]; i++) {
if (!config_rom_entries[i]->init)
continue;
if (config_rom_entries[i]->init()) {
HPSB_ERR("Failed to initialize config rom entry `%s'",
config_rom_entries[i]->name);
error = -1;
} else
HPSB_DEBUG("Initialized config rom entry `%s'",
config_rom_entries[i]->name);
}
return error;
}
void hpsb_cleanup_config_roms(void)
{
int i;
for (i = 0; config_rom_entries[i]; i++) {
if (config_rom_entries[i]->cleanup)
config_rom_entries[i]->cleanup();
}
}
int hpsb_add_extra_config_roms(struct hpsb_host *host)
{
int i, error = 0;
for (i = 0; config_rom_entries[i]; i++) {
if (config_rom_entries[i]->add(host)) {
HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'",
host->id, config_rom_entries[i]->name);
error = -1;
} else {
host->config_roms |= config_rom_entries[i]->flag;
host->update_config_rom = 1;
}
}
return error;
}
void hpsb_remove_extra_config_roms(struct hpsb_host *host)
{
int i;
for (i = 0; config_rom_entries[i]; i++) {
if (!(host->config_roms & config_rom_entries[i]->flag))
continue;
config_rom_entries[i]->remove(host);
host->config_roms &= ~config_rom_entries[i]->flag;
host->update_config_rom = 1;
}
}
#ifndef _IEEE1394_CONFIG_ROMS_H
#define _IEEE1394_CONFIG_ROMS_H
#include "ieee1394_types.h"
#include "hosts.h"
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host);
/* Initialize all config roms */
int hpsb_init_config_roms(void);
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void);
/* Add extra config roms to specified host */
int hpsb_add_extra_config_roms(struct hpsb_host *host);
/* Remove extra config roms from specified host */
void hpsb_remove_extra_config_roms(struct hpsb_host *host);
/* List of flags to check if a host contains a certain extra config rom
* entry. Available in the host->config_roms member. */
#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001
#endif /* _IEEE1394_CONFIG_ROMS_H */
......@@ -704,11 +704,12 @@ void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
/* If the current entry is a directory, then move all
* the entries to the destruction list. */
if (k->value.directory.dentries_head) {
tail->next = k->value.directory.dentries_head;
if (k->value.directory.dentries_head)
k->value.directory.dentries_head->prev = tail;
tail = k->value.directory.dentries_tail;
}
}
free_keyval(k);
k = a;
}
......@@ -1347,6 +1348,12 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
case CSR1212_KV_TYPE_DIRECTORY:
for (i = 0; i < kvi_len; i++) {
csr1212_quad_t ki = kvi->data[i];
/* Some devices put null entries in their unit
* directories. If we come across such and entry,
* then skip it. */
if (ki == 0x0)
continue;
ret = csr1212_parse_dir_entry(kv, ki,
(kv->offset +
quads_to_bytes(i + 1)),
......
......@@ -2222,7 +2222,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
video->ohci = ohci;
/* lower 2 bits of id indicate which of four "plugs"
per host */
video->id = ohci->id << 2;
video->id = ohci->host->id << 2;
if (format == DV1394_NTSC)
video->id |= mode;
else
......@@ -2302,47 +2302,49 @@ static void dv1394_un_init(struct video_card *video)
);
devfs_remove("ieee1394/%s", buf);
list_del(&video->list);
kfree(video);
}
static void dv1394_remove_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
struct video_card *video = NULL;
struct video_card *video;
unsigned long flags;
struct list_head *lh, *templh;
int n;
int id = host->id;
/* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
return;
ohci = (struct ti_ohci *)host->hostdata;
/* find the corresponding video_cards */
do {
struct video_card *tmp_vid;
video = NULL;
/* find the corresponding video_cards */
spin_lock_irqsave(&dv1394_cards_lock, flags);
if (!list_empty(&dv1394_cards)) {
list_for_each_safe(lh, templh, &dv1394_cards) {
video = list_entry(lh, struct video_card, list);
if ((video->id >> 2) == ohci->id)
dv1394_un_init(video);
list_for_each_entry(tmp_vid, &dv1394_cards, list) {
if ((tmp_vid->id >> 2) == id) {
list_del(&tmp_vid->list);
video = tmp_vid;
break;
}
}
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
n = (video->id >> 2);
if (video)
dv1394_un_init(video);
} while (video != NULL);
devfs_remove("ieee1394/dv/host%d/NTSC", n);
devfs_remove("ieee1394/dv/host%d/PAL", n);
devfs_remove("ieee1394/dv/host%d", n);
devfs_remove("ieee1394/dv/host%d/NTSC", id);
devfs_remove("ieee1394/dv/host%d/PAL", id);
devfs_remove("ieee1394/dv/host%d", id);
}
static void dv1394_add_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
int id = host->id;
/* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
......@@ -2350,9 +2352,9 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d", id);
devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
......@@ -2369,7 +2371,7 @@ static void dv1394_add_host (struct hpsb_host *host)
static void dv1394_host_reset(struct hpsb_host *host)
{
struct ti_ohci *ohci;
struct video_card *video = NULL;
struct video_card *video = NULL, *tmp_vid;
unsigned long flags;
/* We only work with the OHCI-1394 driver */
......@@ -2381,9 +2383,9 @@ static void dv1394_host_reset(struct hpsb_host *host)
/* find the corresponding video_cards */
spin_lock_irqsave(&dv1394_cards_lock, flags);
if (!list_empty(&dv1394_cards)) {
list_for_each_entry(video, &dv1394_cards, list) {
if ((video->id >> 2) == ohci->id)
list_for_each_entry(tmp_vid, &dv1394_cards, list) {
if ((tmp_vid->id >> 2) == host->id) {
video = tmp_vid;
break;
}
}
......
......@@ -76,6 +76,7 @@
#include "iso.h"
#include "nodemgr.h"
#include "eth1394.h"
#include "config_roms.h"
#define ETH1394_PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt, driver_name, ## args)
......@@ -88,7 +89,7 @@
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
"$Rev: 1133 $ Ben Collins <bcollins@debian.org>";
"$Rev: 1175 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
......@@ -106,8 +107,6 @@ struct partial_datagram {
struct list_head frag_info;
};
static struct csr1212_keyval *eth1394_ud = NULL;
struct pdg_list {
struct list_head list; /* partial datagram list per node */
unsigned int sz; /* partial datagram list size per node */
......@@ -461,6 +460,8 @@ 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",
.id_table = eth1394_id_table,
......@@ -553,9 +554,11 @@ static void ether1394_add_host (struct hpsb_host *host)
struct net_device *dev = NULL;
struct eth1394_priv *priv;
static int version_printed = 0;
u64 fifo_addr;
if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
return;
fifo_addr = hpsb_allocate_and_register_addrspace(&eth1394_highlevel,
host,
&addr_ops,
......@@ -634,14 +637,6 @@ static void ether1394_add_host (struct hpsb_host *host)
priv->bc_state = ETHER1394_BC_RUNNING;
}
if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
eth1394_ud) != CSR1212_SUCCESS) {
ETH1394_PRINT (KERN_ERR, dev->name,
"Cannot attach IP 1394 Unit Directory to "
"Config ROM\n");
goto out;
}
hi->host->update_config_rom = 1;
return;
out:
......@@ -668,10 +663,6 @@ static void ether1394_remove_host (struct hpsb_host *host)
if (priv->iso != NULL)
hpsb_iso_shutdown(priv->iso);
csr1212_detach_keyval_from_directory(hi->host->csr.rom->root_kv,
eth1394_ud);
hi->host->update_config_rom = 1;
if (hi->dev) {
unregister_netdev (hi->dev);
free_netdev(hi->dev);
......@@ -1483,7 +1474,6 @@ static inline struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host
p = hpsb_alloc_packet(0);
if (p) {
p->host = host;
p->data = NULL;
p->generation = get_hpsb_generation(host);
p->type = hpsb_async;
}
......@@ -1514,7 +1504,7 @@ static inline int ether1394_prep_write_packet(struct hpsb_packet *p,
| (1 << 8) | (TCODE_WRITEB << 4);
p->header[3] = tx_len << 16;
p->data_size = tx_len + (tx_len % 4 ? 4 - (tx_len % 4) : 0);
p->data_size = (tx_len + 3) & ~3;
p->data = (quadlet_t*)data;
return 0;
......@@ -1807,7 +1797,7 @@ static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr)
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, driver_name);
strcpy (info.version, "$Rev: 1133 $");
strcpy (info.version, "$Rev: 1175 $");
/* FIXME XXX provide sane businfo */
strcpy (info.bus_info, "ieee1394");
if (copy_to_user (useraddr, &info, sizeof (info)))
......@@ -1830,67 +1820,13 @@ static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr)
static int __init ether1394_init_module (void)
{
int ret;
struct csr1212_keyval *spec_id = NULL;
struct csr1212_keyval *spec_desc = NULL;
struct csr1212_keyval *ver = NULL;
struct csr1212_keyval *ver_desc = NULL;
packet_task_cache = kmem_cache_create("packet_task", sizeof(struct packet_task),
0, 0, NULL, NULL);
eth1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
ETHER1394_GASP_SPECIFIER_ID);
spec_desc = csr1212_new_string_descriptor_leaf("IANA");
ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
ETHER1394_GASP_VERSION);
ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
if ((!eth1394_ud) ||
(!spec_id) ||
(!spec_desc) ||
(!ver) ||
(!ver_desc)) {
ret = -ENOMEM;
goto out;
}
ret = csr1212_associate_keyval(spec_id, spec_desc);
if (ret != CSR1212_SUCCESS)
goto out;
ret = csr1212_associate_keyval(ver, ver_desc);
if (ret != CSR1212_SUCCESS)
goto out;
ret = csr1212_attach_keyval_to_directory(eth1394_ud, spec_id);
if (ret != CSR1212_SUCCESS)
goto out;
ret = csr1212_attach_keyval_to_directory(eth1394_ud, ver);
if (ret != CSR1212_SUCCESS)
goto out;
/* Register ourselves as a highlevel driver */
hpsb_register_highlevel(&eth1394_highlevel);
ret = hpsb_register_protocol(&eth1394_proto_driver);
out:
if ((ret != 0) && eth1394_ud) {
csr1212_release_keyval(eth1394_ud);
}
if (spec_id)
csr1212_release_keyval(spec_id);
if (spec_desc)
csr1212_release_keyval(spec_desc);
if (ver)
csr1212_release_keyval(ver);
if (ver_desc)
csr1212_release_keyval(ver_desc);
return ret;
return hpsb_register_protocol(&eth1394_proto_driver);
}
static void __exit ether1394_exit_module (void)
......@@ -1898,10 +1834,6 @@ static void __exit ether1394_exit_module (void)
hpsb_unregister_protocol(&eth1394_proto_driver);
hpsb_unregister_highlevel(&eth1394_highlevel);
kmem_cache_destroy(packet_task_cache);
if (eth1394_ud) {
csr1212_release_keyval(eth1394_ud);
}
}
module_init(ether1394_init_module);
......
......@@ -24,6 +24,8 @@
#ifndef __ETH1394_H
#define __ETH1394_H
#include <linux/netdevice.h>
#include "ieee1394.h"
/* Register for incoming packets. This is 4096 bytes, which supports up to
......
......@@ -27,6 +27,7 @@
#include "highlevel.h"
#include "nodemgr.h"
#include "csr.h"
#include "config_roms.h"
static void delayed_reset_bus(unsigned long __reset_info)
......@@ -103,6 +104,7 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
* Return Value: a pointer to the &hpsb_host if succesful, %NULL if
* no memory was available.
*/
static DECLARE_MUTEX(host_num_alloc);
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev)
......@@ -148,14 +150,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->topology_map = h->csr.topology_map + 3;
h->speed_map = (u8 *)(h->csr.speed_map + 2);
while (1) {
if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
h->id = hostnum;
break;
}
down(&host_num_alloc);
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
hostnum++;
}
h->id = hostnum;
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
......@@ -169,12 +169,21 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
class_device_register(&h->class_dev);
get_device(&h->device);
up(&host_num_alloc);
return h;
}
void hpsb_add_host(struct hpsb_host *host)
int hpsb_add_host(struct hpsb_host *host)
{
if (hpsb_default_host_entry(host))
return -ENOMEM;
hpsb_add_extra_config_roms(host);
highlevel_add_host(host);
return 0;
}
void hpsb_remove_host(struct hpsb_host *host)
......@@ -184,6 +193,8 @@ void hpsb_remove_host(struct hpsb_host *host)
highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
class_device_unregister(&host->class_dev);
device_unregister(&host->device);
}
......
......@@ -66,6 +66,8 @@ struct hpsb_host {
int update_config_rom;
struct timer_list delayed_reset;
unsigned int config_roms;
struct list_head addr_space;
};
......@@ -191,7 +193,7 @@ struct hpsb_host_driver {
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev);
void hpsb_add_host(struct hpsb_host *host);
int hpsb_add_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *h);
/* The following 2 functions are deprecated and will be removed when the
......
......@@ -36,8 +36,11 @@
#define ACK_BUSY_X 0x4
#define ACK_BUSY_A 0x5
#define ACK_BUSY_B 0x6
#define ACK_TARDY 0xb
#define ACK_CONFLICT_ERROR 0xc
#define ACK_DATA_ERROR 0xd
#define ACK_TYPE_ERROR 0xe
#define ACK_ADDRESS_ERROR 0xf
/* Non-standard "ACK codes" for internal use */
#define ACKX_NONE (-1)
......
......@@ -44,6 +44,7 @@
#include "nodemgr.h"
#include "dma.h"
#include "iso.h"
#include "config_roms.h"
/*
* Disable the nodemgr detection and config rom reading functionality.
......@@ -92,7 +93,7 @@ static void queue_packet_complete(struct hpsb_packet *packet);
void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
void (*routine)(void *), void *data)
{
BUG_ON(packet->complete_routine != NULL);
WARN_ON(packet->complete_routine != NULL);
packet->complete_routine = routine;
packet->complete_data = data;
return;
......@@ -122,16 +123,23 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
{
struct hpsb_packet *packet = NULL;
void *data = NULL;
int gfp_flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
packet = kmem_cache_alloc(hpsb_packet_cache, GFP_ATOMIC);
packet = kmem_cache_alloc(hpsb_packet_cache, gfp_flags);
if (packet == NULL)
return NULL;
memset(packet, 0, sizeof(struct hpsb_packet));
memset(packet, 0, sizeof(*packet));
packet->header = packet->embedded_header;
INIT_LIST_HEAD(&packet->list);
packet->state = hpsb_unused;
packet->generation = -1;
atomic_set(&packet->refcnt, 1);
if (data_size) {
data = kmalloc(data_size + 8, GFP_ATOMIC);
data_size = (data_size + 3) & ~3;
data = kmalloc(data_size + 8, gfp_flags);
if (data == NULL) {
kmem_cache_free(hpsb_packet_cache, packet);
return NULL;
......@@ -141,12 +149,6 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
packet->data_size = data_size;
}
INIT_LIST_HEAD(&packet->list);
packet->complete_routine = NULL;
packet->complete_data = NULL;
packet->state = hpsb_unused;
packet->generation = -1;
return packet;
}
......@@ -155,15 +157,14 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
* hpsb_free_packet - free packet and data associated with it
* @packet: packet to free (is NULL safe)
*
* This function will free packet->data, packet->header and finally the packet
* itself.
* This function will free packet->data and finally the packet itself.
*/
void hpsb_free_packet(struct hpsb_packet *packet)
{
if (!packet) return;
if (packet && atomic_dec_and_test(&packet->refcnt)) {
kfree(packet->data);
kmem_cache_free(hpsb_packet_cache, packet);
}
}
......@@ -402,8 +403,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode)
{
unsigned long flags;
packet->ack_code = ackcode;
if (packet->no_waiter) {
......@@ -413,18 +412,22 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
atomic_dec(&packet->refcnt);
list_del(&packet->list);
packet->state = hpsb_complete;
queue_packet_complete(packet);
return;
}
if (packet->state == hpsb_complete) {
hpsb_free_packet(packet);
return;
}
atomic_dec(&packet->refcnt);
packet->state = hpsb_pending;
packet->sendtime = jiffies;
spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_add_tail(&packet->list, &host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
......@@ -502,6 +505,15 @@ int hpsb_send_packet(struct hpsb_packet *packet)
packet->state = hpsb_queued;
if (!packet->no_waiter || packet->expect_response) {
unsigned long flags;
atomic_inc(&packet->refcnt);
spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_add_tail(&packet->list, &host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
}
if (packet->node_id == host->node_id)
{ /* it is a local request, so handle it locally */
quadlet_t *data;
......@@ -658,6 +670,11 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
break;
}
if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
packet->ack_code = ACK_PENDING;
}
packet->state = hpsb_complete;
queue_packet_complete(packet);
}
......@@ -1024,10 +1041,16 @@ static int hpsbpkt_thread(void *__hi)
complete_and_exit(&khpsbpkt_complete, 0);
}
static int __init ieee1394_init(void)
{
int i;
if (hpsb_init_config_roms()) {
HPSB_ERR("Failed to initialize some config rom entries.\n");
HPSB_ERR("Some features may not be available\n");
}
khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL);
if (khpsbpkt_pid < 0) {
HPSB_ERR("Failed to start hpsbpkt thread!\n");
......@@ -1044,7 +1067,7 @@ static int __init ieee1394_init(void)
devfs_mk_dir("ieee1394");
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
0, 0, NULL, NULL);
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
bus_register(&ieee1394_bus_type);
for (i = 0; fw_bus_attrs[i]; i++)
......@@ -1083,6 +1106,8 @@ static void __exit ieee1394_cleanup(void)
kmem_cache_destroy(hpsb_packet_cache);
hpsb_cleanup_config_roms();
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
devfs_remove("ieee1394");
}
......
......@@ -4,6 +4,7 @@
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
......@@ -59,6 +60,8 @@ struct hpsb_packet {
struct hpsb_host *host;
unsigned int generation;
atomic_t refcnt;
/* Function (and possible data to pass to it) to call when this
* packet is completed. */
void (*complete_routine)(void *);
......
......@@ -239,6 +239,11 @@ int hpsb_packet_success(struct hpsb_packet *packet)
return -EAGAIN;
}
case ACK_ADDRESS_ERROR:
return -EINVAL;
case ACK_TARDY:
case ACK_CONFLICT_ERROR:
case ACKX_NONE:
case ACKX_SEND_ERROR:
case ACKX_ABORTED:
......@@ -263,7 +268,7 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
if (length == 0)
return NULL;
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
......@@ -291,7 +296,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
if (length == 0)
return NULL;
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
......@@ -325,7 +330,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
if (length == 0)
return NULL;
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
......
......@@ -79,7 +79,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
{
return (bus_info_data[2] >> 8) & 0x3;
return (CSR1212_BE32_TO_CPU(bus_info_data[2]) >> 8) & 0x3;
}
static struct csr1212_bus_ops nodemgr_csr_ops = {
......@@ -1286,18 +1286,19 @@ static void nodemgr_resume_ne(struct node_entry *ne)
}
static void nodemgr_ud_update_pdrv(struct unit_directory *ud)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
struct device *dev;
struct unit_directory *ud;
struct hpsb_protocol_driver *pdrv;
struct class *class = &nodemgr_ud_class;
struct class_device *cdev;
if (!get_device(&ud->device))
return;
list_for_each_entry(dev, &ud->device.children, node)
nodemgr_ud_update_pdrv(container_of(dev, struct unit_directory, device));
down_read(&class->subsys.rwsem);
list_for_each_entry(cdev, &class->children, node) {
ud = container_of(cdev, struct unit_directory, class_dev);
if (ud->ne != ne || !ud->device.driver)
continue;
if (ud->device.driver) {
pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
if (pdrv->update && pdrv->update(ud)) {
......@@ -1306,14 +1307,13 @@ static void nodemgr_ud_update_pdrv(struct unit_directory *ud)
up_write(&ud->device.bus->subsys.rwsem);
}
}
put_device(&ud->device);
up_read(&class->subsys.rwsem);
}
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
{
struct device *dev, *udev;
struct device *dev;
if (ne->host != hi->host || ne->in_limbo)
return;
......@@ -1330,8 +1330,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
if (ne->needs_probe)
nodemgr_process_root_directory(hi, ne);
else if (ne->generation == generation)
list_for_each_entry(udev, &dev->children, node)
nodemgr_ud_update_pdrv(container_of(udev, struct unit_directory, device));
nodemgr_update_pdrv(ne);
else
nodemgr_suspend_ne(ne);
......
This diff is collapsed.
......@@ -149,8 +149,6 @@ struct ohci1394_iso_tasklet {
};
struct ti_ohci {
int id; /* sequential card number */
struct pci_dev *dev;
enum {
......
......@@ -1516,11 +1516,6 @@ static int __devinit add_card(struct pci_dev *dev,
return error; \
} while (0)
struct csr1212_keyval *root;
struct csr1212_keyval *vend_id = NULL;
struct csr1212_keyval *text = NULL;
int ret;
char irq_buf[16];
struct hpsb_host *host;
struct ti_lynx *lynx; /* shortcut to currently handled device */
......@@ -1890,42 +1885,14 @@ static int __devinit add_card(struct pci_dev *dev,
else
host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
/* Setup initial root directory entries */
root = host->csr.rom->root_kv;
vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
be32_to_cpu(lynx->bus_info_block[3]) >> 8);
text = csr1212_new_string_descriptor_leaf("Linux 1394 - PCI-Lynx");
if (!vend_id || !text) {
if (vend_id)
csr1212_release_keyval(vend_id);
if (text)
csr1212_release_keyval(text);
if (hpsb_add_host(host)) {
error = -ENOMEM;
FAIL("Failed to allocate memory for mandatory ConfigROM entries!");
}
ret = csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text); /* no longer needed locally. */
if(ret != CSR1212_SUCCESS) {
csr1212_release_keyval(vend_id);
error = ret;
FAIL("Failed to associate text descriptor to vendor id");
}
ret = csr1212_attach_keyval_to_directory(root, vend_id);
csr1212_release_keyval(vend_id); /* no longer needed locally. */
if(ret != CSR1212_SUCCESS) {
error = ret;
FAIL("Failed to attach vendor id to root directory");
FAIL("Failed to register host with highlevel");
}
host->update_config_rom = 1;
hpsb_add_host(host);
lynx->state = is_host;
return ret;
return 0;
#undef FAIL
}
......
......@@ -78,7 +78,7 @@
#include "sbp2.h"
static char version[] __devinitdata =
"$Rev: 1144 $ Ben Collins <bcollins@debian.org>";
"$Rev: 1170 $ Ben Collins <bcollins@debian.org>";
/*
* Module load parameter definitions
......@@ -677,6 +677,10 @@ static int sbp2_update(struct unit_directory *ud)
*/
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
/* Make sure we unblock requests (since this is likely after a bus
* reset). */
scsi_unblock_requests(scsi_id->scsi_host);
return 0;
}
......@@ -2544,8 +2548,6 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
}
}
scsi_unblock_requests(scsi_id->scsi_host);
return;
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment