Commit ffb74927 authored by Ben Collins's avatar Ben Collins Committed by Linus Torvalds

[PATCH] IEEE-1394/Firewire updates

- 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.
parent 77ad1af8
...@@ -266,12 +266,10 @@ struct amdtp_host { ...@@ -266,12 +266,10 @@ struct amdtp_host {
struct ti_ohci *ohci; struct ti_ohci *ohci;
struct list_head stream_list; struct list_head stream_list;
spinlock_t stream_list_lock; spinlock_t stream_list_lock;
struct list_head link;
}; };
static struct hpsb_highlevel *amdtp_highlevel; 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... */ /* FIXME: This doesn't belong here... */
...@@ -347,7 +345,7 @@ static void stream_start_dma(struct stream *s, struct packet_list *pl) ...@@ -347,7 +345,7 @@ static void stream_start_dma(struct stream *s, struct packet_list *pl)
{ {
u32 syt_cycle, cycle_count, start_cycle; 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; OHCI1394_IsochronousCycleTimer) >> 12;
syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f; 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) ...@@ -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) static int amdtp_open(struct inode *inode, struct file *file)
{ {
struct amdtp_host *host; struct amdtp_host *host;
int i = ieee1394_file_to_instance(file);
/* FIXME: We just grab the first registered host */ host = hpsb_get_hostinfo_bykey(amdtp_highlevel, i);
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);
if (host == NULL) if (host == NULL)
return -ENODEV; return -ENODEV;
...@@ -1209,44 +1201,45 @@ static struct file_operations amdtp_fops = ...@@ -1209,44 +1201,45 @@ static struct file_operations amdtp_fops =
/* IEEE1394 Subsystem functions */ /* 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; struct amdtp_host *ah;
int minor;
char name[16];
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0)
return; 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->host = host;
ah->ohci = host->hostdata; 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); INIT_LIST_HEAD(&ah->stream_list);
spin_lock_init(&ah->stream_list_lock); spin_lock_init(&ah->stream_list_lock);
spin_lock_irq(&host_list_lock); devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor,
list_add_tail(&ah->link, &host_list); S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL);
spin_unlock_irq(&host_list_lock);
} }
static void amdtp_remove_host(struct hpsb_host *host) static void amdtp_remove_host(struct hpsb_host *host)
{ {
struct list_head *lh; struct amdtp_host *ah = hpsb_get_hostinfo(amdtp_highlevel, host);
struct amdtp_host *ah;
spin_lock_irq(&host_list_lock); if (ah)
list_for_each(lh, &host_list) { devfs_remove("amdtp/%d", ah->ohci->id);
if (list_entry(lh, struct amdtp_host, link)->host == host) {
list_del(lh); return;
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);
} }
static struct hpsb_highlevel_ops amdtp_highlevel_ops = { static struct hpsb_highlevel_ops amdtp_highlevel_ops = {
...@@ -1273,10 +1266,13 @@ static int __init amdtp_init_module (void) ...@@ -1273,10 +1266,13 @@ static int __init amdtp_init_module (void)
return -EIO; return -EIO;
} }
devfs_mk_dir("amdtp");
amdtp_highlevel = hpsb_register_highlevel ("amdtp", amdtp_highlevel = hpsb_register_highlevel ("amdtp",
&amdtp_highlevel_ops); &amdtp_highlevel_ops);
if (amdtp_highlevel == NULL) { if (amdtp_highlevel == NULL) {
HPSB_ERR("amdtp: unable to register highlevel ops"); HPSB_ERR("amdtp: unable to register highlevel ops");
devfs_remove("amdtp");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
return -EIO; return -EIO;
} }
...@@ -1309,6 +1305,7 @@ static void __exit amdtp_exit_module (void) ...@@ -1309,6 +1305,7 @@ static void __exit amdtp_exit_module (void)
#endif #endif
hpsb_unregister_highlevel(amdtp_highlevel); hpsb_unregister_highlevel(amdtp_highlevel);
devfs_remove("amdtp");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
HPSB_INFO("Unloaded AMDTP driver"); HPSB_INFO("Unloaded AMDTP driver");
......
...@@ -65,8 +65,6 @@ struct cmp_host { ...@@ -65,8 +65,6 @@ struct cmp_host {
quadlet_t impr_quadlet; quadlet_t impr_quadlet;
} v; } v;
struct plug ipcr[2]; struct plug ipcr[2];
struct list_head link;
}; };
enum { enum {
...@@ -79,31 +77,6 @@ enum { ...@@ -79,31 +77,6 @@ enum {
static struct hpsb_highlevel *cmp_highlevel; 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 * struct cmp_pcr *
cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
void (*update)(struct cmp_pcr *pcr, void *data), void (*update)(struct cmp_pcr *pcr, void *data),
...@@ -112,7 +85,7 @@ cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, ...@@ -112,7 +85,7 @@ cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
struct cmp_host *ch; struct cmp_host *ch;
struct plug *plug; struct plug *plug;
ch = lookup_cmp_host(host); ch = hpsb_get_hostinfo(cmp_highlevel, host);
if (opcr_number >= ch->u.ompr.nplugs || if (opcr_number >= ch->u.ompr.nplugs ||
ch->opcr[opcr_number].update != NULL) ch->opcr[opcr_number].update != NULL)
...@@ -135,7 +108,7 @@ void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr) ...@@ -135,7 +108,7 @@ void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr)
struct cmp_host *ch; struct cmp_host *ch;
struct plug *plug; struct plug *plug;
ch = lookup_cmp_host(host); ch = hpsb_get_hostinfo(cmp_highlevel, host);
plug = (struct plug *)opcr; plug = (struct plug *)opcr;
if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG(); if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();
...@@ -155,48 +128,34 @@ static void reset_plugs(struct cmp_host *ch) ...@@ -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) { if (ch == NULL) {
HPSB_ERR("Failed to allocate cmp_host"); HPSB_ERR("Failed to allocate cmp_host");
return; return;
} }
memset(ch, 0, sizeof *ch);
ch->host = host; ch->host = host;
ch->u.ompr.rate = SPEED_100; ch->u.ompr.rate = SPEED_100;
ch->u.ompr.bcast_channel_base = 63; ch->u.ompr.bcast_channel_base = 63;
ch->u.ompr.nplugs = 2; 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); 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; struct cmp_host *ch;
ch = lookup_cmp_host(host); ch = hpsb_get_hostinfo(cmp_highlevel, host);
if (ch == NULL) BUG(); if (ch == NULL) {
HPSB_ERR("cmp: Tried to reset unknown host");
spin_lock_irq(&host_list_lock); return;
list_del(&ch->link); }
spin_unlock_irq(&host_list_lock);
kfree(ch); reset_plugs(ch);
} }
static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, 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, ...@@ -209,7 +168,7 @@ static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
if (length != 4) if (length != 4)
return RCODE_TYPE_ERROR; return RCODE_TYPE_ERROR;
ch = lookup_cmp_host(host); ch = hpsb_get_hostinfo(cmp_highlevel, host);
if (csraddr == 0x900) { if (csraddr == 0x900) {
*buf = cpu_to_be32(ch->u.ompr_quadlet); *buf = cpu_to_be32(ch->u.ompr_quadlet);
return RCODE_COMPLETE; return RCODE_COMPLETE;
...@@ -242,7 +201,7 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -242,7 +201,7 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int plug; int plug;
struct cmp_host *ch; struct cmp_host *ch;
ch = lookup_cmp_host(host); ch = hpsb_get_hostinfo(cmp_highlevel, host);
if (extcode != EXTCODE_COMPARE_SWAP) if (extcode != EXTCODE_COMPARE_SWAP)
return RCODE_TYPE_ERROR; return RCODE_TYPE_ERROR;
...@@ -301,7 +260,6 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -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 = { static struct hpsb_highlevel_ops cmp_highlevel_ops = {
.add_host = cmp_add_host, .add_host = cmp_add_host,
.remove_host = cmp_remove_host,
.host_reset = cmp_host_reset, .host_reset = cmp_host_reset,
}; };
......
...@@ -90,7 +90,7 @@ static void host_reset(struct hpsb_host *host) ...@@ -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; host->csr.lock = SPIN_LOCK_UNLOCKED;
...@@ -118,7 +118,9 @@ static void add_host(struct hpsb_host *host) ...@@ -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, int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
size_t size, unsigned char rom_version) size_t size, unsigned char rom_version)
{ {
int ret,flags; unsigned long flags;
int ret;
spin_lock_irqsave(&host->csr.lock, flags); spin_lock_irqsave(&host->csr.lock, flags);
if (rom_version != host->csr.rom_version) if (rom_version != host->csr.rom_version)
ret = -1; ret = -1;
...@@ -137,7 +139,9 @@ int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, ...@@ -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, int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
size_t buffersize, size_t *rom_size, unsigned char *rom_version) 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); spin_lock_irqsave(&host->csr.lock, flags);
*rom_version=host->csr.rom_version; *rom_version=host->csr.rom_version;
*rom_size=host->csr.rom_size; *rom_size=host->csr.rom_size;
...@@ -156,9 +160,9 @@ int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, ...@@ -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, static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, unsigned int length, u16 fl) u64 addr, unsigned int length, u16 fl)
{ {
unsigned long flags;
int csraddr = addr - CSR_REGISTER_BASE; int csraddr = addr - CSR_REGISTER_BASE;
const char *src; const char *src;
int flags;
spin_lock_irqsave(&host->csr.lock, flags); spin_lock_irqsave(&host->csr.lock, flags);
......
...@@ -403,9 +403,6 @@ struct video_card { ...@@ -403,9 +403,6 @@ struct video_card {
/* entry in dv1394_cards */ /* entry in dv1394_cards */
struct list_head list; 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 */ /* OHCI card IT DMA context number, -1 if not in use */
int ohci_it_ctx; int ohci_it_ctx;
struct ohci1394_iso_tasklet it_tasklet; struct ohci1394_iso_tasklet it_tasklet;
......
...@@ -2458,14 +2458,9 @@ static int dv1394_devfs_add_entry(struct video_card *video) ...@@ -2458,14 +2458,9 @@ static int dv1394_devfs_add_entry(struct video_card *video)
(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
(video->mode == MODE_RECEIVE ? "in" : "out")); (video->mode == MODE_RECEIVE ? "in" : "out"));
video->devfs_handle = devfs_register(NULL, buf, 0, IEEE1394_MAJOR, devfs_register(NULL, buf, 0, IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video);
&dv1394_fops, video);
if (video->devfs_handle == NULL) {
printk(KERN_ERR "dv1394: unable to create /dev/%s\n", buf);
return -ENOMEM;
}
return 0; return 0;
} }
#endif /* CONFIG_DEVFS_FS */ #endif /* CONFIG_DEVFS_FS */
...@@ -2650,7 +2645,7 @@ static void dv1394_remove_host (struct hpsb_host *host) ...@@ -2650,7 +2645,7 @@ static void dv1394_remove_host (struct hpsb_host *host)
#endif #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; struct ti_ohci *ohci;
char buf[16]; char buf[16];
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
printk(KERN_ERR fmt, ## args) printk(KERN_ERR fmt, ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 806 $ Ben Collins <bcollins@debian.org>"; "$Rev: 886 $ Ben Collins <bcollins@debian.org>";
/* Our ieee1394 highlevel driver */ /* Our ieee1394 highlevel driver */
#define ETHER1394_DRIVER_NAME "ether1394" #define ETHER1394_DRIVER_NAME "ether1394"
...@@ -86,9 +86,6 @@ static char version[] __devinitdata = ...@@ -86,9 +86,6 @@ static char version[] __devinitdata =
static kmem_cache_t *packet_task_cache; static kmem_cache_t *packet_task_cache;
static struct hpsb_highlevel *hl_handle = NULL; 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 */ /* Use common.lf to determine header len */
static int hdr_type_len[] = { static int hdr_type_len[] = {
...@@ -105,40 +102,6 @@ MODULE_LICENSE("GPL"); ...@@ -105,40 +102,6 @@ MODULE_LICENSE("GPL");
static void ether1394_iso(struct hpsb_iso *iso); 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" */ /* This is called after an "ifup" */
static int ether1394_open (struct net_device *dev) static int ether1394_open (struct net_device *dev)
{ {
...@@ -355,7 +318,7 @@ static int ether1394_init_dev (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 * when the module is installed. This is where we add all of our ethernet
* devices. One for each host. * 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 host_info *hi = NULL;
struct net_device *dev = NULL; struct net_device *dev = NULL;
...@@ -378,30 +341,22 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -378,30 +341,22 @@ static void ether1394_add_host (struct hpsb_host *host)
priv->host = host; priv->host = host;
hi = (struct host_info *)kmalloc (sizeof (struct host_info), hi = hpsb_create_hostinfo(hl, host, sizeof(*hi));
in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
if (hi == NULL) if (hi == NULL)
goto out; goto out;
if (register_netdev (dev)) { if (register_netdev (dev)) {
ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");
kfree (dev); goto out;
kfree (hi);
return;
} }
ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n", ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n",
host->driver->name); host->driver->name);
INIT_LIST_HEAD (&hi->list);
hi->host = host; hi->host = host;
hi->dev = dev; 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 /* Ignore validity in hopes that it will be set in the future. It'll
* check it on transmit. */ * check it on transmit. */
priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
...@@ -416,6 +371,9 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -416,6 +371,9 @@ static void ether1394_add_host (struct hpsb_host *host)
out: out:
if (dev != NULL) if (dev != NULL)
kfree (dev); kfree (dev);
if (hi)
hpsb_destroy_hostinfo(hl, host);
ETH1394_PRINT_G (KERN_ERR, "Out of memory\n"); ETH1394_PRINT_G (KERN_ERR, "Out of memory\n");
return; return;
...@@ -424,20 +382,17 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -424,20 +382,17 @@ static void ether1394_add_host (struct hpsb_host *host)
/* Remove a card from our list */ /* Remove a card from our list */
static void ether1394_remove_host (struct hpsb_host *host) static void ether1394_remove_host (struct hpsb_host *host)
{ {
struct eth1394_priv *priv; struct host_info *hi = hpsb_get_hostinfo(hl_handle, host);
struct host_info *hi;
spin_lock_irq (&host_info_lock);
hi = find_host_info (host);
if (hi != NULL) { 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; priv->bc_state = ETHER1394_BC_CLOSED;
unregister_netdev (hi->dev); unregister_netdev (hi->dev);
hpsb_iso_shutdown(priv->iso);
kfree (hi->dev); kfree (hi->dev);
list_del (&hi->list);
kfree (hi);
} }
spin_unlock_irq (&host_info_lock);
return; return;
} }
...@@ -445,12 +400,15 @@ static void ether1394_remove_host (struct hpsb_host *host) ...@@ -445,12 +400,15 @@ static void ether1394_remove_host (struct hpsb_host *host)
/* A reset has just arisen */ /* A reset has just arisen */
static void ether1394_host_reset (struct hpsb_host *host) 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 */ /* This can happen for hosts that we don't use */
if (dev == NULL) if (hi == NULL)
return; return;
dev = hi->dev;
/* Reset our private host data, but not our mtu */ /* Reset our private host data, but not our mtu */
netif_stop_queue (dev); netif_stop_queue (dev);
ether1394_reset_priv (dev, 0); ether1394_reset_priv (dev, 0);
...@@ -559,15 +517,18 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid, ...@@ -559,15 +517,18 @@ static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
struct sk_buff *skb; struct sk_buff *skb;
char *buf = (char *)data; char *buf = (char *)data;
unsigned long flags; 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; struct eth1394_priv *priv;
if (dev == NULL) { if (hi == NULL) {
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n", ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n",
host); host);
return RCODE_ADDRESS_ERROR; return RCODE_ADDRESS_ERROR;
} }
dev = hi->dev;
priv = (struct eth1394_priv *)dev->priv; priv = (struct eth1394_priv *)dev->priv;
/* A packet has been received by the ieee1394 bus. Build an skbuff /* A packet has been received by the ieee1394 bus. Build an skbuff
...@@ -627,8 +588,9 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -627,8 +588,9 @@ static void ether1394_iso(struct hpsb_iso *iso)
struct sk_buff *skb; struct sk_buff *skb;
quadlet_t *data; quadlet_t *data;
char *buf; char *buf;
int flags; unsigned long flags;
struct net_device *dev = ether1394_find_dev(iso->host); struct host_info *hi = hpsb_get_hostinfo(hl_handle, iso->host);
struct net_device *dev;
struct eth1394_priv *priv; struct eth1394_priv *priv;
unsigned int len; unsigned int len;
u32 specifier_id; u32 specifier_id;
...@@ -636,12 +598,14 @@ static void ether1394_iso(struct hpsb_iso *iso) ...@@ -636,12 +598,14 @@ static void ether1394_iso(struct hpsb_iso *iso)
int i; int i;
int nready; int nready;
if (dev == NULL) { if (hi == NULL) {
ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n", ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n",
iso->host->driver->name); iso->host->driver->name);
return; return;
} }
dev = hi->dev;
nready = hpsb_iso_n_ready(iso); nready = hpsb_iso_n_ready(iso);
for(i = 0; i < nready; i++) { for(i = 0; i < nready; i++) {
struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i];
...@@ -941,19 +905,6 @@ static int __init ether1394_init_module (void) ...@@ -941,19 +905,6 @@ static int __init ether1394_init_module (void)
static void __exit ether1394_exit_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); hpsb_unregister_highlevel (hl_handle);
kmem_cache_destroy(packet_task_cache); kmem_cache_destroy(packet_task_cache);
} }
......
...@@ -56,7 +56,6 @@ struct eth1394_priv { ...@@ -56,7 +56,6 @@ struct eth1394_priv {
}; };
struct host_info { struct host_info {
struct list_head list;
struct hpsb_host *host; struct hpsb_host *host;
struct net_device *dev; struct net_device *dev;
}; };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/list.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
...@@ -27,20 +28,192 @@ ...@@ -27,20 +28,192 @@
#include "highlevel.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); static DECLARE_MUTEX(hl_drivers_lock);
LIST_HEAD(addr_space); static LIST_HEAD(addr_space);
rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED;
/* addr_space list will have zero and max already included as bounds */ /* 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_ops dummy_ops = { NULL, NULL, NULL, NULL };
static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr; 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 *hpsb_register_highlevel(const char *name,
struct hpsb_highlevel_ops *ops) struct hpsb_highlevel_ops *ops)
{ {
struct hpsb_highlevel *hl; struct hpsb_highlevel *hl;
struct list_head *lh;
hl = (struct hpsb_highlevel *)kmalloc(sizeof(struct hpsb_highlevel), hl = (struct hpsb_highlevel *)kmalloc(sizeof(struct hpsb_highlevel),
GFP_KERNEL); GFP_KERNEL);
...@@ -50,6 +223,8 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name, ...@@ -50,6 +223,8 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
INIT_LIST_HEAD(&hl->hl_list); INIT_LIST_HEAD(&hl->hl_list);
INIT_LIST_HEAD(&hl->addr_list); INIT_LIST_HEAD(&hl->addr_list);
INIT_LIST_HEAD(&hl->host_info_list);
hl->name = name; hl->name = name;
hl->op = ops; hl->op = ops;
...@@ -57,15 +232,21 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name, ...@@ -57,15 +232,21 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
list_add_tail(&hl->hl_list, &hl_drivers); list_add_tail(&hl->hl_list, &hl_drivers);
up(&hl_drivers_lock); up(&hl_drivers_lock);
if (hl->op->add_host) if (hl->op->add_host) {
hl_all_hosts(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; return hl;
} }
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
{ {
struct list_head *entry; struct list_head *lh, *next;
struct hpsb_address_serve *as; struct hpsb_address_serve *as;
if (hl == NULL) { if (hl == NULL) {
...@@ -73,12 +254,9 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) ...@@ -73,12 +254,9 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
} }
write_lock_irq(&addr_space_lock); write_lock_irq(&addr_space_lock);
entry = hl->addr_list.next; list_for_each_safe (lh, next, &hl->addr_list) {
as = list_entry(lh, struct hpsb_address_serve, addr_list);
while (entry != &hl->addr_list) {
as = list_entry(entry, struct hpsb_address_serve, addr_list);
list_del(&as->as_list); list_del(&as->as_list);
entry = entry->next;
kfree(as); kfree(as);
} }
write_unlock_irq(&addr_space_lock); write_unlock_irq(&addr_space_lock);
...@@ -87,8 +265,16 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) ...@@ -87,8 +265,16 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
list_del(&hl->hl_list); list_del(&hl->hl_list);
up(&hl_drivers_lock); up(&hl_drivers_lock);
if (hl->op->remove_host) if (hl->op->remove_host) {
hl_all_hosts(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); kfree(hl);
} }
...@@ -206,7 +392,7 @@ void highlevel_add_host(struct hpsb_host *host) ...@@ -206,7 +392,7 @@ void highlevel_add_host(struct hpsb_host *host)
hl = list_entry(entry, struct hpsb_highlevel, hl_list); hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->add_host) if (hl->op->add_host)
hl->op->add_host(host); hl->op->add_host(host, hl);
} }
up(&hl_drivers_lock); up(&hl_drivers_lock);
} }
...@@ -220,8 +406,10 @@ void highlevel_remove_host(struct hpsb_host *host) ...@@ -220,8 +406,10 @@ void highlevel_remove_host(struct hpsb_host *host)
list_for_each(entry, &hl_drivers) { list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list); hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->remove_host) if (hl->op->remove_host) {
hl->op->remove_host(host); hl->op->remove_host(host);
hpsb_destroy_hostinfo(hl, host);
}
} }
up(&hl_drivers_lock); up(&hl_drivers_lock);
} }
......
...@@ -11,6 +11,9 @@ struct hpsb_highlevel { ...@@ -11,6 +11,9 @@ struct hpsb_highlevel {
const char *name; const char *name;
struct hpsb_highlevel_ops *op; 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 { ...@@ -38,7 +41,7 @@ struct hpsb_highlevel_ops {
/* New host initialized. Will also be called during /* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */ * 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 /* Host about to be removed. Will also be called during
* hpsb_unregister_highlevel once for each host. */ * hpsb_unregister_highlevel once for each host. */
...@@ -155,4 +158,23 @@ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *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, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel); 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 */ #endif /* IEEE1394_HIGHLEVEL_H */
...@@ -22,12 +22,8 @@ ...@@ -22,12 +22,8 @@
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "highlevel.h" #include "highlevel.h"
static struct list_head hosts = LIST_HEAD_INIT(hosts); LIST_HEAD(hpsb_hosts);
static struct list_head host_drivers = LIST_HEAD_INIT(host_drivers); DECLARE_MUTEX(hpsb_hosts_lock);
spinlock_t hosts_lock = SPIN_LOCK_UNLOCKED;
spinlock_t host_drivers_lock = SPIN_LOCK_UNLOCKED;
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{ {
...@@ -64,11 +60,10 @@ static struct hpsb_host_driver dummy_driver = { ...@@ -64,11 +60,10 @@ static struct hpsb_host_driver dummy_driver = {
int hpsb_ref_host(struct hpsb_host *host) int hpsb_ref_host(struct hpsb_host *host)
{ {
struct list_head *lh; struct list_head *lh;
unsigned long flags;
int retval = 0; int retval = 0;
spin_lock_irqsave(&hosts_lock, flags); down(&hpsb_hosts_lock);
list_for_each(lh, &hosts) { list_for_each(lh, &hpsb_hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) { if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) { if (try_module_get(host->driver->owner)) {
host->refcount++; host->refcount++;
...@@ -77,7 +72,7 @@ int hpsb_ref_host(struct hpsb_host *host) ...@@ -77,7 +72,7 @@ int hpsb_ref_host(struct hpsb_host *host)
break; break;
} }
} }
spin_unlock_irqrestore(&hosts_lock, flags); up(&hpsb_hosts_lock);
return retval; return retval;
} }
...@@ -93,16 +88,14 @@ int hpsb_ref_host(struct hpsb_host *host) ...@@ -93,16 +88,14 @@ int hpsb_ref_host(struct hpsb_host *host)
void hpsb_unref_host(struct hpsb_host *host) void hpsb_unref_host(struct hpsb_host *host)
{ {
unsigned long flags;
module_put(host->driver->owner); module_put(host->driver->owner);
spin_lock_irqsave(&hosts_lock, flags); down(&hpsb_hosts_lock);
host->refcount--; host->refcount--;
if (!host->refcount && host->is_shutdown) if (!host->refcount && host->is_shutdown)
kfree(host); 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) ...@@ -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) void hpsb_add_host(struct hpsb_host *host)
{ {
unsigned long flags; down(&hpsb_hosts_lock);
list_add_tail(&host->host_list, &hpsb_hosts);
spin_lock_irqsave(&hosts_lock, flags); up(&hpsb_hosts_lock);
list_add_tail(&host->host_list, &hosts);
spin_unlock_irqrestore(&hosts_lock, flags);
highlevel_add_host(host); highlevel_add_host(host);
host->driver->devctl(host, RESET_BUS, LONG_RESET); host->driver->devctl(host, RESET_BUS, LONG_RESET);
...@@ -169,29 +160,11 @@ void hpsb_add_host(struct hpsb_host *host) ...@@ -169,29 +160,11 @@ void hpsb_add_host(struct hpsb_host *host)
void hpsb_remove_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->is_shutdown = 1;
host->driver = &dummy_driver; host->driver = &dummy_driver;
highlevel_remove_host(host); list_del(&host->host_list);
up(&hpsb_hosts_lock);
spin_lock_irqsave(&hosts_lock, flags); highlevel_remove_host(host);
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);
} }
...@@ -188,9 +188,9 @@ struct hpsb_host_driver { ...@@ -188,9 +188,9 @@ struct hpsb_host_driver {
quadlet_t data, quadlet_t compare); quadlet_t data, quadlet_t compare);
}; };
/* high level internal use */
struct hpsb_highlevel; extern struct list_head hpsb_hosts;
void hl_all_hosts(void (*function)(struct hpsb_host*)); extern struct semaphore hpsb_hosts_lock;
/* /*
......
...@@ -404,29 +404,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) ...@@ -404,29 +404,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
atomic_inc(&host->generation); atomic_inc(&host->generation);
host->in_bus_reset = 0; host->in_bus_reset = 0;
highlevel_host_reset(host); 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, ...@@ -462,6 +439,63 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
hpsb_schedule_work(&host->timeout_tq); 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 * hpsb_send_packet - transmit a packet on the bus
* @packet: packet to send * @packet: packet to send
...@@ -983,9 +1017,6 @@ static struct file_operations ieee1394_chardev_ops = { ...@@ -983,9 +1017,6 @@ static struct file_operations ieee1394_chardev_ops = {
.open = ieee1394_dispatch_open, .open = ieee1394_dispatch_open,
}; };
devfs_handle_t ieee1394_devfs_handle;
/* claim a block of minor numbers */ /* claim a block of minor numbers */
int ieee1394_register_chardev(int blocknum, int ieee1394_register_chardev(int blocknum,
struct module *module, struct module *module,
...@@ -1150,11 +1181,11 @@ static int __init ieee1394_init(void) ...@@ -1150,11 +1181,11 @@ static int __init ieee1394_init(void)
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
0, 0, NULL, NULL); 0, 0, NULL, NULL);
ieee1394_devfs_handle = devfs_mk_dir("ieee1394"); devfs_mk_dir("ieee1394");
if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) { if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) {
HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
devfs_unregister(ieee1394_devfs_handle); devfs_remove("ieee1394");
return -ENODEV; return -ENODEV;
} }
...@@ -1165,7 +1196,7 @@ static int __init ieee1394_init(void) ...@@ -1165,7 +1196,7 @@ static int __init ieee1394_init(void)
if (ieee1394_procfs_entry == NULL) { if (ieee1394_procfs_entry == NULL) {
HPSB_ERR("unable to create /proc/bus/ieee1394\n"); HPSB_ERR("unable to create /proc/bus/ieee1394\n");
unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
devfs_unregister(ieee1394_devfs_handle); devfs_remove("ieee1394");
return -ENOMEM; return -ENOMEM;
} }
ieee1394_procfs_entry->owner = THIS_MODULE; ieee1394_procfs_entry->owner = THIS_MODULE;
...@@ -1190,10 +1221,7 @@ static void __exit ieee1394_cleanup(void) ...@@ -1190,10 +1221,7 @@ static void __exit ieee1394_cleanup(void)
kmem_cache_destroy(hpsb_packet_cache); kmem_cache_destroy(hpsb_packet_cache);
unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
devfs_remove("ieee1394");
/* it's ok to pass a NULL devfs_handle to devfs_unregister */
devfs_unregister(ieee1394_devfs_handle);
remove_proc_entry("ieee1394", proc_bus); remove_proc_entry("ieee1394", proc_bus);
} }
...@@ -1214,17 +1242,16 @@ EXPORT_SYMBOL(hpsb_speedto_str); ...@@ -1214,17 +1242,16 @@ EXPORT_SYMBOL(hpsb_speedto_str);
EXPORT_SYMBOL(hpsb_set_packet_complete_task); EXPORT_SYMBOL(hpsb_set_packet_complete_task);
EXPORT_SYMBOL(alloc_hpsb_packet); EXPORT_SYMBOL(alloc_hpsb_packet);
EXPORT_SYMBOL(free_hpsb_packet); EXPORT_SYMBOL(free_hpsb_packet);
EXPORT_SYMBOL(hpsb_send_phy_config);
EXPORT_SYMBOL(hpsb_send_packet); EXPORT_SYMBOL(hpsb_send_packet);
EXPORT_SYMBOL(hpsb_reset_bus); EXPORT_SYMBOL(hpsb_reset_bus);
EXPORT_SYMBOL(hpsb_bus_reset); EXPORT_SYMBOL(hpsb_bus_reset);
EXPORT_SYMBOL(hpsb_selfid_received); EXPORT_SYMBOL(hpsb_selfid_received);
EXPORT_SYMBOL(hpsb_selfid_complete); EXPORT_SYMBOL(hpsb_selfid_complete);
EXPORT_SYMBOL(hpsb_check_cycle_master);
EXPORT_SYMBOL(hpsb_packet_sent); EXPORT_SYMBOL(hpsb_packet_sent);
EXPORT_SYMBOL(hpsb_packet_received); EXPORT_SYMBOL(hpsb_packet_received);
EXPORT_SYMBOL(ieee1394_register_chardev); EXPORT_SYMBOL(ieee1394_register_chardev);
EXPORT_SYMBOL(ieee1394_unregister_chardev); EXPORT_SYMBOL(ieee1394_unregister_chardev);
EXPORT_SYMBOL(ieee1394_devfs_handle);
EXPORT_SYMBOL(ieee1394_procfs_entry); EXPORT_SYMBOL(ieee1394_procfs_entry);
/** ieee1394_transactions.c **/ /** ieee1394_transactions.c **/
...@@ -1250,6 +1277,13 @@ EXPORT_SYMBOL(hpsb_register_addrspace); ...@@ -1250,6 +1277,13 @@ EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_listen_channel);
EXPORT_SYMBOL(hpsb_unlisten_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_read);
EXPORT_SYMBOL(highlevel_write); EXPORT_SYMBOL(highlevel_write);
EXPORT_SYMBOL(highlevel_lock); EXPORT_SYMBOL(highlevel_lock);
...@@ -1302,4 +1336,3 @@ EXPORT_SYMBOL(hpsb_iso_n_ready); ...@@ -1302,4 +1336,3 @@ EXPORT_SYMBOL(hpsb_iso_n_ready);
EXPORT_SYMBOL(hpsb_iso_packet_sent); EXPORT_SYMBOL(hpsb_iso_packet_sent);
EXPORT_SYMBOL(hpsb_iso_packet_received); EXPORT_SYMBOL(hpsb_iso_packet_received);
EXPORT_SYMBOL(hpsb_iso_wake); EXPORT_SYMBOL(hpsb_iso_wake);
...@@ -108,6 +108,11 @@ static inline unsigned int get_hpsb_generation(struct hpsb_host *host) ...@@ -108,6 +108,11 @@ static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
return atomic_read(&host->generation); 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. * Queue packet for transmitting, return 0 for failure.
*/ */
...@@ -140,12 +145,6 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid); ...@@ -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); 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 * 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 * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
...@@ -225,9 +224,6 @@ int ieee1394_register_chardev(int blocknum, /* 0-15 */ ...@@ -225,9 +224,6 @@ int ieee1394_register_chardev(int blocknum, /* 0-15 */
/* release a block of minor numbers */ /* release a block of minor numbers */
void ieee1394_unregister_chardev(int blocknum); 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 */ /* the proc_fs entry for /proc/ieee1394 */
extern struct proc_dir_entry *ieee1394_procfs_entry; extern struct proc_dir_entry *ieee1394_procfs_entry;
......
...@@ -70,8 +70,7 @@ static char *nodemgr_find_oui_name(int oui) ...@@ -70,8 +70,7 @@ static char *nodemgr_find_oui_name(int oui)
static DECLARE_MUTEX(nodemgr_serialize); static DECLARE_MUTEX(nodemgr_serialize);
static LIST_HEAD(host_info_list); static struct hpsb_highlevel *nodemgr_hl;
static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
struct host_info { struct host_info {
struct hpsb_host *host; struct hpsb_host *host;
...@@ -917,7 +916,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent ...@@ -917,7 +916,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent
address += 4; address += 4;
infop = (quadlet_t *) ud->quadlets; infop = (quadlet_t *) ud->quadlets;
for (; length > 0; length--, address += 4, infop++) { for (; length > 0; length--, address += 4) {
int code; int code;
quadlet_t value; quadlet_t value;
quadlet_t *quadp; quadlet_t *quadp;
...@@ -990,7 +989,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent ...@@ -990,7 +989,7 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent
CSR offsets for now. */ CSR offsets for now. */
code &= CONFIG_ROM_KEY_TYPE_MASK; code &= CONFIG_ROM_KEY_TYPE_MASK;
if ((code & 0x80) == 0) if ((code & 0x80) == 0)
*infop = quad; *infop++ = quad;
break; break;
} }
} }
...@@ -1140,30 +1139,10 @@ static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, ...@@ -1140,30 +1139,10 @@ static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp,
static int nodemgr_alloc_host_num(void) static int nodemgr_alloc_host_num(void)
{ {
int hostnum = 0; int hostnum;
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;
}
}
if (!found) for (hostnum = 0; hpsb_get_hostinfo_bykey(nodemgr_hl, hostnum); hostnum++)
break; /* Do nothing */;
hostnum++;
}
spin_unlock_irqrestore (&host_info_lock, flags);
return hostnum; return hostnum;
} }
...@@ -1491,7 +1470,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -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 /* 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 * 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) static void nodemgr_do_irm_duties(struct hpsb_host *host)
{ {
quadlet_t bc; quadlet_t bc;
...@@ -1506,12 +1485,30 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host) ...@@ -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), hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
(CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
&bc, sizeof(quadlet_t)); &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 /* 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 * everything we can do, otherwise issue a bus reset and try to become the IRM
* ourselves. */ * ourselves. */
static int nodemgr_check_root_capability(struct hpsb_host *host) static int nodemgr_check_irm_capability(struct hpsb_host *host)
{ {
quadlet_t bc; quadlet_t bc;
int status; int status;
...@@ -1525,9 +1522,10 @@ static int nodemgr_check_root_capability(struct hpsb_host *host) ...@@ -1525,9 +1522,10 @@ static int nodemgr_check_root_capability(struct hpsb_host *host)
&bc, sizeof(quadlet_t)); &bc, sizeof(quadlet_t));
if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { 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 */ * 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); hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
return 0; return 0;
} }
...@@ -1565,7 +1563,7 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1565,7 +1563,7 @@ static int nodemgr_host_thread(void *__hi)
* for the read transactions, so that if another reset occurs * for the read transactions, so that if another reset occurs
* during the scan the transactions will fail instead of * during the scan the transactions will fail instead of
* returning bogus data. */ * 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 /* If we get a reset before we are done waiting, then
* start the the waiting over again */ * start the the waiting over again */
...@@ -1573,7 +1571,7 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1573,7 +1571,7 @@ static int nodemgr_host_thread(void *__hi)
i = HZ/4; i = HZ/4;
} }
if (!nodemgr_check_root_capability(host)) { if (!nodemgr_check_irm_capability(host)) {
/* Do nothing, we are resetting */ /* Do nothing, we are resetting */
up(&nodemgr_serialize); up(&nodemgr_serialize);
continue; continue;
...@@ -1683,12 +1681,11 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr, ...@@ -1683,12 +1681,11 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr,
addr, extcode, data, arg); 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; 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) { if (!hi) {
HPSB_ERR ("NodeMgr: out of memory in add host"); HPSB_ERR ("NodeMgr: out of memory in add host");
...@@ -1698,14 +1695,14 @@ static void nodemgr_add_host(struct hpsb_host *host) ...@@ -1698,14 +1695,14 @@ static void nodemgr_add_host(struct hpsb_host *host)
/* Initialize the hostinfo here and start the thread. The /* Initialize the hostinfo here and start the thread. The
* thread blocks on the reset semaphore until a bus reset * thread blocks on the reset semaphore until a bus reset
* happens. */ * happens. */
memset(hi, 0, sizeof(*hi));
hi->host = host; hi->host = host;
INIT_LIST_HEAD(&hi->list);
init_completion(&hi->exited); init_completion(&hi->exited);
sema_init(&hi->reset_sem, 0); sema_init(&hi->reset_sem, 0);
hi->id = nodemgr_alloc_host_num(); hi->id = nodemgr_alloc_host_num();
hpsb_set_hostinfo_key(hl, host, hi->id);
memcpy(&host->device, &nodemgr_dev_template_host, memcpy(&host->device, &nodemgr_dev_template_host,
sizeof(host->device)); sizeof(host->device));
host->device.parent = &host->pdev->dev; host->device.parent = &host->pdev->dev;
...@@ -1715,40 +1712,22 @@ static void nodemgr_add_host(struct hpsb_host *host) ...@@ -1715,40 +1712,22 @@ static void nodemgr_add_host(struct hpsb_host *host)
sprintf(hi->daemon_name, "knodemgrd_%d", hi->id); sprintf(hi->daemon_name, "knodemgrd_%d", hi->id);
spin_lock_irqsave (&host_info_lock, flags);
hi->pid = kernel_thread(nodemgr_host_thread, hi, hi->pid = kernel_thread(nodemgr_host_thread, hi,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND); CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
if (hi->pid < 0) { if (hi->pid < 0) {
HPSB_ERR ("NodeMgr: failed to start %s thread for %s", HPSB_ERR ("NodeMgr: failed to start %s thread for %s",
hi->daemon_name, host->driver->name); hi->daemon_name, host->driver->name);
kfree(hi); hpsb_destroy_hostinfo(hl, host);
spin_unlock_irqrestore (&host_info_lock, flags);
return; return;
} }
list_add_tail (&hi->list, &host_info_list);
spin_unlock_irqrestore (&host_info_lock, flags);
return; return;
} }
static void nodemgr_host_reset(struct hpsb_host *host) static void nodemgr_host_reset(struct hpsb_host *host)
{ {
struct list_head *lh; struct host_info *hi = hpsb_get_hostinfo(nodemgr_hl, host);
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;
}
}
if (hi != NULL) { if (hi != NULL) {
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
...@@ -1756,29 +1735,14 @@ static void nodemgr_host_reset(struct hpsb_host *host) ...@@ -1756,29 +1735,14 @@ static void nodemgr_host_reset(struct hpsb_host *host)
#endif #endif
up(&hi->reset_sem); up(&hi->reset_sem);
} else } else
HPSB_ERR ("NodeMgr: could not process reset of non-existent host"); HPSB_ERR ("NodeMgr: could not process reset of unused host");
spin_unlock_irqrestore (&host_info_lock, flags);
return; return;
} }
static void nodemgr_remove_host(struct hpsb_host *host) static void nodemgr_remove_host(struct hpsb_host *host)
{ {
struct list_head *lh, *next; struct host_info *hi = hpsb_get_hostinfo(nodemgr_hl, host);
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);
if (hi) { if (hi) {
if (hi->pid >= 0) { if (hi->pid >= 0) {
...@@ -1787,7 +1751,6 @@ static void nodemgr_remove_host(struct hpsb_host *host) ...@@ -1787,7 +1751,6 @@ static void nodemgr_remove_host(struct hpsb_host *host)
nodemgr_remove_host_dev(&host->device); nodemgr_remove_host_dev(&host->device);
device_unregister(&host->device); device_unregister(&host->device);
} }
kfree(hi);
} else } else
HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
host->driver->name); host->driver->name);
...@@ -1801,21 +1764,19 @@ static struct hpsb_highlevel_ops nodemgr_ops = { ...@@ -1801,21 +1764,19 @@ static struct hpsb_highlevel_ops nodemgr_ops = {
.remove_host = nodemgr_remove_host, .remove_host = nodemgr_remove_host,
}; };
static struct hpsb_highlevel *hl;
void init_ieee1394_nodemgr(void) void init_ieee1394_nodemgr(void)
{ {
bus_register(&ieee1394_bus_type); bus_register(&ieee1394_bus_type);
hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); nodemgr_hl = hpsb_register_highlevel("Node manager", &nodemgr_ops);
if (!hl) { if (!nodemgr_hl) {
HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization");
} }
} }
void cleanup_ieee1394_nodemgr(void) void cleanup_ieee1394_nodemgr(void)
{ {
hpsb_unregister_highlevel(hl); hpsb_unregister_highlevel(nodemgr_hl);
bus_unregister(&ieee1394_bus_type); bus_unregister(&ieee1394_bus_type);
} }
...@@ -165,7 +165,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) ...@@ -165,7 +165,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 858 $ Ben Collins <bcollins@debian.org>"; "$Rev: 866 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
static int phys_dma = 1; static int phys_dma = 1;
......
...@@ -72,8 +72,6 @@ printk(KERN_INFO "raw1394:" fmt "\n" , ## args) ...@@ -72,8 +72,6 @@ printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
#define DBGMSG(fmt, args...) #define DBGMSG(fmt, args...)
#endif #endif
static devfs_handle_t devfs_handle;
static LIST_HEAD(host_info_list); static LIST_HEAD(host_info_list);
static int host_count; static int host_count;
static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
...@@ -190,13 +188,13 @@ static void queue_complete_cb(struct pending_request *req) ...@@ -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; struct host_info *hi;
unsigned long flags; unsigned long flags;
hi = (struct host_info *)kmalloc(sizeof(struct host_info), hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
if (hi != NULL) { if (hi != NULL) {
INIT_LIST_HEAD(&hi->list); INIT_LIST_HEAD(&hi->list);
hi->host = host; hi->host = host;
...@@ -2536,17 +2534,14 @@ static int __init init_raw1394(void) ...@@ -2536,17 +2534,14 @@ static int __init init_raw1394(void)
return -ENOMEM; return -ENOMEM;
} }
devfs_handle = devfs_register(NULL, devfs_register(NULL, RAW1394_DEVICE_NAME, 0,
RAW1394_DEVICE_NAME, DEVFS_FL_NONE, IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16,
IEEE1394_MAJOR, S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL);
IEEE1394_MINOR_BLOCK_RAW1394 * 16,
S_IFCHR | S_IRUSR | S_IWUSR, &file_ops,
NULL);
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394,
THIS_MODULE, &file_ops)) { THIS_MODULE, &file_ops)) {
HPSB_ERR("raw1394 failed to register minor device block"); HPSB_ERR("raw1394 failed to register minor device block");
devfs_unregister(devfs_handle); devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(hl_handle); hpsb_unregister_highlevel(hl_handle);
return -EBUSY; return -EBUSY;
} }
...@@ -2562,7 +2557,7 @@ static void __exit cleanup_raw1394(void) ...@@ -2562,7 +2557,7 @@ static void __exit cleanup_raw1394(void)
{ {
hpsb_unregister_protocol(&raw1394_driver); hpsb_unregister_protocol(&raw1394_driver);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394);
devfs_unregister(devfs_handle); devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(hl_handle); hpsb_unregister_highlevel(hl_handle);
} }
......
...@@ -298,7 +298,7 @@ ...@@ -298,7 +298,7 @@
#include "sbp2.h" #include "sbp2.h"
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 846 $ James Goodwin <jamesg@filanet.com>"; "$Rev: 884 $ James Goodwin <jamesg@filanet.com>";
/* /*
* Module load parameter definitions * Module load parameter definitions
...@@ -456,10 +456,6 @@ static Scsi_Host_Template scsi_driver_template; ...@@ -456,10 +456,6 @@ static Scsi_Host_Template scsi_driver_template;
static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 }; 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 *sbp2_hl_handle = NULL;
static struct hpsb_highlevel_ops sbp2_hl_ops = { static struct hpsb_highlevel_ops sbp2_hl_ops = {
...@@ -779,10 +775,9 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( ...@@ -779,10 +775,9 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
static void sbp2util_free_command_dma(struct sbp2_command_info *command) static void sbp2util_free_command_dma(struct sbp2_command_info *command)
{ {
struct sbp2scsi_host_info *hi; 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__); printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__);
return; return;
} }
...@@ -911,87 +906,47 @@ static void sbp2_update(struct unit_directory *ud) ...@@ -911,87 +906,47 @@ static void sbp2_update(struct unit_directory *ud)
static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host)
{ {
struct sbp2scsi_host_info *hi; struct sbp2scsi_host_info *hi;
unsigned long flags;
struct Scsi_Host *scsi_host; struct Scsi_Host *scsi_host;
SBP2_DEBUG("sbp2_add_host"); SBP2_DEBUG("sbp2_add_host");
hi = sbp2_find_host_info(host); hi = hpsb_get_hostinfo(sbp2_hl_handle, host);
if (hi) if (hi)
return hi; return hi;
/* Register our host with the SCSI stack. */ /* 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) { if (!scsi_host) {
SBP2_ERR("failed to register scsi host"); SBP2_ERR("failed to register scsi host");
return NULL; return NULL;
} }
hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata; hi = hpsb_create_hostinfo(sbp2_hl_handle, host, sizeof(*hi));
memset(hi, 0, sizeof(struct sbp2scsi_host_info)); 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; hi->scsi_host = scsi_host;
INIT_LIST_HEAD(&hi->list);
hi->host = host; hi->host = host;
hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; 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 /* 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 * 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 * host. Can't use the fw-host device since it is multi-class
* enabled (scsi-host uses classdata member of the device). */ * enabled (scsi-host uses classdata member of the device). */
if (scsi_add_host(hi->scsi_host, NULL)) { if (scsi_add_host(hi->scsi_host, NULL)) {
SBP2_ERR("failed to add scsi host"); 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); scsi_unregister(hi->scsi_host);
hpsb_destroy_hostinfo(sbp2_hl_handle, host);
} }
return hi; 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. * 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 ...@@ -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) static void sbp2_remove_host(struct hpsb_host *host)
{ {
struct sbp2scsi_host_info *hi; struct sbp2scsi_host_info *hi;
unsigned long flags;
SBP2_DEBUG("sbp2_remove_host"); SBP2_DEBUG("sbp2_remove_host");
spin_lock_irqsave(&sbp2_host_info_lock, flags); hi = hpsb_get_hostinfo(sbp2_hl_handle, host);
hi = sbp2_find_host_info(host);
if (hi)
list_del(&hi->list);
spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
if (hi) { if (hi) {
scsi_remove_host(hi->scsi_host); scsi_remove_host(hi->scsi_host);
scsi_unregister(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 ...@@ -2614,9 +2565,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
return(RCODE_ADDRESS_ERROR); return(RCODE_ADDRESS_ERROR);
} }
spin_lock_irqsave(&sbp2_host_info_lock, flags); hi = hpsb_get_hostinfo(sbp2_hl_handle, host);
hi = sbp2_find_host_info(host);
spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
if (!hi) { if (!hi) {
SBP2_ERR("host info is NULL - this is bad!"); SBP2_ERR("host info is NULL - this is bad!");
...@@ -2763,7 +2712,7 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -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 * 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) { if (!hi) {
SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); 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, ...@@ -2992,7 +2941,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
*/ */
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) 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 scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
struct sbp2_command_info *command; struct sbp2_command_info *command;
unsigned long flags; unsigned long flags;
...@@ -3042,7 +2992,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) ...@@ -3042,7 +2992,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
*/ */
static int sbp2scsi_reset (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]; struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
SBP2_ERR("reset requested"); SBP2_ERR("reset requested");
...@@ -3080,7 +3031,7 @@ static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset, ...@@ -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 */ if (!host) /* if we couldn't find it, we return an error */
return -ESRCH; 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... */ if (!hi) /* shouldn't happen, but... */
return -ESRCH; return -ESRCH;
......
...@@ -417,11 +417,6 @@ struct scsi_id_instance_data { ...@@ -417,11 +417,6 @@ struct scsi_id_instance_data {
* Sbp2 host data structure (one per sbp2 host) * Sbp2 host data structure (one per sbp2 host)
*/ */
struct sbp2scsi_host_info { struct sbp2scsi_host_info {
/*
* For use in keeping track of hosts
*/
struct list_head list;
struct hpsb_host *host; struct hpsb_host *host;
/* /*
...@@ -463,7 +458,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i ...@@ -463,7 +458,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
* IEEE-1394 core driver related prototypes * IEEE-1394 core driver related prototypes
*/ */
static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); 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 void sbp2_remove_host(struct hpsb_host *host);
static int sbp2_probe(struct device *dev); static int sbp2_probe(struct device *dev);
......
...@@ -122,16 +122,9 @@ struct dma_iso_ctx { ...@@ -122,16 +122,9 @@ struct dma_iso_ctx {
struct list_head link; 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 file_ctx {
struct video_card *video; struct ti_ohci *ohci;
struct list_head context_list; struct list_head context_list;
struct dma_iso_ctx *current_ctx; struct dma_iso_ctx *current_ctx;
}; };
...@@ -162,10 +155,6 @@ printk(level "video1394_%d: " fmt "\n" , card , ## args) ...@@ -162,10 +155,6 @@ printk(level "video1394_%d: " fmt "\n" , card , ## args)
void wakeup_dma_ir_ctx(unsigned long l); void wakeup_dma_ir_ctx(unsigned long l);
void wakeup_dma_it_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; static struct hpsb_highlevel *hl_handle = NULL;
...@@ -716,8 +705,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, ...@@ -716,8 +705,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct file_ctx *ctx = (struct file_ctx *)file->private_data; struct file_ctx *ctx = (struct file_ctx *)file->private_data;
struct video_card *video = ctx->video; struct ti_ohci *ohci = ctx->ohci;
struct ti_ohci *ohci = video->ohci;
unsigned long flags; unsigned long flags;
switch(cmd) switch(cmd)
...@@ -1162,7 +1150,7 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1162,7 +1150,7 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma)
lock_kernel(); lock_kernel();
if (ctx->current_ctx == NULL) { 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 } else
res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
unlock_kernel(); unlock_kernel();
...@@ -1173,32 +1161,21 @@ int video1394_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -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) static int video1394_open(struct inode *inode, struct file *file)
{ {
int i = ieee1394_file_to_instance(file); int i = ieee1394_file_to_instance(file);
unsigned long flags; struct ti_ohci *ohci;
struct video_card *video = NULL;
struct list_head *lh;
struct file_ctx *ctx; struct file_ctx *ctx;
spin_lock_irqsave(&video1394_cards_lock, flags); ohci = hpsb_get_hostinfo_bykey(hl_handle, i);
list_for_each(lh, &video1394_cards) { if (ohci == NULL)
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)
return -EIO; return -EIO;
ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL); ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
if (ctx == NULL) { if (ctx == NULL) {
PRINT(KERN_ERR, video->ohci->id, "Cannot malloc file_ctx"); PRINT(KERN_ERR, ohci->id, "Cannot malloc file_ctx");
return -ENOMEM; return -ENOMEM;
} }
memset(ctx, 0, sizeof(struct file_ctx)); memset(ctx, 0, sizeof(struct file_ctx));
ctx->video = video; ctx->ohci = ohci;
INIT_LIST_HEAD(&ctx->context_list); INIT_LIST_HEAD(&ctx->context_list);
ctx->current_ctx = NULL; ctx->current_ctx = NULL;
file->private_data = ctx; file->private_data = ctx;
...@@ -1209,8 +1186,7 @@ static int video1394_open(struct inode *inode, struct file *file) ...@@ -1209,8 +1186,7 @@ static int video1394_open(struct inode *inode, struct file *file)
static int video1394_release(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 file_ctx *ctx = (struct file_ctx *)file->private_data;
struct video_card *video = ctx->video; struct ti_ohci *ohci = ctx->ohci;
struct ti_ohci *ohci = video->ohci;
struct list_head *lh, *next; struct list_head *lh, *next;
u64 mask; u64 mask;
...@@ -1273,54 +1249,11 @@ static struct hpsb_protocol_driver video1394_driver = { ...@@ -1273,54 +1249,11 @@ static struct hpsb_protocol_driver video1394_driver = {
}; };
static int video1394_init(struct ti_ohci *ohci) static void video1394_add_host (struct hpsb_host *host, struct hpsb_highlevel *hl)
{
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)
{ {
struct ti_ohci *ohci; struct ti_ohci *ohci;
unsigned long flags; char name[16];
struct list_head *lh, *next; int minor;
struct video_card *p;
/* We only work with the OHCI-1394 driver */ /* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
...@@ -1328,34 +1261,34 @@ static void video1394_remove_host (struct hpsb_host *host) ...@@ -1328,34 +1261,34 @@ static void video1394_remove_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata; ohci = (struct ti_ohci *)host->hostdata;
spin_lock_irqsave(&video1394_cards_lock, flags); if (!hpsb_create_hostinfo(hl, host, 0)) {
list_for_each_safe(lh, next, &video1394_cards) { PRINT(KERN_ERR, ohci->id, "Cannot allocate hostinfo");
p = list_entry(lh, struct video_card, list); return;
if (p->ohci == ohci) {
remove_card(p);
break;
}
} }
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; return;
} }
static void video1394_add_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
/* We only work with the OHCI-1394 driver */ static void video1394_remove_host (struct hpsb_host *host)
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) {
return; 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; return;
} }
static struct hpsb_highlevel_ops hl_ops = { static struct hpsb_highlevel_ops hl_ops = {
.add_host = video1394_add_host, .add_host = video1394_add_host,
.remove_host = video1394_remove_host, .remove_host = video1394_remove_host,
...@@ -1497,7 +1430,7 @@ static void __exit video1394_exit_module (void) ...@@ -1497,7 +1430,7 @@ static void __exit video1394_exit_module (void)
hpsb_unregister_highlevel (hl_handle); hpsb_unregister_highlevel (hl_handle);
devfs_unregister(devfs_handle); devfs_remove(VIDEO1394_DRIVER_NAME);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
...@@ -1514,12 +1447,12 @@ static int __init video1394_init_module (void) ...@@ -1514,12 +1447,12 @@ static int __init video1394_init_module (void)
return -EIO; 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); hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
if (hl_handle == NULL) { if (hl_handle == NULL) {
PRINT_G(KERN_ERR, "No more memory for driver\n"); 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); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
return -ENOMEM; return -ENOMEM;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment