[Linux1394-cvslog] rev 529 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <hog...@us...> - 2002-07-25 00:15:54
|
Author: hogsberg Date: Wed, 24 Jul 2002 20:15:24 -0400 New Revision: 529 Modified: trunk/nodemgr.c trunk/sbp2.c Log: Remove spinlock madness from nodemgr.c and replace with simple semaphore locking scheme. Add more #ifdef cruft to sbp2.c to lift the io_request_lock during sbp2_init, which do all sorts of blocking stuff. Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c Wed Jul 24 20:15:34 2002 @@ -45,18 +45,21 @@ * a way that's easy to parse by the protocol interface. */ -static LIST_HEAD(node_list); -static rwlock_t node_lock = RW_LOCK_UNLOCKED; +/* The nodemgr maintains a number of data structures: the node list, + * the driver list, unit directory list and the host info list. The + * first three lists are accessed from process context only: /proc + * readers, insmod and rmmod, and the nodemgr thread. Access to these + * lists are serialized by means of the nodemgr_serialize mutex, which + * must be taken before accessing the structures and released + * afterwards. The host info list is only accessed during insmod, + * rmmod and from interrupt and allways only for a short period of + * time, so a spinlock is used to protect this list. + */ +static DECLARE_MUTEX(nodemgr_serialize); +static LIST_HEAD(node_list); static LIST_HEAD(driver_list); -static rwlock_t driver_lock = RW_LOCK_UNLOCKED; - -/* The rwlock unit_directory_lock is always held when manipulating the - * global unit_directory_list, but this also protects access to the - * lists of unit directories stored in the protocol drivers. - */ static LIST_HEAD(unit_directory_list); -static rwlock_t unit_directory_lock = RW_LOCK_UNLOCKED; static LIST_HEAD(host_info_list); static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; @@ -84,6 +87,9 @@ int len; char *out = page; + if (down_interruptible(&nodemgr_serialize)) + return -EINTR; + list_for_each(lh, &node_list) { struct list_head *l; int ud_count = 0; @@ -148,6 +154,8 @@ } + up(&nodemgr_serialize); + len = out - page; len -= off; if (len < count) { @@ -306,7 +314,6 @@ nodeid_t nodeid, unsigned int generation) { struct node_entry *ne; - unsigned long flags; ne = nodemgr_scan_root_directory (host, nodeid, generation); if (!ne) return NULL; @@ -318,9 +325,7 @@ ne->guid = guid; ne->generation = generation; - write_lock_irqsave(&node_lock, flags); list_add_tail(&ne->list, &node_list); - write_unlock_irqrestore(&node_lock, flags); nodemgr_process_config_rom (ne, busoptions); @@ -758,11 +763,9 @@ void hpsb_release_unit_directory(struct unit_directory *ud) { - unsigned long flags; - - write_lock_irqsave(&unit_directory_lock, flags); + down(&nodemgr_serialize); nodemgr_release_unit_directory(ud); - write_unlock_irqrestore(&unit_directory_lock, flags); + up(&nodemgr_serialize); } static void nodemgr_free_unit_directories(struct node_entry *ne) @@ -852,13 +855,12 @@ { struct unit_directory *ud; struct list_head *lh; - unsigned long flags; - write_lock_irqsave(&driver_lock, flags); + if (down_interruptible(&nodemgr_serialize)) + return -EINTR; + list_add_tail(&driver->list, &driver_list); - write_unlock_irqrestore(&driver_lock, flags); - write_lock_irqsave(&unit_directory_lock, flags); INIT_LIST_HEAD(&driver->unit_directories); lh = unit_directory_list.next; while (lh != &unit_directory_list) { @@ -867,7 +869,8 @@ if (nodemgr_match_driver(driver, ud) && driver->probe(ud) == 0) nodemgr_claim_unit_directory(ud, driver); } - write_unlock_irqrestore(&unit_directory_lock, flags); + + up(&nodemgr_serialize); /* * Right now registration always succeeds, but maybe we should @@ -881,13 +884,10 @@ { struct list_head *lh; struct unit_directory *ud; - unsigned long flags; - write_lock_irqsave(&driver_lock, flags); - list_del(&driver->list); - write_unlock_irqrestore(&driver_lock, flags); + down(&nodemgr_serialize); - write_lock_irqsave(&unit_directory_lock, flags); + list_del(&driver->list); lh = driver->unit_directories.next; while (lh != &driver->unit_directories) { ud = list_entry(lh, struct unit_directory, driver_list); @@ -896,14 +896,13 @@ ud->driver->disconnect(ud); nodemgr_release_unit_directory(ud); } - write_unlock_irqrestore(&unit_directory_lock, flags); + + up(&nodemgr_serialize); } static void nodemgr_process_config_rom(struct node_entry *ne, quadlet_t busoptions) { - unsigned long flags; - ne->busopt.irmc = (busoptions >> 31) & 1; ne->busopt.cmc = (busoptions >> 30) & 1; ne->busopt.isc = (busoptions >> 29) & 1; @@ -929,11 +928,9 @@ * thing. If this was a new device, the call to * nodemgr_disconnect_drivers is a no-op and all is well. */ - write_lock_irqsave(&unit_directory_lock, flags); nodemgr_free_unit_directories(ne); nodemgr_process_root_directory(ne); nodemgr_bind_drivers(ne); - write_unlock_irqrestore(&unit_directory_lock, flags); } /* @@ -1032,16 +1029,12 @@ static void nodemgr_remove_node(struct node_entry *ne) { - unsigned long flags; - HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", (ne->host->node_id == ne->nodeid) ? "Host" : "Device", NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid, ne->vendor_name ?: "Unknown"); - write_lock_irqsave(&unit_directory_lock, flags); nodemgr_free_unit_directories(ne); - write_unlock_irqrestore(&unit_directory_lock, flags); list_del(&ne->list); kfree(ne); @@ -1077,7 +1070,7 @@ } guid = ((u64)buffer[3] << 32) | buffer[4]; - ne = hpsb_guid_get_entry(guid); + ne = find_entry_by_guid(guid); if (!ne) nodemgr_create_node(guid, buffer[2], host, nodeid, generation); @@ -1089,13 +1082,11 @@ static void nodemgr_node_probe_cleanup(struct hpsb_host *host, unsigned int generation) { - unsigned long flags; struct list_head *lh, *next; struct node_entry *ne; /* Now check to see if we have any nodes that aren't referenced * any longer. */ - write_lock_irqsave(&node_lock, flags); list_for_each_safe(lh, next, &node_list) { ne = list_entry(lh, struct node_entry, list); @@ -1110,7 +1101,6 @@ if (ne->generation != generation) nodemgr_remove_node(ne); } - write_unlock_irqrestore(&node_lock, flags); return; } @@ -1169,12 +1159,14 @@ daemonize(); strcpy(current->comm, "knodemgrd"); - + /* Sit and wait for a signal to probe the nodes on the bus. This * happens when we get a bus reset. */ - while (!down_interruptible(&hi->reset_sem)) + while (!down_interruptible(&hi->reset_sem) && + !down_interruptible(&nodemgr_serialize)) { nodemgr_node_probe(hi->host); - + up(&nodemgr_serialize); + } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name); #endif @@ -1184,24 +1176,22 @@ struct node_entry *hpsb_guid_get_entry(u64 guid) { - unsigned long flags; struct node_entry *ne; - read_lock_irqsave(&node_lock, flags); + down(&nodemgr_serialize); ne = find_entry_by_guid(guid); - read_unlock_irqrestore(&node_lock, flags); + up(&nodemgr_serialize); return ne; } struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid) { - unsigned long flags; struct node_entry *ne; - read_lock_irqsave(&node_lock, flags); + down(&nodemgr_serialize); ne = find_entry_by_nodeid(nodeid); - read_unlock_irqrestore(&node_lock, flags); + up(&nodemgr_serialize); return ne; } @@ -1309,17 +1299,14 @@ } } - if (hi == NULL) { - HPSB_ERR ("NodeMgr: could not process reset of non-existent host"); - goto done_reset_host; - } - + if (hi != NULL) #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG ("NodeMgr: Processing host reset for %s", host->driver->name); #endif - up(&hi->reset_sem); + up(&hi->reset_sem); + else + HPSB_ERR ("NodeMgr: could not process reset of non-existent host"); -done_reset_host: spin_unlock_irqrestore (&host_info_lock, flags); return; @@ -1341,30 +1328,31 @@ break; } } - - if (!hi) - HPSB_ERR ("NodeMgr: host %s does not exist, cannot remove", - host->driver->name); spin_unlock_irqrestore (&host_info_lock, flags); + if (hi) { + if (hi->pid >= 0) { + kill_proc(hi->pid, SIGTERM, 1); + wait_for_completion(&hi->exited); + } + kfree(hi); + } + else + HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", + host->driver->name); + + down(&nodemgr_serialize); + /* Even if we fail the host_info part, remove all the node * entries. */ - write_lock_irqsave(&node_lock, flags); list_for_each_safe(lh, next, &node_list) { ne = list_entry(lh, struct node_entry, list); if (ne->host == host) nodemgr_remove_node(ne); } - write_unlock_irqrestore(&node_lock, flags); - if (hi) { - if (hi->pid >= 0) { - kill_proc(hi->pid, SIGTERM, 1); - wait_for_completion(&hi->exited); - } - kfree(hi); - } + up(&nodemgr_serialize); return; } Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c Wed Jul 24 20:15:36 2002 @@ -320,6 +320,7 @@ #include <linux/blk.h> #include <linux/smp_lock.h> #include <linux/init.h> +#include <linux/blk.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -3170,7 +3171,14 @@ * host controller currently registered, and for each of those * we register a scsi host with the scsi stack. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + spin_unlock_irq(&io_request_lock); sbp2_init(); + spin_lock_irq(&io_request_lock); +#else + sbp2_init(); +#endif /* We return the number of hosts registered. */ return scsi_driver_template.present; |