Update of /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394 In directory sc8-pr-cvs1:/tmp/cvs-serv7538/drivers/ieee1394 Modified Files: hosts.c ieee1394_core.c nodemgr.c ohci1394.c pcilynx.c sbp2.c sbp2.h video1394.c video1394.h Log Message: DA: sync with Marcelo 2.4.17 Index: hosts.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/hosts.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- hosts.c 10 Apr 2002 15:32:20 -0000 1.2 +++ hosts.c 10 Jun 2003 01:13:29 -0000 1.3 @@ -170,10 +170,10 @@ list_for_each(hlh, &tmpl->hosts) { host = list_entry(hlh, struct hpsb_host, list); if (host->initialized) { + highlevel_remove_host(host); + host->initialized = 0; abort_requests(host); - - highlevel_remove_host(host); tmpl->release_host(host); while (test_bit(0, &host->timeout_tq.sync)) { Index: ieee1394_core.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/ieee1394_core.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ieee1394_core.c 10 Apr 2002 15:32:20 -0000 1.2 +++ ieee1394_core.c 10 Jun 2003 01:13:29 -0000 1.3 @@ -318,7 +318,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) { - host->node_id = 0xffc0 | phyid; + host->node_id = LOCAL_BUS | phyid; host->in_bus_reset = 0; host->is_root = isroot; Index: nodemgr.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/nodemgr.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- nodemgr.c 10 Apr 2002 15:32:20 -0000 1.1 +++ nodemgr.c 10 Jun 2003 01:13:29 -0000 1.2 @@ -359,7 +359,7 @@ kfree(buf); kfree(envp); if (value != 0) - HPSB_DEBUG("NodeMgr: hotplug policy returned 0x%x", value); + HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value); } #else @@ -369,9 +369,8 @@ { #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled"); -#else - return; #endif + return; } #endif /* CONFIG_HOTPLUG */ @@ -582,13 +581,13 @@ struct hpsb_host *host, nodeid_t nodeid) { struct list_head *lh; + struct unit_directory *ud; - if (ne->nodeid != nodeid) + if (ne->nodeid != nodeid) { HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT, NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid)); - - ne->host = host; - ne->nodeid = nodeid; + ne->nodeid = nodeid; + } if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) nodemgr_process_config_rom (ne, busoptions); @@ -597,8 +596,6 @@ atomic_set(&ne->generation, get_hpsb_generation(ne->host)); list_for_each (lh, &ne->unit_directories) { - struct unit_directory *ud; - ud = list_entry (lh, struct unit_directory, node_list); if (ud->driver != NULL && ud->driver->update != NULL) ud->driver->update(ud); @@ -679,57 +676,76 @@ return; } +/* Used to schedule each nodes config rom probe */ +struct node_probe_task { + nodeid_t nodeid; + struct hpsb_host *host; + atomic_t *count; + struct tq_struct task; +}; + /* This is where we probe the nodes for their information and provided * features. */ -static void nodemgr_node_probe(void *data) +static void nodemgr_node_probe_one(void *__npt) { - struct hpsb_host *host = (struct hpsb_host *)data; - struct selfid *sid = (struct selfid *)host->topology_map; - struct list_head *lh, *next; + struct node_probe_task *npt = (struct node_probe_task *)__npt; struct node_entry *ne; - int nodecount = host->node_count; - nodeid_t nodeid = LOCAL_BUS; quadlet_t buffer[5]; octlet_t guid; - unsigned long flags; /* We need to detect when the ConfigROM's generation has changed, * so we only update the node's info when it needs to be. */ - for (; nodecount; nodecount--, nodeid++, sid++) { - /* Skip extended, and non-active node's */ - while (sid->extended) - sid++; - if (!sid->link_active) - continue; - if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2)) - continue; + if (read_businfo_block (npt->host, npt->nodeid, buffer, sizeof(buffer) >> 2)) + goto probe_complete; - if (buffer[1] != IEEE1394_BUSID_MAGIC) { - /* This isn't a 1394 device */ - HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device", - NODE_BUS_ARGS(nodeid)); - continue; - } + if (buffer[1] != IEEE1394_BUSID_MAGIC) { + /* This isn't a 1394 device */ + HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device", + NODE_BUS_ARGS(npt->nodeid)); + goto probe_complete; + } + + guid = ((u64)buffer[3] << 32) | buffer[4]; + ne = hpsb_guid_get_entry(guid); + + if (!ne) + nodemgr_create_node(guid, buffer[2], npt->host, npt->nodeid); + else + nodemgr_update_node(ne, buffer[2], npt->host, npt->nodeid); + +probe_complete: + atomic_dec(npt->count); + + kfree(npt); + + return; +} - guid = ((u64)buffer[3] << 32) | buffer[4]; - ne = hpsb_guid_get_entry(guid); +static void nodemgr_node_probe_cleanup(void *__npt) +{ + struct node_probe_task *npt = (struct node_probe_task *)__npt; + unsigned long flags; + struct list_head *lh, *next; + struct node_entry *ne; + + /* If things aren't done yet, reschedule ourselves. */ + if (atomic_read(npt->count)) { + schedule_task(&npt->task); + return; + } - if (!ne) - nodemgr_create_node(guid, buffer[2], host, nodeid); - else - nodemgr_update_node(ne, buffer[2], host, nodeid); - } + kfree(npt->count); /* Now check to see if we have any nodes that aren't referenced * any longer. */ - write_lock_irqsave(&node_lock, flags); + write_lock_irqsave(&node_lock, flags); for (lh = node_list.next; lh != &node_list; lh = next) { ne = list_entry(lh, struct node_entry, list); next = lh->next; /* Only checking this host */ - if (ne->host != host) + if (ne->host != npt->host) continue; /* If the generation didn't get updated, then either the @@ -741,9 +757,70 @@ } write_unlock_irqrestore(&node_lock, flags); + kfree(npt); + return; } +static void nodemgr_node_probe(void *__host) +{ + struct hpsb_host *host = (struct hpsb_host *)__host; + int nodecount = host->node_count; + struct selfid *sid = (struct selfid *)host->topology_map; + nodeid_t nodeid = LOCAL_BUS; + struct node_probe_task *npt; + atomic_t *count; + + count = kmalloc(sizeof (*count), GFP_KERNEL); + + if (count == NULL) { + HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe"); + return; + } + + atomic_set(count, 0); + + for (; nodecount; nodecount--, nodeid++, sid++) { + while (sid->extended) + sid++; + if (!sid->link_active || nodeid == host->node_id) + continue; + + npt = kmalloc(sizeof (*npt), GFP_KERNEL); + + if (npt == NULL) { + HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe"); + break; + } + + INIT_TQUEUE(&npt->task, nodemgr_node_probe_one, npt); + npt->host = host; + npt->nodeid = nodeid; + npt->count = count; + + atomic_inc(count); + + schedule_task(&npt->task); + } + + /* Now schedule a task to clean things up after the node probes + * are done. */ + npt = kmalloc (sizeof (*npt), GFP_KERNEL); + + if (npt == NULL) { + HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe"); + return; + } + + INIT_TQUEUE(&npt->task, nodemgr_node_probe_cleanup, npt); + npt->host = host; + npt->nodeid = 0; + npt->count = count; + + schedule_task(&npt->task); + + return; +} struct node_entry *hpsb_guid_get_entry(u64 guid) { @@ -864,7 +941,7 @@ write_unlock_irqrestore(&node_lock, flags); spin_lock_irqsave (&host_info_lock, flags); - list_for_each(lh, &host_info_list) { + list_for_each_safe(lh, next, &host_info_list) { struct host_info *hi = list_entry(lh, struct host_info, list); if (hi->host == host) { list_del(&hi->list); Index: ohci1394.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/ohci1394.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ohci1394.c 10 Apr 2002 15:32:20 -0000 1.2 +++ ohci1394.c 10 Jun 2003 01:13:29 -0000 1.3 @@ -106,16 +106,12 @@ #include <linux/init.h> #ifdef CONFIG_ALL_PPC -#include <asm/feature.h> +#include <asm/machdep.h> +#include <asm/pmac_feature.h> #include <asm/prom.h> #include <asm/pci-bridge.h> #endif -/* Revert to old bus reset algorithm that works on my Pismo until - * the new one is fixed - */ -#undef BUSRESET_WORKAROUND - #include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" @@ -175,7 +171,7 @@ MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl); static char version[] __devinitdata = - "v0.51 08/08/01 Ben Collins <bco...@de...>"; + "$Revision$ Ben Collins <bco...@de...>"; /* Module Parameters */ MODULE_PARM(attempt_root,"i"); @@ -516,12 +512,9 @@ /* After enabling LPS, we need to wait for the connection * between phy and link to be established. This should be * signaled by the LPS bit becoming 1, but this happens - * immediately. Instead we wait for reads from LinkControl to - * give a valid result, i.e. not 0xffffffff. */ - while (reg_read(ohci, OHCI1394_LinkControlSet) == 0xffffffff) { - DBGMSG(ohci->id, "waiting for phy-link connection"); - mdelay(2); - } + * immediately. There seems to be no consistent way to wait + * for this, but 50ms seems to be enough. */ + mdelay(50); /* Set the bus number */ reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); @@ -1131,11 +1124,7 @@ * selfIDComplete interrupt. */ spin_lock_irqsave(&ohci->event_lock, flags); event = reg_read(ohci, OHCI1394_IntEventClear); -#ifdef BUSRESET_WORKAROUND - reg_write(ohci, OHCI1394_IntEventClear, event); -#else reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset); -#endif spin_unlock_irqrestore(&ohci->event_lock, flags); if (!event) return; @@ -1154,11 +1143,17 @@ * selfID phase, so we disable busReset interrupts, to * avoid burying the cpu in interrupt requests. */ spin_lock_irqsave(&ohci->event_lock, flags); -#ifdef BUSRESET_WORKAROUND - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); -#else reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); -#endif + if (ohci->dev->vendor == PCI_VENDOR_ID_APPLE && + ohci->dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) { + udelay(10); + while(reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { + reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); + spin_unlock_irqrestore(&ohci->event_lock, flags); + udelay(10); + spin_lock_irqsave(&ohci->event_lock, flags); + } + } spin_unlock_irqrestore(&ohci->event_lock, flags); if (!host->in_bus_reset) { DBGMSG(ohci->id, "irq_handler: Bus reset requested%s", @@ -1309,12 +1304,10 @@ /* Finally, we clear the busReset event and reenable * the busReset interrupt. */ -#ifndef BUSRESET_WORKAROUND spin_lock_irqsave(&ohci->event_lock, flags); reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); spin_unlock_irqrestore(&ohci->event_lock, flags); -#endif event &= ~OHCI1394_selfIDComplete; } @@ -1966,8 +1959,6 @@ cf_put_keyval(&cr, 0x03, 0x00005e); /* Vendor ID */ cf_put_refer(&cr, 0x81, 2); /* Textual description unit */ cf_put_keyval(&cr, 0x0c, 0x0083c0); /* Node capabilities */ - cf_put_refer(&cr, 0xd1, 3); /* IPv4 unit directory */ - cf_put_refer(&cr, 0xd1, 4); /* IPv6 unit directory */ /* NOTE: Add other unit referers here, and append at bottom */ cf_unit_end(&cr); @@ -1980,46 +1971,6 @@ cf_put_4bytes(&cr, '9', '4', 0x0, 0x0); cf_unit_end(&cr); - /* IPv4 unit directory, RFC 2734 */ - cf_unit_begin(&cr, 3); - cf_put_keyval(&cr, 0x12, 0x00005e); /* Unit spec ID */ - cf_put_refer(&cr, 0x81, 6); /* Textual description unit */ - cf_put_keyval(&cr, 0x13, 0x000001); /* Unit software version */ - cf_put_refer(&cr, 0x81, 7); /* Textual description unit */ - cf_unit_end(&cr); - - cf_unit_begin(&cr, 6); - cf_put_keyval(&cr, 0, 0); - cf_put_1quad(&cr, 0); - cf_put_4bytes(&cr, 'I', 'A', 'N', 'A'); - cf_unit_end(&cr); - - cf_unit_begin(&cr, 7); - cf_put_keyval(&cr, 0, 0); - cf_put_1quad(&cr, 0); - cf_put_4bytes(&cr, 'I', 'P', 'v', '4'); - cf_unit_end(&cr); - - /* IPv6 unit directory, draft-ietf-ipngwg-1394-01.txt */ - cf_unit_begin(&cr, 4); - cf_put_keyval(&cr, 0x12, 0x00005e); /* Unit spec ID */ - cf_put_refer(&cr, 0x81, 8); /* Textual description unit */ - cf_put_keyval(&cr, 0x13, 0x000002); /* (Proposed) Unit software version */ - cf_put_refer(&cr, 0x81, 9); /* Textual description unit */ - cf_unit_end(&cr); - - cf_unit_begin(&cr, 8); - cf_put_keyval(&cr, 0, 0); - cf_put_1quad(&cr, 0); - cf_put_4bytes(&cr, 'I', 'A', 'N', 'A'); - cf_unit_end(&cr); - - cf_unit_begin(&cr, 9); - cf_put_keyval(&cr, 0, 0); - cf_put_1quad(&cr, 0); - cf_put_4bytes(&cr, 'I', 'P', 'v', '6'); - cf_unit_end(&cr); - ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu; } @@ -2309,8 +2260,8 @@ of_node = pci_device_to_OF_node(ohci->dev); if (of_node) { - feature_set_firewire_power(of_node, 0); - feature_set_firewire_cable_power(of_node, 0); + pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0); } } #endif /* CONFIG_ALL_PPC */ @@ -2423,7 +2374,7 @@ name: OHCI1394_DRIVER_NAME, id_table: ohci1394_pci_tbl, probe: ohci1394_add_one, - remove: ohci1394_remove_one, + remove: __devexit_p(ohci1394_remove_one), }; static void __exit ohci1394_cleanup (void) Index: pcilynx.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/pcilynx.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- pcilynx.c 10 Apr 2002 15:32:20 -0000 1.2 +++ pcilynx.c 10 Jun 2003 01:13:30 -0000 1.3 @@ -1637,8 +1637,8 @@ static void __exit pcilynx_cleanup(void) { - pci_unregister_driver(&lynx_pcidriver); hpsb_unregister_lowlevel(&lynx_template); + pci_unregister_driver(&lynx_pcidriver); PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module"); } Index: sbp2.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/sbp2.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- sbp2.c 10 Apr 2002 15:32:20 -0000 1.1 +++ sbp2.c 10 Jun 2003 01:13:30 -0000 1.2 @@ -222,8 +222,25 @@ * when we register our driver. This change * automtically adds hotplug support to the driver. * Kristian Hogsberg <hog...@us...> + * + * 11/17/01 - Various bugfixes/cleanups: + * * Remember to logout of device in sbp2_disconnect. + * * If we fail to reconnect to a device after bus reset + * remember to release unit directory, so the ieee1394 + * knows we no longer manage it. + * * Unregister scsi hosts in sbp2_remove_host when a + * hpsb_host goes away. + * * Remove stupid hack in sbp2_remove_host. + * * Switched to "manual" module initialization + * (i.e. not scsi_module.c) and moved sbp2_cleanup + * moved sbp2scsi_release to sbp2_module_ext. The + * release function is called once pr. registered + * scsi host, but sbp2_cleanup should only be called + * upon module unload. Moved much initialization + * from sbp2scsi_detect to sbp2_module_init. + * Kristian Hogsberg <hog...@us...> */ - + /* @@ -244,6 +261,7 @@ #include <linux/proc_fs.h> #include <linux/blk.h> #include <linux/smp_lock.h> +#include <linux/init.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -395,7 +413,7 @@ * Globals */ -Scsi_Host_Template *global_scsi_tpnt = NULL; +static Scsi_Host_Template scsi_driver_template; static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 }; @@ -671,13 +689,13 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id, struct sbp2scsi_host_info *hi) { - struct list_head *lh; + struct list_head *lh, *next; struct sbp2_command_info *command; unsigned long flags; sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { - list_for_each(lh, &scsi_id->sbp2_command_orb_completed) { + list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) { command = list_entry(lh, struct sbp2_command_info, list); /* Release our generic DMA's */ @@ -868,7 +886,6 @@ hpsb_unregister_highlevel(sbp2_hl_handle); sbp2_hl_handle = NULL; } - return; } static int sbp2_probe(struct unit_directory *ud) @@ -889,8 +906,10 @@ SBP2_DEBUG("sbp2_disconnect"); hi = sbp2_find_host_info(ud->ne->host); - if (hi != NULL) - sbp2_remove_device(hi, scsi_id); + if (hi != NULL) { + sbp2_logout_device(hi, scsi_id); + sbp2_remove_device(hi, scsi_id); + } } static void sbp2_update(struct unit_directory *ud) @@ -909,12 +928,10 @@ */ if (sbp2_login_device(hi, scsi_id)) { - /* Login failed too... so, just mark him as - * unvalidated, so that he gets cleaned up - * later. - */ + /* Login failed too, just remove the device. */ SBP2_ERR("sbp2_reconnect_device failed!"); sbp2_remove_device(hi, scsi_id); + hpsb_release_unit_directory(ud); return; } } @@ -978,7 +995,10 @@ sbp2_spin_unlock(&sbp2_host_info_lock, flags); /* Register our host with the SCSI stack. */ - sbp2scsi_register_scsi_host(hi); + hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *)); + if (hi->scsi_host) + hi->scsi_host->hostdata[0] = (unsigned long)hi; + scsi_driver_template.present++; return; } @@ -1003,13 +1023,12 @@ } /* - * This function is called when the host is removed + * This function is called when a host is removed. */ static void sbp2_remove_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; unsigned long flags; - int i; SBP2_DEBUG("sbp2_remove_host"); @@ -1017,22 +1036,11 @@ hi = sbp2_find_host_info(host); if (hi != NULL) { - /* Here's an annoying hack: we get a disconnect - * callback for each device, so this loop shouldn't be - * necessary. However, the sbp2 driver receives the - * remove_host callback before the nodemgr, so when we - * get the disconnect callback, we've already freed - * the host. Thus, we free the devices here... - */ - for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) { - if (hi->scsi_id[i] != NULL) { - sbp2_logout_device(hi, hi->scsi_id[i]); - sbp2_remove_device(hi, hi->scsi_id[i]); - } - } sbp2util_remove_request_packet_pool(hi); sbp2_host_count--; list_del(&hi->list); + scsi_unregister(hi->scsi_host); + scsi_driver_template.present--; kfree(hi); } else @@ -1203,10 +1211,7 @@ */ if (sbp2_login_device(hi, scsi_id)) { - /* - * Login failed... so, just mark him as unvalidated, so - * that he gets cleaned up later. - */ + /* Login failed, just remove the device. */ SBP2_ERR("sbp2_login_device failed"); sbp2_remove_device(hi, scsi_id); return -EBUSY; @@ -1231,11 +1236,13 @@ } /* - * This function removes (cleans-up after) any unvalidated sbp2 devices + * This function removes an sbp2 device from the sbp2scsi_host_info struct. */ static void sbp2_remove_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) { + SBP2_DEBUG("sbp2_remove_device"); + /* Complete any pending commands with selection timeout */ sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT); @@ -1276,8 +1283,7 @@ SBP2_DMA_FREE("single logout orb"); } - SBP2_DEBUG("Unvalidated SBP-2 device removed, SCSI ID = %d", - scsi_id->id); + SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id); hi->scsi_id[scsi_id->id] = NULL; kfree(scsi_id); } @@ -1381,7 +1387,7 @@ /* * Check status - */ + */ if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { @@ -1687,9 +1693,9 @@ scsi_id->max_payload_size = min(sbp2_speedto_maxrec[scsi_id->speed_code], (u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1)); - SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [0x%02x/%u]", + SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code], - scsi_id->max_payload_size, 1 << ((u32)scsi_id->max_payload_size + 2)); + 1 << ((u32)scsi_id->max_payload_size + 2)); return(0); } @@ -2860,127 +2866,111 @@ return(0); } -/* - * This routine is called at setup (init) and does nothing. Not used here. =) - */ -void sbp2scsi_setup( char *str, int *ints) -{ - SBP2_DEBUG("sbp2scsi_setup"); - return; -} - -/* - * This is our detection routine, and is where we init everything. - */ static int sbp2scsi_detect (Scsi_Host_Template *tpnt) { SBP2_DEBUG("sbp2scsi_detect"); - global_scsi_tpnt = tpnt; + /* + * Call sbp2_init to register with the ieee1394 stack. This + * results in a callback to sbp2_add_host for each ieee1394 + * host controller currently registered, and for each of those + * we register a scsi host with the scsi stack. + */ + sbp2_init(); + + /* We return the number of hosts registered. */ + return sbp2_host_count; +} + +MODULE_AUTHOR("James Goodwin <ja...@fi...>"); +MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); +MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); +MODULE_LICENSE("GPL"); + +/* SCSI host template */ +static Scsi_Host_Template scsi_driver_template = { + name: "IEEE-1394 SBP-2 protocol driver", + detect: sbp2scsi_detect, + queuecommand: sbp2scsi_queuecommand, + abort: sbp2scsi_abort, + reset: sbp2scsi_reset, + bios_param: sbp2scsi_biosparam, + can_queue: SBP2SCSI_MAX_OUTSTANDING_CMDS, + this_id: -1, + sg_tablesize: SBP2_MAX_SG_ELEMENTS, + cmd_per_lun: SBP2SCSI_MAX_CMDS_PER_LUN, + use_clustering: SBP2_CLUSTERING, + emulated: 1, + + module: THIS_MODULE, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,26) - global_scsi_tpnt->proc_name = SBP2_DEVICE_NAME; + proc_name: SBP2_DEVICE_NAME #endif +}; + +static int sbp2_module_init(void) +{ + SBP2_DEBUG("sbp2_module_init"); + /* * Module load option for force one command at a time */ if (serialize_io) { SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)"); - global_scsi_tpnt->can_queue = 1; - global_scsi_tpnt->cmd_per_lun = 1; + scsi_driver_template.can_queue = 1; + scsi_driver_template.cmd_per_lun = 1; } /* - * Module load option to limit max size of requests from the scsi drivers + * Module load option to limit max size of requests from the + * scsi drivers */ if (no_large_packets) { - SBP2_ERR("Driver forced to limit max transfer size (no_large_packets = 1)"); - global_scsi_tpnt->sg_tablesize = 0x1f; - global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING; + SBP2_ERR("Driver forced to limit max transfer size " + "(no_large_packets = 1)"); + scsi_driver_template.sg_tablesize = 0x1f; + scsi_driver_template.use_clustering = DISABLE_CLUSTERING; } if (mode_sense_hack) { SBP2_ERR("Mode sense emulation enabled (mode_sense_hack = 1)"); } - sbp2_init(); - - if (!sbp2_host_count) { - SBP2_ERR("Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2..."); + /* + * Ideally we would register our scsi_driver_template with the + * scsi stack and after that register with the ieee1394 stack + * and process the add_host callbacks. However, the detect + * function in the scsi host template requires that we find at + * least one host, so we "nest" the registrations by calling + * sbp2_init from the detect function. + */ + if (scsi_register_module(MODULE_SCSI_HA, &scsi_driver_template) || + !scsi_driver_template.present) { + SBP2_ERR("Please load the lower level IEEE-1394 driver " + "(e.g. ohci1394) before sbp2..."); sbp2_cleanup(); + return -ENODEV; } - /* - * Since we are returning this count, it means that sbp2 must be - * loaded "after" the host adapter module... - */ - return(sbp2_host_count); + return 0; } -/* - * This function is called from sbp2_add_host, and is where we register - * our scsi host - */ -static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi) +static void __exit sbp2_module_exit(void) { - struct Scsi_Host *shpnt = NULL; - - SBP2_DEBUG("sbp2scsi_register_scsi_host"); - SBP2_DEBUG("sbp2scsi_host_info = %p", hi); + SBP2_DEBUG("sbp2_module_exit"); /* - * Let's register with the scsi stack + * On module unload we unregister with the ieee1394 stack + * which results in remove_host callbacks for all ieee1394 + * host controllers. In the callbacks we unregister the + * corresponding scsi hosts. */ - if (global_scsi_tpnt) { - - shpnt = scsi_register (global_scsi_tpnt, sizeof(void *)); - - /* - * If successful, save off a context (to be used when SCSI - * commands are received) - */ - if (shpnt) { - shpnt->hostdata[0] = (unsigned long)hi; - } - } - - return; -} - -/* Called when our module is released */ -static int sbp2scsi_release(struct Scsi_Host *host) -{ - SBP2_DEBUG("sbp2scsi_release"); sbp2_cleanup(); - return(0); -} -/* Called for contents of procfs */ -static const char *sbp2scsi_info (struct Scsi_Host *host) -{ - return "IEEE-1394 SBP-2 protocol driver"; + if (scsi_unregister_module(MODULE_SCSI_HA, &scsi_driver_template)) + SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver"); } -MODULE_AUTHOR("James Goodwin <ja...@fi...>"); -MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); -MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); -MODULE_LICENSE("GPL"); - -/* SCSI host template */ -static Scsi_Host_Template driver_template = { - name: "IEEE1394 SBP-2", - detect: sbp2scsi_detect, - release: sbp2scsi_release, - info: sbp2scsi_info, - queuecommand: sbp2scsi_queuecommand, - abort: sbp2scsi_abort, - reset: sbp2scsi_reset, - bios_param: sbp2scsi_biosparam, - can_queue: SBP2SCSI_MAX_OUTSTANDING_CMDS, - this_id: -1, - sg_tablesize: SBP2_MAX_SG_ELEMENTS, - cmd_per_lun: SBP2SCSI_MAX_CMDS_PER_LUN, - use_clustering: SBP2_CLUSTERING, - emulated: 1 -}; - -#include "../scsi/scsi_module.c" +module_init(sbp2_module_init); +module_exit(sbp2_module_exit); Index: sbp2.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/sbp2.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- sbp2.h 10 Apr 2002 15:32:20 -0000 1.1 +++ sbp2.h 10 Jun 2003 01:13:31 -0000 1.2 @@ -403,6 +403,13 @@ spinlock_t sbp2_request_packet_lock; /* + * This is the scsi host we register with the scsi mid level. + * We keep a reference to it here, so we can unregister it + * when the hpsb_host is removed. + */ + struct Scsi_Host *scsi_host; + + /* * Lists keeping track of inuse/free sbp2_request_packets. These structures are * used for sending out sbp2 command and agent reset packets. We initially create * a pool of request packets so that we don't have to do any kmallocs while in critical @@ -498,7 +505,6 @@ /* * Scsi interface related prototypes */ -static const char *sbp2scsi_info (struct Scsi_Host *host); static int sbp2scsi_detect (Scsi_Host_Template *tpnt); void sbp2scsi_setup(char *str, int *ints); static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); @@ -509,6 +515,5 @@ u32 status); static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); -static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi); #endif /* SBP2_H */ Index: video1394.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/video1394.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- video1394.c 10 Apr 2002 15:32:20 -0000 1.2 +++ video1394.c 10 Jun 2003 01:13:31 -0000 1.3 @@ -47,6 +47,8 @@ #include <linux/types.h> #include <linux/wrapper.h> #include <linux/vmalloc.h> +#include <linux/timex.h> +#include <linux/mm.h> #include "ieee1394.h" #include "ieee1394_types.h" @@ -95,6 +97,7 @@ struct dma_cmd **ir_prg; struct it_dma_prg **it_prg; unsigned int *buffer_status; + struct timeval *buffer_time; /* time when the buffer was received */ unsigned int *last_used_cmd; /* For ISO Transmit with variable sized packets only ! */ int ctrlClear; @@ -102,8 +105,8 @@ int cmdPtr; int ctxMatch; wait_queue_head_t waitq; - spinlock_t lock; - unsigned int syt_offset; + spinlock_t lock; + unsigned int syt_offset; int flags; }; @@ -304,6 +307,8 @@ if ((*d)->buffer_status) kfree((*d)->buffer_status); + if ((*d)->buffer_time) + kfree((*d)->buffer_time); if ((*d)->last_used_cmd) kfree((*d)->last_used_cmd); if ((*d)->next_buffer) @@ -437,6 +442,8 @@ d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int), GFP_KERNEL); + d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval), + GFP_KERNEL); d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int), GFP_KERNEL); d->next_buffer = kmalloc(d->num_desc * sizeof(int), @@ -447,6 +454,11 @@ free_dma_iso_ctx(&d); return NULL; } + if (d->buffer_time == NULL) { + PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_time"); + free_dma_iso_ctx(&d); + return NULL; + } if (d->last_used_cmd == NULL) { PRINT(KERN_ERR, ohci->id, "Failed to allocate last_used_cmd"); free_dma_iso_ctx(&d); @@ -458,6 +470,7 @@ return NULL; } memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int)); + memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval)); memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int)); memset(d->next_buffer, -1, d->num_desc * sizeof(int)); @@ -604,6 +617,7 @@ if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) { reset_ir_status(d, i); d->buffer_status[i] = VIDEO1394_BUFFER_READY; + get_fast_time(&d->buffer_time[i]); } } spin_unlock(&d->lock); @@ -876,9 +890,23 @@ if(copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; + + /* if channel < 0, find lowest available one */ + if (v.channel < 0) { + mask = (u64)0x1; + for (i=0; i<ISO_CHANNELS; i++) { + if (!(ohci->ISO_channel_usage & mask)) { + v.channel = i; + PRINT(KERN_INFO, ohci->id, "Found free channel %d\n", i); + break; + } + mask = mask << 1; + } + } + if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { PRINT(KERN_ERR, ohci->id, - "Iso channel %d out of bound", v.channel); + "Iso channel %d out of bounds", v.channel); return -EFAULT; } mask = (u64)0x1<<v.channel; @@ -1092,6 +1120,7 @@ } case VIDEO1394_LISTEN_WAIT_BUFFER: + case VIDEO1394_LISTEN_POLL_BUFFER: { struct video1394_wait v; struct dma_iso_ctx *d; @@ -1120,6 +1149,12 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; break; case VIDEO1394_BUFFER_QUEUED: + if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) { + /* for polling, return error code EINTR */ + spin_unlock_irqrestore(&d->lock, flags); + return -EINTR; + } + #if 1 while(d->buffer_status[v.buffer]!= VIDEO1394_BUFFER_READY) { @@ -1147,6 +1182,10 @@ return -EFAULT; } + /* set time of buffer */ + v.filltime = d->buffer_time[v.buffer]; +// printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec); + /* * Look ahead to see how many more buffers have been received */ @@ -1596,7 +1635,8 @@ { struct ti_ohci *ohci; unsigned long flags; - struct list_head *lh; + struct list_head *lh, *next; + struct video_card *p; /* We only work with the OHCI-1394 driver */ if (strcmp(host->template->name, OHCI1394_DRIVER_NAME)) @@ -1605,14 +1645,11 @@ ohci = (struct ti_ohci *)host->hostdata; spin_lock_irqsave(&video1394_cards_lock, flags); - if (!list_empty(&video1394_cards)) { - struct video_card *p; - list_for_each(lh, &video1394_cards) { - p = list_entry(lh, struct video_card, list); - if (p ->ohci == ohci) { - remove_card(p); - break; - } + list_for_each_safe(lh, next, &video1394_cards) { + p = list_entry(lh, struct video_card, list); + if (p->ohci == ohci) { + remove_card(p); + break; } } spin_unlock_irqrestore(&video1394_cards_lock, flags); @@ -1652,7 +1689,7 @@ devfs_unregister(devfs_handle); devfs_unregister_chrdev(VIDEO1394_MAJOR, VIDEO1394_DRIVER_NAME); - PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module\n"); + PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); } static int __init video1394_init_module (void) @@ -1678,6 +1715,7 @@ return -ENOMEM; } + PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module"); return 0; } Index: video1394.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/ieee1394/video1394.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- video1394.h 10 Apr 2002 15:32:20 -0000 1.2 +++ video1394.h 10 Jun 2003 01:13:32 -0000 1.3 @@ -35,11 +35,12 @@ VIDEO1394_LISTEN_CHANNEL = 0, VIDEO1394_UNLISTEN_CHANNEL, VIDEO1394_LISTEN_QUEUE_BUFFER, - VIDEO1394_LISTEN_WAIT_BUFFER, + VIDEO1394_LISTEN_WAIT_BUFFER, // wait until buffer is ready VIDEO1394_TALK_CHANNEL, VIDEO1394_UNTALK_CHANNEL, VIDEO1394_TALK_QUEUE_BUFFER, - VIDEO1394_TALK_WAIT_BUFFER + VIDEO1394_TALK_WAIT_BUFFER, + VIDEO1394_LISTEN_POLL_BUFFER // return immediately with -EINTR if not ready }; #define VIDEO1394_SYNC_FRAMES 0x00000001 @@ -47,7 +48,7 @@ #define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004 struct video1394_mmap { - unsigned int channel; + int channel; /* -1 to find an open channel in LISTEN/TALK */ unsigned int sync_tag; unsigned int nb_buffers; unsigned int buf_size; @@ -69,6 +70,7 @@ struct video1394_wait { unsigned int channel; unsigned int buffer; + struct timeval filltime; /* time of buffer full */ }; |