Commit 3ed2969b authored by Ben Collins's avatar Ben Collins

[PATCH] IEEE1394/Firewire updates

- Workaround possible reset loop trying to get IRM sanity
- Logical Unit DIrectory (LUN) support for sbp2(scsi) devices.
- Fix hostnum allocation.
- Whitespace and formatting sync with 2.4 branch.
- Make pcilynx return IRQ_NONE for no interrupts to handle.
parent 83e410b8
...@@ -20,4 +20,4 @@ clean-files := oui.c ...@@ -20,4 +20,4 @@ clean-files := oui.c
$(obj)/oui.o: $(obj)/oui.c $(obj)/oui.o: $(obj)/oui.c
$(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh $(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh
$(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c $(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $@
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/byteorder.h>
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "ieee1394.h" #include "ieee1394.h"
...@@ -48,6 +47,7 @@ static char *nodemgr_find_oui_name(int oui) ...@@ -48,6 +47,7 @@ static char *nodemgr_find_oui_name(int oui)
return NULL; return NULL;
} }
/* /*
* Basically what we do here is start off retrieving the bus_info block. * Basically what we do here is start off retrieving the bus_info block.
* From there will fill in some info about the node, verify it is of IEEE * From there will fill in some info about the node, verify it is of IEEE
...@@ -594,7 +594,6 @@ static int nodemgr_read_text_leaf(struct node_entry *ne, ...@@ -594,7 +594,6 @@ static int nodemgr_read_text_leaf(struct node_entry *ne,
ret = -ENXIO; ret = -ENXIO;
for (; size > 0; size--, address += 4, quadp++) { for (; size > 0; size--, address += 4, quadp++) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
ret = hpsb_node_read(ne, address, quadp, 4); ret = hpsb_node_read(ne, address, quadp, 4);
if (ret != -EAGAIN) if (ret != -EAGAIN)
break; break;
...@@ -638,7 +637,6 @@ static struct node_entry *nodemgr_scan_root_directory ...@@ -638,7 +637,6 @@ static struct node_entry *nodemgr_scan_root_directory
code = CONFIG_ROM_KEY(quad); code = CONFIG_ROM_KEY(quad);
if (code == CONFIG_ROM_VENDOR_ID && length > 0) { if (code == CONFIG_ROM_VENDOR_ID && length > 0) {
/* Check if there is a text descriptor leaf /* Check if there is a text descriptor leaf
immediately after this. */ immediately after this. */
size = nodemgr_size_text_leaf(host, nodeid, generation, size = nodemgr_size_text_leaf(host, nodeid, generation,
...@@ -847,7 +845,7 @@ static struct unit_directory *nodemgr_scan_unit_directory ...@@ -847,7 +845,7 @@ static struct unit_directory *nodemgr_scan_unit_directory
store? Only count immediate values and store? Only count immediate values and
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 & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
count++; count++;
break; break;
} }
...@@ -894,20 +892,21 @@ static struct unit_directory *nodemgr_scan_unit_directory ...@@ -894,20 +892,21 @@ static struct unit_directory *nodemgr_scan_unit_directory
/* This implementation currently only scans the config rom and its /* This implementation currently only scans the config rom and its
* immediate unit directories looking for software_id and * immediate unit directories looking for software_id and
* software_version entries, in order to get driver autoloading working. */ * software_version entries, in order to get driver autoloading working. */
static void nodemgr_process_unit_directory(struct host_info *hi, struct node_entry *ne, static struct unit_directory *nodemgr_process_unit_directory
octlet_t address, unsigned int id) (struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int *id)
{ {
struct unit_directory *ud; struct unit_directory *ud;
quadlet_t quad; quadlet_t quad;
quadlet_t *infop; quadlet_t *infop;
int length; int length;
struct unit_directory *ud_temp = NULL;
if (!(ud = nodemgr_scan_unit_directory(ne, address))) if (!(ud = nodemgr_scan_unit_directory(ne, address)))
goto unit_directory_error; goto unit_directory_error;
ud->ne = ne; ud->ne = ne;
ud->address = address; ud->address = address;
ud->id = id; ud->id = (*id)++;
if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
address, &quad)) address, &quad))
...@@ -983,12 +982,48 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent ...@@ -983,12 +982,48 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent
/* TODO: read strings... icons? */ /* TODO: read strings... icons? */
break; break;
case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY:
/* TODO: Parent this with it's UD */
ud_temp = nodemgr_process_unit_directory(hi, ne, address + value * 4, id);
/* inherit unspecified values */
if (ud_temp != NULL)
{
if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
!(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
{
ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID;
ud_temp->vendor_id = ud->vendor_id;
ud_temp->vendor_oui = ud->vendor_oui;
}
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
!(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
{
ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID;
ud_temp->model_id = ud->model_id;
}
if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
!(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
{
ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
ud_temp->specifier_id = ud->specifier_id;
}
if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
!(ud_temp->flags & UNIT_DIRECTORY_VERSION))
{
ud_temp->flags |= UNIT_DIRECTORY_VERSION;
ud_temp->version = ud->version;
}
}
break;
default: default:
/* Which types of quadlets do we want to /* Which types of quadlets do we want to
store? Only count immediate values and store? Only count immediate values and
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 & CONFIG_ROM_KEY_TYPE_LEAF) == 0)
*infop++ = quad; *infop++ = quad;
break; break;
} }
...@@ -1006,11 +1041,12 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent ...@@ -1006,11 +1041,12 @@ static void nodemgr_process_unit_directory(struct host_info *hi, struct node_ent
device_create_file(&ud->device, &dev_attr_ud_vendor_oui); device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
nodemgr_create_ud_dev_files(ud); nodemgr_create_ud_dev_files(ud);
return; return ud;
unit_directory_error: unit_directory_error:
if (ud != NULL) if (ud != NULL)
kfree(ud); kfree(ud);
return NULL;
} }
...@@ -1071,7 +1107,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent ...@@ -1071,7 +1107,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
break; break;
case CONFIG_ROM_UNIT_DIRECTORY: case CONFIG_ROM_UNIT_DIRECTORY:
nodemgr_process_unit_directory(hi, ne, address + value * 4, ud_id++); nodemgr_process_unit_directory(hi, ne, address + value * 4, &ud_id);
break; break;
case CONFIG_ROM_DESCRIPTOR_LEAF: case CONFIG_ROM_DESCRIPTOR_LEAF:
...@@ -1137,6 +1173,9 @@ static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, ...@@ -1137,6 +1173,9 @@ static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp,
#endif /* CONFIG_HOTPLUG */ #endif /* CONFIG_HOTPLUG */
static DECLARE_MUTEX(host_num_sema);
/* Must hold above mutex until the result of the below call is assigned to
* a hostinfo entry. */
static int nodemgr_alloc_host_num(void) static int nodemgr_alloc_host_num(void)
{ {
int hostnum; int hostnum;
...@@ -1156,6 +1195,18 @@ int hpsb_register_protocol(struct hpsb_protocol_driver *driver) ...@@ -1156,6 +1195,18 @@ int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
/* /*
* Right now registration always succeeds, but maybe we should * Right now registration always succeeds, but maybe we should
* detect clashes in protocols handled by other drivers. * detect clashes in protocols handled by other drivers.
* DRD> No because multiple drivers are needed to handle certain devices.
* For example, a DV camera is an IEC 61883 device (dv1394) and AV/C (raw1394).
* This will become less an issue with libiec61883 using raw1394.
*
* BenC: But can we handle this with an ALLOW_SHARED flag for a
* protocol? When we get an SBP-3 driver, it will be nice if they were
* mutually exclusive, since SBP-3 can handle SBP-2 protocol.
*
* Not to mention that we currently do not seem to support multiple
* drivers claiming the same unitdirectory. If we implement both of
* those, then we'll need to keep probing when a driver claims a
* unitdirectory, but is sharable.
*/ */
return 0; return 0;
...@@ -1434,9 +1485,9 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1434,9 +1485,9 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
/* If we had a bus reset while we were scanning the bus, it is /* If we had a bus reset while we were scanning the bus, it is
* possible that we did not probe all nodes. In that case, we * possible that we did not probe all nodes. In that case, we
* skip the clean up for now, since we could remove nodes that * skip the clean up for now, since we could remove nodes that
* were still on the bus. The bus reset increased * were still on the bus. The bus reset increased hi->reset_sem,
* hi->reset_sem, so there's a bus scan pending which will do * so there's a bus scan pending which will do the clean up
* the clean up eventually. */ * eventually. */
if (generation == get_hpsb_generation(host)) { if (generation == get_hpsb_generation(host)) {
struct cleanup_baton cleanup; struct cleanup_baton cleanup;
...@@ -1470,7 +1521,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1470,7 +1521,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). Other IRM responsibilities go in here as well. */ * 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;
...@@ -1489,12 +1540,12 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host) ...@@ -1489,12 +1540,12 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host)
/* If there is no bus manager then we should set the root node's /* If there is no bus manager then we should set the root node's
* force_root bit to promote bus stability per the 1394 * force_root bit to promote bus stability per the 1394
* spec. (8.4.2.6) */ * spec. (8.4.2.6) */
if(host->busmgr_id == 0x3f && host->node_count > 1) if (host->busmgr_id == 0x3f && host->node_count > 1)
{ {
u16 root_node = host->node_count - 1; u16 root_node = host->node_count - 1;
struct node_entry *ne = hpsb_nodeid_get_entry(host, root_node); struct node_entry *ne = hpsb_nodeid_get_entry(host, root_node);
if(ne->busopt.cmc) if (ne->busopt.cmc)
hpsb_send_phy_config(host, root_node, -1); hpsb_send_phy_config(host, root_node, -1);
else { else {
HPSB_DEBUG("The root node is not cycle master capable; " HPSB_DEBUG("The root node is not cycle master capable; "
...@@ -1508,7 +1559,7 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host) ...@@ -1508,7 +1559,7 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host)
/* 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_irm_capability(struct hpsb_host *host) static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
{ {
quadlet_t bc; quadlet_t bc;
int status; int status;
...@@ -1525,10 +1576,19 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host) ...@@ -1525,10 +1576,19 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host)
/* The current irm 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("Current remote IRM is not 1394a-2000 compliant, resetting..."); HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting...");
if (cycles >= 5) {
/* Oh screw it! Just leave the bus as it is */
HPSB_DEBUG("Stopping reset loop for IRM sanity");
return 1;
}
hpsb_send_phy_config(host, host->node_id, -1); 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;
} }
return 1; return 1;
} }
...@@ -1536,6 +1596,7 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1536,6 +1596,7 @@ static int nodemgr_host_thread(void *__hi)
{ {
struct host_info *hi = (struct host_info *)__hi; struct host_info *hi = (struct host_info *)__hi;
struct hpsb_host *host = hi->host; struct hpsb_host *host = hi->host;
int reset_cycles = 0;
/* No userlevel access needed */ /* No userlevel access needed */
daemonize(hi->daemon_name); daemonize(hi->daemon_name);
...@@ -1571,12 +1632,14 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1571,12 +1632,14 @@ static int nodemgr_host_thread(void *__hi)
i = HZ/4; i = HZ/4;
} }
if (!nodemgr_check_irm_capability(host)) { if (!nodemgr_check_irm_capability(host, reset_cycles++)) {
/* Do nothing, we are resetting */ /* Do nothing, we are resetting */
up(&nodemgr_serialize); up(&nodemgr_serialize);
continue; continue;
} }
reset_cycles = 0;
nodemgr_node_probe(hi, generation); nodemgr_node_probe(hi, generation);
nodemgr_do_irm_duties(host); nodemgr_do_irm_duties(host);
...@@ -1588,7 +1651,7 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1588,7 +1651,7 @@ static int nodemgr_host_thread(void *__hi)
caught_signal: caught_signal:
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name); HPSB_DEBUG ("NodeMgr: Exiting thread");
#endif #endif
complete_and_exit(&hi->exited, 0); complete_and_exit(&hi->exited, 0);
...@@ -1672,25 +1735,28 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr, ...@@ -1672,25 +1735,28 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr,
static void nodemgr_add_host(struct hpsb_host *host, struct hpsb_highlevel *hl) static void nodemgr_add_host(struct hpsb_host *host, struct hpsb_highlevel *hl)
{ {
struct host_info *hi; struct host_info *hi;
int id;
down(&host_num_sema);
/* Must be called before we create the hostinfo entry, else it
* will match entry '0' since all keys default to zero */
id = nodemgr_alloc_host_num();
hi = hpsb_create_hostinfo(hl, host, sizeof(*hi)); hi = hpsb_create_hostinfo(hl, host, sizeof(*hi));
if (!hi) { if (!hi) {
up(&host_num_sema);
HPSB_ERR ("NodeMgr: out of memory in add host"); HPSB_ERR ("NodeMgr: out of memory in add host");
return; return;
} }
/* Initialize the hostinfo here and start the thread. The hi->id = id;
* thread blocks on the reset semaphore until a bus reset hpsb_set_hostinfo_key(hl, host, hi->id);
* happens. */ up(&host_num_sema);
hi->host = host; hi->host = host;
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();
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;
...@@ -1756,7 +1822,7 @@ void init_ieee1394_nodemgr(void) ...@@ -1756,7 +1822,7 @@ void init_ieee1394_nodemgr(void)
{ {
bus_register(&ieee1394_bus_type); bus_register(&ieee1394_bus_type);
nodemgr_hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); nodemgr_hl = hpsb_register_highlevel("Node manager", &nodemgr_ops);
if (!nodemgr_hl) { if (!nodemgr_hl) {
HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization");
} }
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#define CONFIG_ROM_MODEL_ID 0x17 #define CONFIG_ROM_MODEL_ID 0x17
#define CONFIG_ROM_NODE_CAPABILITES 0x0C #define CONFIG_ROM_NODE_CAPABILITES 0x0C
#define CONFIG_ROM_UNIT_DIRECTORY 0xd1 #define CONFIG_ROM_UNIT_DIRECTORY 0xd1
#define CONFIG_ROM_LOGICAL_UNIT_DIRECTORY 0xd4
#define CONFIG_ROM_SPECIFIER_ID 0x12 #define CONFIG_ROM_SPECIFIER_ID 0x12
#define CONFIG_ROM_UNIT_SW_VERSION 0x13 #define CONFIG_ROM_UNIT_SW_VERSION 0x13
#define CONFIG_ROM_DESCRIPTOR_LEAF 0x81 #define CONFIG_ROM_DESCRIPTOR_LEAF 0x81
...@@ -137,8 +138,7 @@ struct node_entry { ...@@ -137,8 +138,7 @@ struct node_entry {
const char *vendor_name; const char *vendor_name;
const char *vendor_oui; const char *vendor_oui;
u32 capabilities; u32 capabilities;
struct hpsb_tlabel_pool *tpool; struct hpsb_tlabel_pool *tpool;
struct device device; struct device device;
......
...@@ -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: 897 $ Ben Collins <bcollins@debian.org>"; "$Rev: 902 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
static int phys_dma = 1; static int phys_dma = 1;
......
...@@ -1175,7 +1175,7 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id, ...@@ -1175,7 +1175,7 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id,
intmask = reg_read(lynx, PCI_INT_STATUS); intmask = reg_read(lynx, PCI_INT_STATUS);
if (!(intmask & PCI_INT_INT_PEND)) if (!(intmask & PCI_INT_INT_PEND))
return IRQ_HANDLED; return IRQ_NONE;
PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask, PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask,
linkint); linkint);
......
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