]> git.hungrycats.org Git - linux/commitdiff
[PATCH] IEEE-1394/Firewire updates
authorBen Collins <bcollins@debian.org>
Sat, 19 Apr 2003 12:34:28 +0000 (05:34 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 19 Apr 2003 12:34:28 +0000 (05:34 -0700)
- Cleaned up hostinfo usage in all drivers and created a central API to
  handle them all.
- Fixup some spinlock mis-usage.
- Remove devfs_handle mis-usage.
- Cleaned up some heavy handed spinlocking to use mutexes instead.
- Add function to send PHY config packets and use to to settle
  IRM/cycle-master/root descrepancies.

19 files changed:
drivers/ieee1394/amdtp.c
drivers/ieee1394/cmp.c
drivers/ieee1394/csr.c
drivers/ieee1394/dv1394-private.h
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/eth1394.h
drivers/ieee1394/highlevel.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c

index 6e7b20f898c309d163b42de9f4e75de6248c8b7f..e2e995f3d405a2894909b2aafc18b8cca1b26b3e 100644 (file)
@@ -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");
index ba7f58475c7452ae0d61a97fd05a26f87b34b871..9f21025b0d1cda51f3322be1fef8cecc2efdd347 100644 (file)
@@ -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,
 };
 
index e13186e64115f5dc5bcedd96e10617a9fa8ff09f..75492616e6826b42037d1318be50279f6181f8a6 100644 (file)
@@ -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); 
 
index 9fe654b0ffb9c36847fef4cf71fd4e8efac3ccb5..14b970fef601b2f8148f4a9a2d5bbc4bf8e59d72 100644 (file)
@@ -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;
index 03a9a5d1546fd6c31287212bce741029bcd2c5b6..e06c50e7cc8188a84ceb0b5a5af21f826c11f82a 100644 (file)
@@ -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];
index 5b0b99628c1dab5e66f67d318bc12ffd0de9baeb..f9e1584d90104c755797534916a0d78d489209cb 100644 (file)
@@ -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);
 }
index 1c38fb02cdfe82a0fcbe40e48cccbb267dca1153..40fa50d026167e8fef01f8e6a553564e8429d19f 100644 (file)
@@ -56,7 +56,6 @@ struct eth1394_priv {
 };
 
 struct host_info {
-       struct list_head list;
        struct hpsb_host *host;
        struct net_device *dev;
 };
index 843675b655e68034b80fc5d9f98a56af91300c2a..6ea4467042179d8e3c52e6f4f4342c66480e15dc 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/list.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #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);
 }
index d6a90ddf24251b1563788e84684a404ab880bdb1..420c404f7b0535f9cb0097c11640926d6b53b12d 100644 (file)
@@ -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 */
index 1726629944bce541220fa96a21f5f2c3aba02fa0..54e4069df3d302ee143e85b2c51b2c48c6c1e6ba 100644 (file)
 #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);
 }
index 0c39327a52afe5186ba0ca0c397d25cb30bd1745..51513a3939631223492e1c9b3b7b7ad3e98c713f 100644 (file)
@@ -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;
 
 
 /*
index 2c1e53f95b0410b76a103d38bdae5d8e198d078d..a15bec819d0d4ee6bdd953455c776631630876d4 100644 (file)
@@ -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;
 }
 
 
@@ -462,6 +439,63 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
         hpsb_schedule_work(&host->timeout_tq);
 }
 
+/**
+ * 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);
-
index 37db15faac3ea43f31fb6a4d4a98ae1cea79375d..886491ced8d06236bdcc4778fd2ad66ceb4a0456 100644 (file)
@@ -108,6 +108,11 @@ static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
         return atomic_read(&host->generation);
 }
 
+/*
+ * 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.
  */
@@ -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;
 
index de87726d1a639642ce0ebb5c6d5b92d9c8f63696..7bb767ba646a55c4a29230e9f74063ea9abad5aa 100644 (file)
@@ -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);
 }
index c007efd9a2cba8432796d83e2e1696d79b9d7cce..b892955253913634b0887371cfa13f7e26d292b7 100644 (file)
@@ -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;
index facb0ed0dd146264bd12cdaba46460fdb885b7c3..1c690ce7a99b010b031cf4e98b8991240f443c3c 100644 (file)
@@ -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);
 }
 
index f80b2194922e1cd103039f84688a1751e943db85..230638ed5ed9568d4301397248297154bdf61a95 100644 (file)
 #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;
 
index a642dcf3c17dfadb4d5a7a9d86d8608fddcab107..b1e33863cbd96a9cd58ff2ecb66b4ee0062f18e4 100644 (file)
@@ -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);
index 50988d1d7ff89e7f6bfc6d9ca2b291639b7d2442..c74e4a5d7f61a9cc8ec5db38a8cc3093d2881f13 100644 (file)
@@ -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;
        }