diff options
| -rw-r--r-- | drivers/ieee1394/amdtp.c | 65 | ||||
| -rw-r--r-- | drivers/ieee1394/cmp.c | 70 | ||||
| -rw-r--r-- | drivers/ieee1394/csr.c | 12 | ||||
| -rw-r--r-- | drivers/ieee1394/dv1394-private.h | 3 | ||||
| -rw-r--r-- | drivers/ieee1394/dv1394.c | 13 | ||||
| -rw-r--r-- | drivers/ieee1394/eth1394.c | 105 | ||||
| -rw-r--r-- | drivers/ieee1394/eth1394.h | 1 | ||||
| -rw-r--r-- | drivers/ieee1394/highlevel.c | 218 | ||||
| -rw-r--r-- | drivers/ieee1394/highlevel.h | 24 | ||||
| -rw-r--r-- | drivers/ieee1394/hosts.c | 55 | ||||
| -rw-r--r-- | drivers/ieee1394/hosts.h | 6 | ||||
| -rw-r--r-- | drivers/ieee1394/ieee1394_core.c | 105 | ||||
| -rw-r--r-- | drivers/ieee1394/ieee1394_core.h | 14 | ||||
| -rw-r--r-- | drivers/ieee1394/nodemgr.c | 125 | ||||
| -rw-r--r-- | drivers/ieee1394/ohci1394.c | 2 | ||||
| -rw-r--r-- | drivers/ieee1394/raw1394.c | 21 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.c | 95 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.h | 6 | ||||
| -rw-r--r-- | drivers/ieee1394/video1394.c | 131 |
19 files changed, 509 insertions, 562 deletions
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 6e7b20f898c3..e2e995f3d405 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -266,12 +266,10 @@ struct amdtp_host { struct ti_ohci *ohci; struct list_head stream_list; spinlock_t stream_list_lock; - struct list_head link; }; static struct hpsb_highlevel *amdtp_highlevel; -static LIST_HEAD(host_list); -static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED; + /* FIXME: This doesn't belong here... */ @@ -347,7 +345,7 @@ static void stream_start_dma(struct stream *s, struct packet_list *pl) { u32 syt_cycle, cycle_count, start_cycle; - cycle_count = reg_read(s->host->host->hostdata, + cycle_count = reg_read(s->host->ohci, OHCI1394_IsochronousCycleTimer) >> 12; syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f; @@ -1169,15 +1167,9 @@ static unsigned int amdtp_poll(struct file *file, poll_table *pt) static int amdtp_open(struct inode *inode, struct file *file) { struct amdtp_host *host; + int i = ieee1394_file_to_instance(file); - /* FIXME: We just grab the first registered host */ - spin_lock(&host_list_lock); - if (!list_empty(&host_list)) - host = list_entry(host_list.next, struct amdtp_host, link); - else - host = NULL; - spin_unlock(&host_list_lock); - + host = hpsb_get_hostinfo_bykey(amdtp_highlevel, i); if (host == NULL) return -ENODEV; @@ -1209,44 +1201,45 @@ static struct file_operations amdtp_fops = /* IEEE1394 Subsystem functions */ -static void amdtp_add_host(struct hpsb_host *host) +static void amdtp_add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) { struct amdtp_host *ah; + int minor; + char name[16]; if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) return; - ah = kmalloc(sizeof *ah, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); + ah = hpsb_create_hostinfo(hl, host, sizeof(*ah)); + if (!ah) { + HPSB_ERR("amdtp: Unable able to alloc hostinfo"); + return; + } + ah->host = host; ah->ohci = host->hostdata; + + hpsb_set_hostinfo_key(hl, host, ah->ohci->id); + + minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id; + + sprintf(name, "amdtp/%d", ah->ohci->id); + INIT_LIST_HEAD(&ah->stream_list); spin_lock_init(&ah->stream_list_lock); - spin_lock_irq(&host_list_lock); - list_add_tail(&ah->link, &host_list); - spin_unlock_irq(&host_list_lock); + devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, + S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL); } static void amdtp_remove_host(struct hpsb_host *host) { - struct list_head *lh; - struct amdtp_host *ah; + struct amdtp_host *ah = hpsb_get_hostinfo(amdtp_highlevel, host); - spin_lock_irq(&host_list_lock); - list_for_each(lh, &host_list) { - if (list_entry(lh, struct amdtp_host, link)->host == host) { - list_del(lh); - break; - } - } - spin_unlock_irq(&host_list_lock); - - if (lh != &host_list) { - ah = list_entry(lh, struct amdtp_host, link); - kfree(ah); - } - else - HPSB_ERR("remove_host: bogus ohci host: %p", host); + if (ah) + devfs_remove("amdtp/%d", ah->ohci->id); + + return; } static struct hpsb_highlevel_ops amdtp_highlevel_ops = { @@ -1273,10 +1266,13 @@ static int __init amdtp_init_module (void) return -EIO; } + devfs_mk_dir("amdtp"); + amdtp_highlevel = hpsb_register_highlevel ("amdtp", &amdtp_highlevel_ops); if (amdtp_highlevel == NULL) { HPSB_ERR("amdtp: unable to register highlevel ops"); + devfs_remove("amdtp"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); return -EIO; } @@ -1309,6 +1305,7 @@ static void __exit amdtp_exit_module (void) #endif hpsb_unregister_highlevel(amdtp_highlevel); + devfs_remove("amdtp"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); HPSB_INFO("Unloaded AMDTP driver"); diff --git a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c index ba7f58475c74..9f21025b0d1c 100644 --- a/drivers/ieee1394/cmp.c +++ b/drivers/ieee1394/cmp.c @@ -65,8 +65,6 @@ struct cmp_host { quadlet_t impr_quadlet; } v; struct plug ipcr[2]; - - struct list_head link; }; enum { @@ -79,31 +77,6 @@ enum { static struct hpsb_highlevel *cmp_highlevel; -static LIST_HEAD(host_list); -static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED; - -static struct cmp_host * -lookup_cmp_host(struct hpsb_host *host) -{ - struct cmp_host *ch; - struct list_head *lh; - unsigned long flags; - - ch = NULL; - spin_lock_irqsave(&host_list_lock, flags); - list_for_each(lh, &host_list) { - ch = list_entry(lh, struct cmp_host, link); - if (ch->host == host) - break; - } - spin_unlock_irqrestore(&host_list_lock, flags); - - if (lh == &host_list) - return NULL; - else - return ch; -} - struct cmp_pcr * cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, void (*update)(struct cmp_pcr *pcr, void *data), @@ -112,7 +85,7 @@ cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, struct cmp_host *ch; struct plug *plug; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(cmp_highlevel, host); if (opcr_number >= ch->u.ompr.nplugs || ch->opcr[opcr_number].update != NULL) @@ -135,7 +108,7 @@ void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr) struct cmp_host *ch; struct plug *plug; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(cmp_highlevel, host); plug = (struct plug *)opcr; if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG(); @@ -155,48 +128,34 @@ static void reset_plugs(struct cmp_host *ch) } } -static void cmp_add_host(struct hpsb_host *host) +static void cmp_add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) { - struct cmp_host *ch; + struct cmp_host *ch = hpsb_create_hostinfo(hl, host, sizeof (*ch)); - ch = kmalloc(sizeof *ch, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); if (ch == NULL) { HPSB_ERR("Failed to allocate cmp_host"); return; } - memset(ch, 0, sizeof *ch); + ch->host = host; ch->u.ompr.rate = SPEED_100; ch->u.ompr.bcast_channel_base = 63; ch->u.ompr.nplugs = 2; - reset_plugs(ch); - spin_lock_irq(&host_list_lock); - list_add_tail(&ch->link, &host_list); - spin_unlock_irq(&host_list_lock); -} - -static void cmp_host_reset(struct hpsb_host *host) -{ - struct cmp_host *ch; - - ch = lookup_cmp_host(host); - if (ch == NULL) BUG(); reset_plugs(ch); } -static void cmp_remove_host(struct hpsb_host *host) +static void cmp_host_reset(struct hpsb_host *host) { struct cmp_host *ch; - ch = lookup_cmp_host(host); - if (ch == NULL) BUG(); - - spin_lock_irq(&host_list_lock); - list_del(&ch->link); - spin_unlock_irq(&host_list_lock); + ch = hpsb_get_hostinfo(cmp_highlevel, host); + if (ch == NULL) { + HPSB_ERR("cmp: Tried to reset unknown host"); + return; + } - kfree(ch); + reset_plugs(ch); } static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, @@ -209,7 +168,7 @@ static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, if (length != 4) return RCODE_TYPE_ERROR; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(cmp_highlevel, host); if (csraddr == 0x900) { *buf = cpu_to_be32(ch->u.ompr_quadlet); return RCODE_COMPLETE; @@ -242,7 +201,7 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, int plug; struct cmp_host *ch; - ch = lookup_cmp_host(host); + ch = hpsb_get_hostinfo(cmp_highlevel, host); if (extcode != EXTCODE_COMPARE_SWAP) return RCODE_TYPE_ERROR; @@ -301,7 +260,6 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, static struct hpsb_highlevel_ops cmp_highlevel_ops = { .add_host = cmp_add_host, - .remove_host = cmp_remove_host, .host_reset = cmp_host_reset, }; diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index e13186e64115..75492616e682 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c @@ -90,7 +90,7 @@ static void host_reset(struct hpsb_host *host) } -static void add_host(struct hpsb_host *host) +static void add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) { host->csr.lock = SPIN_LOCK_UNLOCKED; @@ -118,7 +118,9 @@ static void add_host(struct hpsb_host *host) int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, size_t size, unsigned char rom_version) { - int ret,flags; + unsigned long flags; + int ret; + spin_lock_irqsave(&host->csr.lock, flags); if (rom_version != host->csr.rom_version) ret = -1; @@ -137,7 +139,9 @@ int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, size_t buffersize, size_t *rom_size, unsigned char *rom_version) { - int ret,flags; + unsigned long flags; + int ret; + spin_lock_irqsave(&host->csr.lock, flags); *rom_version=host->csr.rom_version; *rom_size=host->csr.rom_size; @@ -156,9 +160,9 @@ int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, u64 addr, unsigned int length, u16 fl) { + unsigned long flags; int csraddr = addr - CSR_REGISTER_BASE; const char *src; - int flags; spin_lock_irqsave(&host->csr.lock, flags); diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h index 9fe654b0ffb9..14b970fef601 100644 --- a/drivers/ieee1394/dv1394-private.h +++ b/drivers/ieee1394/dv1394-private.h @@ -403,9 +403,6 @@ struct video_card { /* entry in dv1394_cards */ struct list_head list; - /* handle to /dev/ieee1394/dv/N, NULL if devfs not in use */ - devfs_handle_t devfs_handle; - /* OHCI card IT DMA context number, -1 if not in use */ int ohci_it_ctx; struct ohci1394_iso_tasklet it_tasklet; diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 03a9a5d1546f..e06c50e7cc81 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2458,14 +2458,9 @@ static int dv1394_devfs_add_entry(struct video_card *video) (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), (video->mode == MODE_RECEIVE ? "in" : "out")); - video->devfs_handle = devfs_register(NULL, buf, 0, IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, - S_IFCHR | S_IRUGO | S_IWUGO, - &dv1394_fops, video); - if (video->devfs_handle == NULL) { - printk(KERN_ERR "dv1394: unable to create /dev/%s\n", buf); - return -ENOMEM; - } + devfs_register(NULL, buf, 0, IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, + S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video); return 0; } #endif /* CONFIG_DEVFS_FS */ @@ -2650,7 +2645,7 @@ static void dv1394_remove_host (struct hpsb_host *host) #endif } -static void dv1394_add_host (struct hpsb_host *host) +static void dv1394_add_host (struct hpsb_host *host, struct hpsb_highlevel *hl) { struct ti_ohci *ohci; char buf[16]; diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 5b0b99628c1d..f9e1584d9010 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -78,7 +78,7 @@ printk(KERN_ERR fmt, ## args) static char version[] __devinitdata = - "$Rev: 806 $ Ben Collins <bcollins@debian.org>"; + "$Rev: 886 $ Ben Collins <bcollins@debian.org>"; /* Our ieee1394 highlevel driver */ #define ETHER1394_DRIVER_NAME "ether1394" @@ -86,9 +86,6 @@ static char version[] __devinitdata = static kmem_cache_t *packet_task_cache; static struct hpsb_highlevel *hl_handle = NULL; -/* Card handling */ -static LIST_HEAD (host_info_list); -static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; /* Use common.lf to determine header len */ static int hdr_type_len[] = { @@ -105,40 +102,6 @@ MODULE_LICENSE("GPL"); static void ether1394_iso(struct hpsb_iso *iso); -/* Find our host_info struct for a given host pointer. Must be called - * under spinlock. */ -static inline struct host_info *find_host_info (struct hpsb_host *host) -{ - struct list_head *lh; - struct host_info *hi; - - lh = host_info_list.next; - while (lh != &host_info_list) { - hi = list_entry (lh, struct host_info, list); - - if (hi->host == host) - return hi; - - lh = lh->next; - } - return NULL; -} - -/* Find the network device for our host */ -static inline struct net_device *ether1394_find_dev (struct hpsb_host *host) -{ - struct host_info *hi; - - spin_lock_irq (&host_info_lock); - hi = find_host_info (host); - spin_unlock_irq (&host_info_lock); - - if (hi == NULL) - return NULL; - - return hi->dev; -} - /* This is called after an "ifup" */ static int ether1394_open (struct net_device *dev) { @@ -355,7 +318,7 @@ static int ether1394_init_dev (struct net_device *dev) * when the module is installed. This is where we add all of our ethernet * devices. One for each host. */ -static void ether1394_add_host (struct hpsb_host *host) +static void ether1394_add_host (struct hpsb_host *host, struct hpsb_highlevel *hl) { struct host_info *hi = NULL; struct net_device *dev = NULL; @@ -378,30 +341,22 @@ static void ether1394_add_host (struct hpsb_host *host) priv->host = host; - hi = (struct host_info *)kmalloc (sizeof (struct host_info), - in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); + hi = hpsb_create_hostinfo(hl, host, sizeof(*hi)); if (hi == NULL) goto out; if (register_netdev (dev)) { ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); - kfree (dev); - kfree (hi); - return; + goto out; } ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n", host->driver->name); - INIT_LIST_HEAD (&hi->list); hi->host = host; hi->dev = dev; - spin_lock_irq (&host_info_lock); - list_add_tail (&hi->list, &host_info_list); - spin_unlock_irq (&host_info_lock); - /* Ignore validity in hopes that it will be set in the future. It'll * check it on transmit. */ priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; @@ -416,6 +371,9 @@ static void ether1394_add_host (struct hpsb_host *host) out: if (dev != NULL) kfree (dev); + if (hi) + hpsb_destroy_hostinfo(hl, host); + ETH1394_PRINT_G (KERN_ERR, "Out of memory\n"); return; @@ -424,20 +382,17 @@ out: /* Remove a card from our list */ static void ether1394_remove_host (struct hpsb_host *host) { - struct eth1394_priv *priv; - struct host_info *hi; + struct host_info *hi = hpsb_get_hostinfo(hl_handle, host); - spin_lock_irq (&host_info_lock); - hi = find_host_info (host); if (hi != NULL) { - priv = (struct eth1394_priv *)hi->dev->priv; + struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; + priv->bc_state = ETHER1394_BC_CLOSED; unregister_netdev (hi->dev); + hpsb_iso_shutdown(priv->iso); + kfree (hi->dev); - list_del (&hi->list); - kfree (hi); } - spin_unlock_irq (&host_info_lock); return; } @@ -445,12 +400,15 @@ static void ether1394_remove_host (struct hpsb_host *host) /* A reset has just arisen */ static void ether1394_host_reset (struct hpsb_host *host) { - struct net_device *dev = ether1394_find_dev(host); + struct host_info *hi = hpsb_get_hostinfo(hl_handle, host); + struct net_device *dev; /* This can happen for hosts that we don't use */ - if (dev == NULL) + if (hi == NULL) return; + dev = hi->dev; + /* Reset our private host data, but not our mtu */ netif_stop_queue (dev); ether1394_reset_priv (dev, 0); @@ -559,15 +517,18 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid, struct sk_buff *skb; char *buf = (char *)data; unsigned long flags; - struct net_device *dev = ether1394_find_dev (host); + struct host_info *hi = hpsb_get_hostinfo(hl_handle, host); + struct net_device *dev; struct eth1394_priv *priv; - if (dev == NULL) { + if (hi == NULL) { ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n", host); return RCODE_ADDRESS_ERROR; } + dev = hi->dev; + priv = (struct eth1394_priv *)dev->priv; /* A packet has been received by the ieee1394 bus. Build an skbuff @@ -627,8 +588,9 @@ static void ether1394_iso(struct hpsb_iso *iso) struct sk_buff *skb; quadlet_t *data; char *buf; - int flags; - struct net_device *dev = ether1394_find_dev(iso->host); + unsigned long flags; + struct host_info *hi = hpsb_get_hostinfo(hl_handle, iso->host); + struct net_device *dev; struct eth1394_priv *priv; unsigned int len; u32 specifier_id; @@ -636,12 +598,14 @@ static void ether1394_iso(struct hpsb_iso *iso) int i; int nready; - if (dev == NULL) { + if (hi == NULL) { ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n", iso->host->driver->name); return; } + dev = hi->dev; + nready = hpsb_iso_n_ready(iso); for(i = 0; i < nready; i++) { struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; @@ -941,19 +905,6 @@ static int __init ether1394_init_module (void) static void __exit ether1394_exit_module (void) { - struct list_head *lh; - struct host_info *hi; - struct eth1394_priv *priv; - - lh = host_info_list.next; - while (lh != &host_info_list) { - hi = list_entry (lh, struct host_info, list); - priv = (struct eth1394_priv*)hi->dev->priv; - if (priv->bc_state != ETHER1394_BC_CLOSED) { - hpsb_iso_shutdown(priv->iso); - } - lh = lh->next; - } hpsb_unregister_highlevel (hl_handle); kmem_cache_destroy(packet_task_cache); } diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index 1c38fb02cdfe..40fa50d02616 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -56,7 +56,6 @@ struct eth1394_priv { }; struct host_info { - struct list_head list; struct hpsb_host *host; struct net_device *dev; }; diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 843675b655e6..6ea446704217 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -19,6 +19,7 @@ #include <linux/config.h> #include <linux/slab.h> +#include <linux/list.h> #include "ieee1394.h" #include "ieee1394_types.h" @@ -27,20 +28,192 @@ #include "highlevel.h" -LIST_HEAD(hl_drivers); +struct hl_host_info { + struct list_head list; + struct hpsb_host *host; + size_t size; + unsigned long key; + void *data; +}; + + +static LIST_HEAD(hl_drivers); static DECLARE_MUTEX(hl_drivers_lock); -LIST_HEAD(addr_space); -rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; +static LIST_HEAD(addr_space); +static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; /* addr_space list will have zero and max already included as bounds */ static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL }; static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr; + +/* Internal usage. Must be called with hl_drivers_lock held */ +static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, + struct hpsb_host *host) +{ + struct hl_host_info *hi; + struct list_head *lh; + + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->host == host) + return hi; + } + + return NULL; +} + + +/* Returns a per host/driver data structure that was previously stored by + * hpsb_create_hostinfo. */ +void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi; + void *data = NULL; + + read_lock(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + if (hi) + data = hi->data; + read_unlock(&hl_drivers_lock); + + return data; +} + + +/* If size is zero, then the return here is only valid for error checking */ +void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + size_t data_size) +{ + struct hl_host_info *hi; + void *data; + + read_lock(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + read_unlock(&hl_drivers_lock); + if (hi) { + HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists", + hl->name); + return NULL; + } + + hi = kmalloc(sizeof(*hi) + data_size, GFP_KERNEL); + if (!hi) + return NULL; + + memset(hi, 0, sizeof(*hi) + data_size); + + if (data_size) { + data = hi->data = hi + 1; + hi->size = data_size; + } else + data = hi; + + hi->host = host; + + write_lock_irq(&hl_drivers_lock); + list_add_tail(&hi->list, &hl->host_info_list); + write_unlock_irq(&hl_drivers_lock); + + return data; +} + + +int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + void *data) +{ + struct hl_host_info *hi; + int ret = -EINVAL; + + write_lock_irq(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + if (hi) { + if (!hi->size && !hi->data) { + hi->data = data; + ret = 0; + } else + HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data", + hl->name); + } else + HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", + hl->name); + write_unlock_irq(&hl_drivers_lock); + + return ret; +} + + +void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi; + + write_lock_irq(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + if (hi) { + list_del(&hi->list); + kfree(hi); + } + write_unlock_irq(&hl_drivers_lock); + + return; +} + + +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key) +{ + struct hl_host_info *hi; + + write_lock(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + if (hi) + hi->key = key; + write_unlock(&hl_drivers_lock); + + return; +} + + +unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + struct hl_host_info *hi; + unsigned long key = 0; + + read_lock(&hl_drivers_lock); + hi = hl_get_hostinfo(hl, host); + if (hi) + key = hi->key; + read_unlock(&hl_drivers_lock); + + return key; +} + + +void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) +{ + struct list_head *lh; + struct hl_host_info *hi; + void *data = NULL; + + read_lock(&hl_drivers_lock); + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->key == key) { + data = hi->data; + break; + } + } + read_unlock(&hl_drivers_lock); + + return data; +} + + struct hpsb_highlevel *hpsb_register_highlevel(const char *name, struct hpsb_highlevel_ops *ops) { struct hpsb_highlevel *hl; + struct list_head *lh; hl = (struct hpsb_highlevel *)kmalloc(sizeof(struct hpsb_highlevel), GFP_KERNEL); @@ -50,6 +223,8 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name, INIT_LIST_HEAD(&hl->hl_list); INIT_LIST_HEAD(&hl->addr_list); + INIT_LIST_HEAD(&hl->host_info_list); + hl->name = name; hl->op = ops; @@ -57,15 +232,21 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name, list_add_tail(&hl->hl_list, &hl_drivers); up(&hl_drivers_lock); - if (hl->op->add_host) - hl_all_hosts(hl->op->add_host); + if (hl->op->add_host) { + down(&hpsb_hosts_lock); + list_for_each (lh, &hpsb_hosts) { + struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list); + hl->op->add_host(host, hl); + } + up(&hpsb_hosts_lock); + } return hl; } void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) { - struct list_head *entry; + struct list_head *lh, *next; struct hpsb_address_serve *as; if (hl == NULL) { @@ -73,12 +254,9 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) } write_lock_irq(&addr_space_lock); - entry = hl->addr_list.next; - - while (entry != &hl->addr_list) { - as = list_entry(entry, struct hpsb_address_serve, addr_list); + list_for_each_safe (lh, next, &hl->addr_list) { + as = list_entry(lh, struct hpsb_address_serve, addr_list); list_del(&as->as_list); - entry = entry->next; kfree(as); } write_unlock_irq(&addr_space_lock); @@ -87,8 +265,16 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) list_del(&hl->hl_list); up(&hl_drivers_lock); - if (hl->op->remove_host) - hl_all_hosts(hl->op->remove_host); + if (hl->op->remove_host) { + down(&hpsb_hosts_lock); + list_for_each(lh, &hpsb_hosts) { + struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list); + + hl->op->remove_host(host); + hpsb_destroy_hostinfo(hl, host); + } + up(&hpsb_hosts_lock); + } kfree(hl); } @@ -206,7 +392,7 @@ void highlevel_add_host(struct hpsb_host *host) hl = list_entry(entry, struct hpsb_highlevel, hl_list); if (hl->op->add_host) - hl->op->add_host(host); + hl->op->add_host(host, hl); } up(&hl_drivers_lock); } @@ -220,8 +406,10 @@ void highlevel_remove_host(struct hpsb_host *host) list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->remove_host) + if (hl->op->remove_host) { hl->op->remove_host(host); + hpsb_destroy_hostinfo(hl, host); + } } up(&hl_drivers_lock); } diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index d6a90ddf2425..420c404f7b05 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h @@ -11,6 +11,9 @@ struct hpsb_highlevel { const char *name; struct hpsb_highlevel_ops *op; + + /* Used by the highlevel drivers to store data per host */ + struct list_head host_info_list; }; @@ -38,7 +41,7 @@ struct hpsb_highlevel_ops { /* New host initialized. Will also be called during * hpsb_register_highlevel for all hosts already installed. */ - void (*add_host) (struct hpsb_host *host); + void (*add_host) (struct hpsb_host *host, struct hpsb_highlevel *hl); /* Host about to be removed. Will also be called during * hpsb_unregister_highlevel once for each host. */ @@ -155,4 +158,23 @@ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel); + +/* Retrieve a hostinfo pointer bound to this driver/host */ +void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); +/* Allocate a hostinfo pointer of data_size bound to this driver/host */ +void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + size_t data_size); +/* Free and remove the hostinfo pointer bound to this driver/host */ +void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); +/* Set an alternate lookup key for the hostinfo bound to this driver/host */ +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key); +/* Retrieve the alternate lookup key for the hostinfo bound to this driver/host */ +unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host); +/* Retrive a hostinfo pointer bound to this driver using its alternate key */ +void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key); +/* Set the hostinfo pointer to something useful. Usually follows a call to + * hpsb_create_hostinfo, where the size is 0. */ +int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data); + + #endif /* IEEE1394_HIGHLEVEL_H */ diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 1726629944bc..54e4069df3d3 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -22,12 +22,8 @@ #include "ieee1394_core.h" #include "highlevel.h" -static struct list_head hosts = LIST_HEAD_INIT(hosts); -static struct list_head host_drivers = LIST_HEAD_INIT(host_drivers); - -spinlock_t hosts_lock = SPIN_LOCK_UNLOCKED; -spinlock_t host_drivers_lock = SPIN_LOCK_UNLOCKED; - +LIST_HEAD(hpsb_hosts); +DECLARE_MUTEX(hpsb_hosts_lock); static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) { @@ -64,11 +60,10 @@ static struct hpsb_host_driver dummy_driver = { int hpsb_ref_host(struct hpsb_host *host) { struct list_head *lh; - unsigned long flags; int retval = 0; - spin_lock_irqsave(&hosts_lock, flags); - list_for_each(lh, &hosts) { + down(&hpsb_hosts_lock); + list_for_each(lh, &hpsb_hosts) { if (host == list_entry(lh, struct hpsb_host, host_list)) { if (try_module_get(host->driver->owner)) { host->refcount++; @@ -77,7 +72,7 @@ int hpsb_ref_host(struct hpsb_host *host) break; } } - spin_unlock_irqrestore(&hosts_lock, flags); + up(&hpsb_hosts_lock); return retval; } @@ -93,16 +88,14 @@ int hpsb_ref_host(struct hpsb_host *host) void hpsb_unref_host(struct hpsb_host *host) { - unsigned long flags; - module_put(host->driver->owner); - spin_lock_irqsave(&hosts_lock, flags); + down(&hpsb_hosts_lock); host->refcount--; if (!host->refcount && host->is_shutdown) kfree(host); - spin_unlock_irqrestore(&hosts_lock, flags); + up(&hpsb_hosts_lock); } /** @@ -157,11 +150,9 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra) void hpsb_add_host(struct hpsb_host *host) { - unsigned long flags; - - spin_lock_irqsave(&hosts_lock, flags); - list_add_tail(&host->host_list, &hosts); - spin_unlock_irqrestore(&hosts_lock, flags); + down(&hpsb_hosts_lock); + list_add_tail(&host->host_list, &hpsb_hosts); + up(&hpsb_hosts_lock); highlevel_add_host(host); host->driver->devctl(host, RESET_BUS, LONG_RESET); @@ -169,29 +160,11 @@ void hpsb_add_host(struct hpsb_host *host) void hpsb_remove_host(struct hpsb_host *host) { - unsigned long flags; - + down(&hpsb_hosts_lock); host->is_shutdown = 1; host->driver = &dummy_driver; - highlevel_remove_host(host); + list_del(&host->host_list); + up(&hpsb_hosts_lock); - spin_lock_irqsave(&hosts_lock, flags); - list_del(&host->host_list); - spin_unlock_irqrestore(&hosts_lock, flags); -} - -/* - * This function calls the given function for every host currently registered. - */ -void hl_all_hosts(void (*function)(struct hpsb_host*)) -{ - struct list_head *lh; - struct hpsb_host *host; - - spin_lock_irq(&hosts_lock); - list_for_each (lh, &hosts) { - host = list_entry(lh, struct hpsb_host, host_list); - function(host); - } - spin_unlock_irq(&hosts_lock); + highlevel_remove_host(host); } diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 0c39327a52af..51513a393963 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -188,9 +188,9 @@ struct hpsb_host_driver { quadlet_t data, quadlet_t compare); }; -/* high level internal use */ -struct hpsb_highlevel; -void hl_all_hosts(void (*function)(struct hpsb_host*)); + +extern struct list_head hpsb_hosts; +extern struct semaphore hpsb_hosts_lock; /* diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 2c1e53f95b04..a15bec819d0d 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -404,29 +404,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) atomic_inc(&host->generation); host->in_bus_reset = 0; highlevel_host_reset(host); - - /* check for common cycle master error */ - hpsb_check_cycle_master(host); -} - - -void hpsb_check_cycle_master(struct hpsb_host *host) -{ - /* check if host is IRM and not ROOT */ - if (host->is_irm && !host->is_root) { - HPSB_NOTICE("Host is IRM but not root, resetting"); - if (host->reset_retries++ < 4) { - /* selfid stage did not yield valid cycle master */ - hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); - } else { - host->reset_retries = 0; - HPSB_NOTICE("Stopping out-of-control reset loop"); - HPSB_NOTICE("Warning - Cycle Master not set correctly"); - } - return; - } - - host->reset_retries = 0; } @@ -463,6 +440,63 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, } /** + * hpsb_send_phy_config - transmit a PHY configuration packet on the bus + * @host: host that PHY config packet gets sent through + * @rootid: root whose force_root bit should get set (-1 = don't set force_root) + * @gapcnt: gap count value to set (-1 = don't set gap count) + * + * This function sends a PHY config packet on the bus through the specified host. + * + * Return value: 0 for success or error number otherwise. + */ +int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) +{ + struct hpsb_packet *packet; + int retval = 0; + + if(rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || + (rootid == -1 && gapcnt == -1)) { + HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", + rootid, gapcnt); + return -EINVAL; + } + + packet = alloc_hpsb_packet(0); + if (!packet) + return -ENOMEM; + + packet->host = host; + packet->header_size = 16; + packet->data_size = 0; + packet->expect_response = 0; + packet->no_waiter = 0; + packet->type = hpsb_raw; + packet->header[0] = 0; + if(rootid != -1) + packet->header[0] |= rootid << 24 | 1 << 23; + if(gapcnt != -1) + packet->header[0] |= gapcnt << 16 | 1 << 22; + + packet->header[1] = ~packet->header[0]; + + packet->generation = get_hpsb_generation(host); + + HPSB_DEBUG("Sending PHY configuration packet (I hope)..."); + if (!hpsb_send_packet(packet)) { + retval = -EINVAL; + goto fail; + } + + down(&packet->state_change); + down(&packet->state_change); + +fail: + free_hpsb_packet(packet); + + return retval; +} + +/** * hpsb_send_packet - transmit a packet on the bus * @packet: packet to send * @@ -983,9 +1017,6 @@ static struct file_operations ieee1394_chardev_ops = { .open = ieee1394_dispatch_open, }; -devfs_handle_t ieee1394_devfs_handle; - - /* claim a block of minor numbers */ int ieee1394_register_chardev(int blocknum, struct module *module, @@ -1150,11 +1181,11 @@ static int __init ieee1394_init(void) hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), 0, 0, NULL, NULL); - ieee1394_devfs_handle = devfs_mk_dir("ieee1394"); + devfs_mk_dir("ieee1394"); if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) { HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); - devfs_unregister(ieee1394_devfs_handle); + devfs_remove("ieee1394"); return -ENODEV; } @@ -1165,7 +1196,7 @@ static int __init ieee1394_init(void) if (ieee1394_procfs_entry == NULL) { HPSB_ERR("unable to create /proc/bus/ieee1394\n"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); - devfs_unregister(ieee1394_devfs_handle); + devfs_remove("ieee1394"); return -ENOMEM; } ieee1394_procfs_entry->owner = THIS_MODULE; @@ -1190,10 +1221,7 @@ static void __exit ieee1394_cleanup(void) kmem_cache_destroy(hpsb_packet_cache); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); - - /* it's ok to pass a NULL devfs_handle to devfs_unregister */ - devfs_unregister(ieee1394_devfs_handle); - + devfs_remove("ieee1394"); remove_proc_entry("ieee1394", proc_bus); } @@ -1214,17 +1242,16 @@ EXPORT_SYMBOL(hpsb_speedto_str); EXPORT_SYMBOL(hpsb_set_packet_complete_task); EXPORT_SYMBOL(alloc_hpsb_packet); EXPORT_SYMBOL(free_hpsb_packet); +EXPORT_SYMBOL(hpsb_send_phy_config); EXPORT_SYMBOL(hpsb_send_packet); EXPORT_SYMBOL(hpsb_reset_bus); EXPORT_SYMBOL(hpsb_bus_reset); EXPORT_SYMBOL(hpsb_selfid_received); EXPORT_SYMBOL(hpsb_selfid_complete); -EXPORT_SYMBOL(hpsb_check_cycle_master); EXPORT_SYMBOL(hpsb_packet_sent); EXPORT_SYMBOL(hpsb_packet_received); EXPORT_SYMBOL(ieee1394_register_chardev); EXPORT_SYMBOL(ieee1394_unregister_chardev); -EXPORT_SYMBOL(ieee1394_devfs_handle); EXPORT_SYMBOL(ieee1394_procfs_entry); /** ieee1394_transactions.c **/ @@ -1250,6 +1277,13 @@ EXPORT_SYMBOL(hpsb_register_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_unlisten_channel); +EXPORT_SYMBOL(hpsb_get_hostinfo); +EXPORT_SYMBOL(hpsb_create_hostinfo); +EXPORT_SYMBOL(hpsb_destroy_hostinfo); +EXPORT_SYMBOL(hpsb_set_hostinfo_key); +EXPORT_SYMBOL(hpsb_get_hostinfo_key); +EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); +EXPORT_SYMBOL(hpsb_set_hostinfo); EXPORT_SYMBOL(highlevel_read); EXPORT_SYMBOL(highlevel_write); EXPORT_SYMBOL(highlevel_lock); @@ -1302,4 +1336,3 @@ EXPORT_SYMBOL(hpsb_iso_n_ready); EXPORT_SYMBOL(hpsb_iso_packet_sent); EXPORT_SYMBOL(hpsb_iso_packet_received); EXPORT_SYMBOL(hpsb_iso_wake); - diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 37db15faac3e..886491ced8d0 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -109,6 +109,11 @@ static inline unsigned int get_hpsb_generation(struct hpsb_host *host) } /* + * Send a PHY configuration packet. + */ +int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt); + +/* * Queue packet for transmitting, return 0 for failure. */ int hpsb_send_packet(struct hpsb_packet *packet); @@ -140,12 +145,6 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid); */ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot); -/* - * Check bus reset results to find cycle master - */ -void hpsb_check_cycle_master(struct hpsb_host *host); - - /* * Notify core of sending a packet. Ackcode is the ack code returned for async * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE @@ -225,9 +224,6 @@ int ieee1394_register_chardev(int blocknum, /* 0-15 */ /* release a block of minor numbers */ void ieee1394_unregister_chardev(int blocknum); -/* the devfs handle for /dev/ieee1394; NULL if devfs is not in use */ -extern devfs_handle_t ieee1394_devfs_handle; - /* the proc_fs entry for /proc/ieee1394 */ extern struct proc_dir_entry *ieee1394_procfs_entry; diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index de87726d1a63..7bb767ba646a 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -70,8 +70,7 @@ static char *nodemgr_find_oui_name(int oui) static DECLARE_MUTEX(nodemgr_serialize); -static LIST_HEAD(host_info_list); -static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; +static struct hpsb_highlevel *nodemgr_hl; struct host_info { struct hpsb_host *host; @@ -917,7 +916,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent address += 4; infop = (quadlet_t *) ud->quadlets; - for (; length > 0; length--, address += 4, infop++) { + for (; length > 0; length--, address += 4) { int code; quadlet_t value; quadlet_t *quadp; @@ -990,7 +989,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent CSR offsets for now. */ code &= CONFIG_ROM_KEY_TYPE_MASK; if ((code & 0x80) == 0) - *infop = quad; + *infop++ = quad; break; } } @@ -1140,30 +1139,10 @@ static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, static int nodemgr_alloc_host_num(void) { - int hostnum = 0; - unsigned long flags; - struct list_head *lh; - - spin_lock_irqsave (&host_info_lock, flags); - - while (1) { - int found = 0; - - list_for_each(lh, &host_info_list) { - struct host_info *hi = list_entry(lh, struct host_info, list); - if (hi->id == hostnum) { - found = 1; - break; - } - } + int hostnum; - if (!found) - break; - - hostnum++; - } - - spin_unlock_irqrestore (&host_info_lock, flags); + for (hostnum = 0; hpsb_get_hostinfo_bykey(nodemgr_hl, hostnum); hostnum++) + /* Do nothing */; return hostnum; } @@ -1491,7 +1470,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other * nodes of the broadcast channel. (Really we're only setting the validity - * bit). */ + * bit). Other IRM responsibilities go in here as well. */ static void nodemgr_do_irm_duties(struct hpsb_host *host) { quadlet_t bc; @@ -1506,12 +1485,30 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host) hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), &bc, sizeof(quadlet_t)); + + /* If there is no bus manager then we should set the root node's + * force_root bit to promote bus stability per the 1394 + * spec. (8.4.2.6) */ + if(host->busmgr_id == 0x3f && host->node_count > 1) + { + u16 root_node = host->node_count - 1; + struct node_entry *ne = hpsb_nodeid_get_entry(host, root_node); + + if(ne->busopt.cmc) + hpsb_send_phy_config(host, root_node, -1); + else { + HPSB_DEBUG("The root node is not cycle master capable; " + "selecting a new root node and resetting..."); + hpsb_send_phy_config(host, host->node_id, -1); + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + } + } } /* We need to ensure that if we are not the IRM, that the IRM node is capable of * everything we can do, otherwise issue a bus reset and try to become the IRM * ourselves. */ -static int nodemgr_check_root_capability(struct hpsb_host *host) +static int nodemgr_check_irm_capability(struct hpsb_host *host) { quadlet_t bc; int status; @@ -1525,9 +1522,10 @@ static int nodemgr_check_root_capability(struct hpsb_host *host) &bc, sizeof(quadlet_t)); if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { - /* The root node does not have a valid BROADCAST_CHANNEL + /* The current irm node does not have a valid BROADCAST_CHANNEL * register and we do, so reset the bus with force_root set */ - HPSB_DEBUG("Remote root is not IRM capable, resetting..."); + HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting..."); + hpsb_send_phy_config(host, host->node_id, -1); hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); return 0; } @@ -1565,7 +1563,7 @@ static int nodemgr_host_thread(void *__hi) * for the read transactions, so that if another reset occurs * during the scan the transactions will fail instead of * returning bogus data. */ - generation = get_hpsb_generation(hi->host); + generation = get_hpsb_generation(host); /* If we get a reset before we are done waiting, then * start the the waiting over again */ @@ -1573,7 +1571,7 @@ static int nodemgr_host_thread(void *__hi) i = HZ/4; } - if (!nodemgr_check_root_capability(host)) { + if (!nodemgr_check_irm_capability(host)) { /* Do nothing, we are resetting */ up(&nodemgr_serialize); continue; @@ -1683,12 +1681,11 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr, addr, extcode, data, arg); } -static void nodemgr_add_host(struct hpsb_host *host) +static void nodemgr_add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) { struct host_info *hi; - unsigned long flags; - hi = kmalloc(sizeof (struct host_info), in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); + hi = hpsb_create_hostinfo(hl, host, sizeof(*hi)); if (!hi) { HPSB_ERR ("NodeMgr: out of memory in add host"); @@ -1698,14 +1695,14 @@ static void nodemgr_add_host(struct hpsb_host *host) /* Initialize the hostinfo here and start the thread. The * thread blocks on the reset semaphore until a bus reset * happens. */ - memset(hi, 0, sizeof(*hi)); hi->host = host; - INIT_LIST_HEAD(&hi->list); init_completion(&hi->exited); sema_init(&hi->reset_sem, 0); hi->id = nodemgr_alloc_host_num(); + hpsb_set_hostinfo_key(hl, host, hi->id); + memcpy(&host->device, &nodemgr_dev_template_host, sizeof(host->device)); host->device.parent = &host->pdev->dev; @@ -1715,40 +1712,22 @@ static void nodemgr_add_host(struct hpsb_host *host) sprintf(hi->daemon_name, "knodemgrd_%d", hi->id); - spin_lock_irqsave (&host_info_lock, flags); - hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - + if (hi->pid < 0) { HPSB_ERR ("NodeMgr: failed to start %s thread for %s", hi->daemon_name, host->driver->name); - kfree(hi); - spin_unlock_irqrestore (&host_info_lock, flags); + hpsb_destroy_hostinfo(hl, host); return; } - list_add_tail (&hi->list, &host_info_list); - - spin_unlock_irqrestore (&host_info_lock, flags); - return; } static void nodemgr_host_reset(struct hpsb_host *host) { - struct list_head *lh; - struct host_info *hi = NULL; - unsigned long flags; - - spin_lock_irqsave (&host_info_lock, flags); - list_for_each(lh, &host_info_list) { - struct host_info *myhi = list_entry(lh, struct host_info, list); - if (myhi->host == host) { - hi = myhi; - break; - } - } + struct host_info *hi = hpsb_get_hostinfo(nodemgr_hl, host); if (hi != NULL) { #ifdef CONFIG_IEEE1394_VERBOSEDEBUG @@ -1756,29 +1735,14 @@ static void nodemgr_host_reset(struct hpsb_host *host) #endif up(&hi->reset_sem); } else - HPSB_ERR ("NodeMgr: could not process reset of non-existent host"); - - spin_unlock_irqrestore (&host_info_lock, flags); + HPSB_ERR ("NodeMgr: could not process reset of unused host"); return; } static void nodemgr_remove_host(struct hpsb_host *host) { - struct list_head *lh, *next; - unsigned long flags; - struct host_info *hi = NULL; - - spin_lock_irqsave (&host_info_lock, flags); - list_for_each_safe(lh, next, &host_info_list) { - struct host_info *myhi = list_entry(lh, struct host_info, list); - if (myhi->host == host) { - list_del(&myhi->list); - hi = myhi; - break; - } - } - spin_unlock_irqrestore (&host_info_lock, flags); + struct host_info *hi = hpsb_get_hostinfo(nodemgr_hl, host); if (hi) { if (hi->pid >= 0) { @@ -1787,7 +1751,6 @@ static void nodemgr_remove_host(struct hpsb_host *host) nodemgr_remove_host_dev(&host->device); device_unregister(&host->device); } - kfree(hi); } else HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", host->driver->name); @@ -1801,21 +1764,19 @@ static struct hpsb_highlevel_ops nodemgr_ops = { .remove_host = nodemgr_remove_host, }; -static struct hpsb_highlevel *hl; - void init_ieee1394_nodemgr(void) { bus_register(&ieee1394_bus_type); - hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); - if (!hl) { + nodemgr_hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); + if (!nodemgr_hl) { HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); } } void cleanup_ieee1394_nodemgr(void) { - hpsb_unregister_highlevel(hl); + hpsb_unregister_highlevel(nodemgr_hl); bus_unregister(&ieee1394_bus_type); } diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index c007efd9a2cb..b89295525391 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -165,7 +165,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 858 $ Ben Collins <bcollins@debian.org>"; + "$Rev: 866 $ Ben Collins <bcollins@debian.org>"; /* Module Parameters */ static int phys_dma = 1; diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index facb0ed0dd14..1c690ce7a99b 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -72,8 +72,6 @@ printk(KERN_INFO "raw1394:" fmt "\n" , ## args) #define DBGMSG(fmt, args...) #endif -static devfs_handle_t devfs_handle; - static LIST_HEAD(host_info_list); static int host_count; static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; @@ -190,13 +188,13 @@ static void queue_complete_cb(struct pending_request *req) } -static void add_host(struct hpsb_host *host) +static void add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) { struct host_info *hi; unsigned long flags; - hi = (struct host_info *)kmalloc(sizeof(struct host_info), - in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); + hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL); + if (hi != NULL) { INIT_LIST_HEAD(&hi->list); hi->host = host; @@ -2536,17 +2534,14 @@ static int __init init_raw1394(void) return -ENOMEM; } - devfs_handle = devfs_register(NULL, - RAW1394_DEVICE_NAME, DEVFS_FL_NONE, - IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_RAW1394 * 16, - S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, - NULL); + devfs_register(NULL, RAW1394_DEVICE_NAME, 0, + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16, + S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL); if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, THIS_MODULE, &file_ops)) { HPSB_ERR("raw1394 failed to register minor device block"); - devfs_unregister(devfs_handle); + devfs_remove(RAW1394_DEVICE_NAME); hpsb_unregister_highlevel(hl_handle); return -EBUSY; } @@ -2562,7 +2557,7 @@ static void __exit cleanup_raw1394(void) { hpsb_unregister_protocol(&raw1394_driver); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394); - devfs_unregister(devfs_handle); + devfs_remove(RAW1394_DEVICE_NAME); hpsb_unregister_highlevel(hl_handle); } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f80b2194922e..230638ed5ed9 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -298,7 +298,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 846 $ James Goodwin <jamesg@filanet.com>"; + "$Rev: 884 $ James Goodwin <jamesg@filanet.com>"; /* * Module load parameter definitions @@ -456,10 +456,6 @@ static Scsi_Host_Template scsi_driver_template; static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 }; -static LIST_HEAD(sbp2_host_info_list); - -static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED; - static struct hpsb_highlevel *sbp2_hl_handle = NULL; static struct hpsb_highlevel_ops sbp2_hl_ops = { @@ -779,10 +775,9 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( static void sbp2util_free_command_dma(struct sbp2_command_info *command) { struct sbp2scsi_host_info *hi; - - hi = (struct sbp2scsi_host_info *)&command->Current_SCpnt->device->host->hostdata; - if (hi == NULL) { + hi = hpsb_get_hostinfo_bykey(sbp2_hl_handle, (unsigned long)command->Current_SCpnt->device->host); + if (!hi) { printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__); return; } @@ -911,87 +906,47 @@ static void sbp2_update(struct unit_directory *ud) static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; - unsigned long flags; struct Scsi_Host *scsi_host; SBP2_DEBUG("sbp2_add_host"); - hi = sbp2_find_host_info(host); + hi = hpsb_get_hostinfo(sbp2_hl_handle, host); if (hi) return hi; /* Register our host with the SCSI stack. */ - scsi_host = scsi_register (&scsi_driver_template, sizeof(struct sbp2scsi_host_info)); + scsi_host = scsi_register (&scsi_driver_template, 0); if (!scsi_host) { SBP2_ERR("failed to register scsi host"); return NULL; } - hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata; - memset(hi, 0, sizeof(struct sbp2scsi_host_info)); + hi = hpsb_create_hostinfo(sbp2_hl_handle, host, sizeof(*hi)); + if (!hi) { + SBP2_ERR("failed to allocate hostinfo"); + scsi_unregister(hi->scsi_host); + } + + hpsb_set_hostinfo_key(sbp2_hl_handle, host, (unsigned long)scsi_host); hi->scsi_host = scsi_host; - INIT_LIST_HEAD(&hi->list); hi->host = host; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; - spin_lock_irqsave(&sbp2_host_info_lock, flags); - list_add_tail(&hi->list, &sbp2_host_info_list); - spin_unlock_irqrestore(&sbp2_host_info_lock, flags); - /* XXX We need a device to pass here as the scsi-host class. Can't * use the PCI device, since it is already bound to the ieee1394 * host. Can't use the fw-host device since it is multi-class * enabled (scsi-host uses classdata member of the device). */ if (scsi_add_host(hi->scsi_host, NULL)) { SBP2_ERR("failed to add scsi host"); - - spin_lock_irqsave(&sbp2_host_info_lock, flags); - list_del(&hi->list); - spin_unlock_irqrestore(&sbp2_host_info_lock, flags); - scsi_unregister(hi->scsi_host); + hpsb_destroy_hostinfo(sbp2_hl_handle, host); } return hi; } -/* - * This fuction returns a host info structure from the host structure, in - * case we have multiple hosts. - */ -static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host) -{ - struct list_head *lh; - struct sbp2scsi_host_info *hi; - - list_for_each (lh, &sbp2_host_info_list) { - hi = list_entry(lh, struct sbp2scsi_host_info, list); - if (hi->host == host) - return hi; - } - - return NULL; -} - -/* - * This function returns a host info structure for a given Scsi_Host - * struct. - */ -static struct sbp2scsi_host_info *sbp2_find_host_info_scsi(struct Scsi_Host *host) -{ - struct list_head *lh; - struct sbp2scsi_host_info *hi; - - list_for_each (lh, &sbp2_host_info_list) { - hi = list_entry(lh, struct sbp2scsi_host_info, list); - if (hi->scsi_host == host) - return hi; - } - - return NULL; -} /* * This function is called when a host is removed. @@ -999,20 +954,16 @@ static struct sbp2scsi_host_info *sbp2_find_host_info_scsi(struct Scsi_Host *hos static void sbp2_remove_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; - unsigned long flags; SBP2_DEBUG("sbp2_remove_host"); - spin_lock_irqsave(&sbp2_host_info_lock, flags); - hi = sbp2_find_host_info(host); - if (hi) - list_del(&hi->list); - spin_unlock_irqrestore(&sbp2_host_info_lock, flags); + hi = hpsb_get_hostinfo(sbp2_hl_handle, host); if (hi) { scsi_remove_host(hi->scsi_host); scsi_unregister(hi->scsi_host); - } + } else + SBP2_ERR("attempt to remove unknown host %p", host); } /* @@ -2614,9 +2565,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest return(RCODE_ADDRESS_ERROR); } - spin_lock_irqsave(&sbp2_host_info_lock, flags); - hi = sbp2_find_host_info(host); - spin_unlock_irqrestore(&sbp2_host_info_lock, flags); + hi = hpsb_get_hostinfo(sbp2_hl_handle, host); if (!hi) { SBP2_ERR("host info is NULL - this is bad!"); @@ -2763,7 +2712,7 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) /* * Pull our host info and scsi id instance data from the scsi command */ - hi = (struct sbp2scsi_host_info *) &SCpnt->device->host->hostdata; + hi = hpsb_get_hostinfo_bykey(sbp2_hl_handle, (unsigned long)SCpnt->device->host); if (!hi) { SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); @@ -2992,7 +2941,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, */ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata; + struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(sbp2_hl_handle, + (unsigned long)SCpnt->device->host); struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; struct sbp2_command_info *command; unsigned long flags; @@ -3042,7 +2992,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) */ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata; + struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(sbp2_hl_handle, + (unsigned long)SCpnt->device->host); struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; SBP2_ERR("reset requested"); @@ -3080,7 +3031,7 @@ static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset, if (!host) /* if we couldn't find it, we return an error */ return -ESRCH; - hi = sbp2_find_host_info_scsi(host); + hi = hpsb_get_hostinfo_bykey(sbp2_hl_handle, (unsigned long)host); if (!hi) /* shouldn't happen, but... */ return -ESRCH; diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index a642dcf3c17d..b1e33863cbd9 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -417,11 +417,6 @@ struct scsi_id_instance_data { * Sbp2 host data structure (one per sbp2 host) */ struct sbp2scsi_host_info { - - /* - * For use in keeping track of hosts - */ - struct list_head list; struct hpsb_host *host; /* @@ -463,7 +458,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i * IEEE-1394 core driver related prototypes */ static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); -static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host); static void sbp2_remove_host(struct hpsb_host *host); static int sbp2_probe(struct device *dev); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 50988d1d7ff8..c74e4a5d7f61 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -122,16 +122,9 @@ struct dma_iso_ctx { struct list_head link; }; -struct video_card { - struct ti_ohci *ohci; - struct list_head list; - int id; - devfs_handle_t devfs; -}; - struct file_ctx { - struct video_card *video; + struct ti_ohci *ohci; struct list_head context_list; struct dma_iso_ctx *current_ctx; }; @@ -162,10 +155,6 @@ printk(level "video1394_%d: " fmt "\n" , card , ## args) void wakeup_dma_ir_ctx(unsigned long l); void wakeup_dma_it_ctx(unsigned long l); -static LIST_HEAD(video1394_cards); -static spinlock_t video1394_cards_lock = SPIN_LOCK_UNLOCKED; - -static devfs_handle_t devfs_handle; static struct hpsb_highlevel *hl_handle = NULL; @@ -716,8 +705,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct file_ctx *ctx = (struct file_ctx *)file->private_data; - struct video_card *video = ctx->video; - struct ti_ohci *ohci = video->ohci; + struct ti_ohci *ohci = ctx->ohci; unsigned long flags; switch(cmd) @@ -1162,7 +1150,7 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma) lock_kernel(); if (ctx->current_ctx == NULL) { - PRINT(KERN_ERR, ctx->video->ohci->id, "Current iso context not set"); + PRINT(KERN_ERR, ctx->ohci->id, "Current iso context not set"); } else res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); unlock_kernel(); @@ -1173,32 +1161,21 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma) static int video1394_open(struct inode *inode, struct file *file) { int i = ieee1394_file_to_instance(file); - unsigned long flags; - struct video_card *video = NULL; - struct list_head *lh; + struct ti_ohci *ohci; struct file_ctx *ctx; - spin_lock_irqsave(&video1394_cards_lock, flags); - list_for_each(lh, &video1394_cards) { - struct video_card *p = list_entry(lh, struct video_card, list); - if (p->id == i) { - video = p; - break; - } - } - spin_unlock_irqrestore(&video1394_cards_lock, flags); - - if (video == NULL) + ohci = hpsb_get_hostinfo_bykey(hl_handle, i); + if (ohci == NULL) return -EIO; ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL); if (ctx == NULL) { - PRINT(KERN_ERR, video->ohci->id, "Cannot malloc file_ctx"); + PRINT(KERN_ERR, ohci->id, "Cannot malloc file_ctx"); return -ENOMEM; } memset(ctx, 0, sizeof(struct file_ctx)); - ctx->video = video; + ctx->ohci = ohci; INIT_LIST_HEAD(&ctx->context_list); ctx->current_ctx = NULL; file->private_data = ctx; @@ -1209,8 +1186,7 @@ static int video1394_open(struct inode *inode, struct file *file) static int video1394_release(struct inode *inode, struct file *file) { struct file_ctx *ctx = (struct file_ctx *)file->private_data; - struct video_card *video = ctx->video; - struct ti_ohci *ohci = video->ohci; + struct ti_ohci *ohci = ctx->ohci; struct list_head *lh, *next; u64 mask; @@ -1273,54 +1249,11 @@ static struct hpsb_protocol_driver video1394_driver = { }; -static int video1394_init(struct ti_ohci *ohci) -{ - struct video_card *video; - unsigned long flags; - char name[24]; - int minor; - - video = kmalloc(sizeof(struct video_card), GFP_KERNEL); - if (video == NULL) { - PRINT(KERN_ERR, ohci->id, "Cannot allocate video_card"); - return -1; - } - - memset(video, 0, sizeof(struct video_card)); - - spin_lock_irqsave(&video1394_cards_lock, flags); - INIT_LIST_HEAD(&video->list); - list_add_tail(&video->list, &video1394_cards); - spin_unlock_irqrestore(&video1394_cards_lock, flags); - - video->id = ohci->id; - video->ohci = ohci; - - sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, video->id); - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + video->id; - video->devfs = devfs_register(NULL, name, DEVFS_FL_DEFAULT, - IEEE1394_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, - &video1394_fops, NULL); - - return 0; -} - -/* Must be called under spinlock */ -static void remove_card(struct video_card *video) -{ - devfs_unregister(video->devfs); - list_del(&video->list); - - kfree(video); -} - -static void video1394_remove_host (struct hpsb_host *host) +static void video1394_add_host (struct hpsb_host *host, struct hpsb_highlevel *hl) { struct ti_ohci *ohci; - unsigned long flags; - struct list_head *lh, *next; - struct video_card *p; + char name[16]; + int minor; /* We only work with the OHCI-1394 driver */ if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) @@ -1328,34 +1261,34 @@ static void video1394_remove_host (struct hpsb_host *host) ohci = (struct ti_ohci *)host->hostdata; - spin_lock_irqsave(&video1394_cards_lock, flags); - list_for_each_safe(lh, next, &video1394_cards) { - p = list_entry(lh, struct video_card, list); - if (p->ohci == ohci) { - remove_card(p); - break; - } + if (!hpsb_create_hostinfo(hl, host, 0)) { + PRINT(KERN_ERR, ohci->id, "Cannot allocate hostinfo"); + return; } - spin_unlock_irqrestore(&video1394_cards_lock, flags); + + hpsb_set_hostinfo(hl, host, ohci); + hpsb_set_hostinfo_key(hl, host, ohci->id); + + sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); + minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; + devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, + S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL); return; } -static void video1394_add_host (struct hpsb_host *host) -{ - struct ti_ohci *ohci; - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; +static void video1394_remove_host (struct hpsb_host *host) +{ + struct ti_ohci *ohci = hpsb_get_hostinfo(hl_handle, host); - ohci = (struct ti_ohci *)host->hostdata; + if (ohci) + devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); - video1394_init(ohci); - return; } + static struct hpsb_highlevel_ops hl_ops = { .add_host = video1394_add_host, .remove_host = video1394_remove_host, @@ -1497,7 +1430,7 @@ static void __exit video1394_exit_module (void) hpsb_unregister_highlevel (hl_handle); - devfs_unregister(devfs_handle); + devfs_remove(VIDEO1394_DRIVER_NAME); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); @@ -1514,12 +1447,12 @@ static int __init video1394_init_module (void) return -EIO; } - devfs_handle = devfs_mk_dir(VIDEO1394_DRIVER_NAME); + devfs_mk_dir(VIDEO1394_DRIVER_NAME); hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops); if (hl_handle == NULL) { PRINT_G(KERN_ERR, "No more memory for driver\n"); - devfs_unregister(devfs_handle); + devfs_remove(VIDEO1394_DRIVER_NAME); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); return -ENOMEM; } |
