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 */
};
|