linux1394-cvslog Mailing List for IEEE 1394 for Linux (Page 2)
Brought to you by:
aeb,
bencollins
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(10) |
Jul
(12) |
Aug
(8) |
Sep
(9) |
Oct
(4) |
Nov
(5) |
Dec
(5) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(7) |
Feb
(3) |
Mar
(15) |
Apr
(12) |
May
(5) |
Jun
(9) |
Jul
(32) |
Aug
(39) |
Sep
(42) |
Oct
(22) |
Nov
(28) |
Dec
(8) |
2002 |
Jan
(37) |
Feb
(47) |
Mar
(6) |
Apr
(29) |
May
(33) |
Jun
(9) |
Jul
(28) |
Aug
(30) |
Sep
(15) |
Oct
(75) |
Nov
(37) |
Dec
(31) |
2003 |
Jan
|
Feb
(89) |
Mar
(41) |
Apr
(13) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: SVN U. <ben...@li...> - 2003-03-12 02:44:54
|
Author: bencollins Date: 2003-03-11 21:44:04 -0500 (Tue, 11 Mar 2003) New Revision: 836 Modified: trunk/TODO trunk/nodemgr.c trunk/nodemgr.h Log: Convert over to using guid as the node. Handle rescan's and node changes better. Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-11 21:44:05.000000000 -0500 @@ -31,9 +31,14 @@ #include "nodemgr.h" -/* Shitty part is, 0x0 can just mean it wasn't set, but that matches an - * OUI entry. We don't want that, so we take a chance and never match 0x0. - * Sorry XEROX. */ +#if 1 +#define FW_BUS_ID_FMT "%012Lx" +#define FW_BUS_ID_ARGS(__hi, __ne) (unsigned long long)__ne->guid & 0xffffffffffff +#else +#define FW_BUS_ID_FMT "%d-" NODE_BUS_FMT +#define FW_BUS_ID_ARGS(__hi, __ne) __hi->id, NODE_BUS_ARGS(__ne->nodeid) +#endif + static char *nodemgr_find_oui_name(int oui) { #ifdef CONFIG_IEEE1394_OUI_DB @@ -43,7 +48,7 @@ } oui_list[]; int i; - for (i = 1; oui_list[i].name; i++) + for (i = 0; oui_list[i].name; i++) if (oui_list[i].oui == oui) return oui_list[i].name; #endif @@ -153,15 +158,20 @@ static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_show_ne_tlabels_mask,NULL); -fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n") fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n") -fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n") fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n") + +fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n") fw_attr(ne, struct node_entry, vendor_name, const char *, "%s\n") -fw_attr(ne, struct node_entry, oui_name, const char *, "%s\n") +fw_attr(ne, struct node_entry, vendor_oui, const char *, "%s\n") + +fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n") +fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n") +fw_attr(ne, struct node_entry, guid_vendor_oui, const char *, "%s\n") static struct device_attribute *const fw_ne_attrs[] = { &dev_attr_ne_guid, + &dev_attr_ne_guid_vendor_id, &dev_attr_ne_capabilities, &dev_attr_ne_vendor_id, &dev_attr_ne_nodeid, @@ -175,12 +185,13 @@ fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n") fw_attr(ud, struct unit_directory, length, int, "%d\n") -/* These are all dependent on if the value is preovided */ +/* These are all dependent on the value being provided */ fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, vendor_name, const char *, "%s\n") +fw_attr(ud, struct unit_directory, vendor_oui, const char *, "%s\n") fw_attr(ud, struct unit_directory, model_name, const char *, "%s\n") static struct device_attribute *const fw_ud_attrs[] = { @@ -401,8 +412,9 @@ } -static void nodemgr_remove_ud(struct device *dev) +static void nodemgr_remove_ud(struct unit_directory *ud) { + struct device *dev = &ud->device; int i; for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) @@ -412,6 +424,7 @@ device_remove_file(dev, &dev_attr_ud_version); device_remove_file(dev, &dev_attr_ud_vendor_id); device_remove_file(dev, &dev_attr_ud_vendor_name); + device_remove_file(dev, &dev_attr_ud_vendor_oui); device_remove_file(dev, &dev_attr_ud_model_id); device_remove_file(dev, &dev_attr_ud_model_name); @@ -419,17 +432,46 @@ } -static void nodemgr_remove_ne(struct device *dev) +static void nodemgr_remove_node_uds(struct node_entry *ne) { - int i; struct list_head *lh, *next; - list_for_each_safe(lh, next, &dev->children) - nodemgr_remove_ud(list_to_dev(lh)); + list_for_each_safe(lh, next, &ne->device.children) { + struct unit_directory *ud; + ud = container_of(list_to_dev(lh), struct unit_directory, device); + nodemgr_remove_ud(ud); + } +} + + +static void nodemgr_update_ud_names(struct host_info *hi, struct node_entry *ne) +{ + struct list_head *lh; + + list_for_each(lh, &ne->device.children) { + struct unit_directory *ud; + ud = container_of(list_to_dev(lh), struct unit_directory, device); + + sprintf(ud->device.name, "IEEE-1394 unit directory %d-" NODE_BUS_FMT "-%u", + hi->id, NODE_BUS_ARGS(ne->nodeid), ud->id); + } +} + + +static void nodemgr_remove_ne(struct node_entry *ne) +{ + struct device *dev = &ne->device; + int i; + + nodemgr_remove_node_uds(ne); for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) device_remove_file(dev, fw_ne_attrs[i]); + device_remove_file(dev, &dev_attr_ne_guid_vendor_oui); + device_remove_file(dev, &dev_attr_ne_vendor_name); + device_remove_file(dev, &dev_attr_ne_vendor_oui); + device_unregister(dev); } @@ -440,14 +482,9 @@ struct list_head *lh, *next; list_for_each_safe(lh, next, &dev->children) { - struct device *child_dev = list_to_dev(lh); struct node_entry *ne; - - ne = container_of(child_dev, struct node_entry, device); - /* Force free'ing of ne struct aswell */ - ne->device.release = nodemgr_release_ne; - - nodemgr_remove_ne(child_dev); + ne = container_of(list_to_dev(lh), struct node_entry, device); + nodemgr_remove_ne(ne); } for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) @@ -467,6 +504,7 @@ static struct device nodemgr_dev_template_ne = { .bus = &ieee1394_bus_type, + .release = nodemgr_release_ne, .class_num = DEV_CLASS_NODE, }; @@ -622,8 +660,7 @@ memset(ne, 0, total_size); if (size != 0) { - ne->vendor_name - = (const char *) &(ne->quadlets[2]); + ne->vendor_name = (const char *) &(ne->quadlets[2]); ne->quadlets[size] = 0; } else { ne->vendor_name = NULL; @@ -650,15 +687,30 @@ ne->host = host; ne->nodeid = nodeid; - ne->guid = guid; ne->generation = generation; + ne->guid = guid; + ne->guid_vendor_id = (guid >> 40) & 0xffffff; + ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id); + memcpy(&ne->device, &nodemgr_dev_template_ne, sizeof(ne->device)); ne->device.parent = &host->device; + snprintf(ne->device.bus_id, BUS_ID_SIZE, FW_BUS_ID_FMT, + FW_BUS_ID_ARGS(hi, ne)); + sprintf(ne->device.name, "IEEE-1394 device %d-" NODE_BUS_FMT, + hi->id, NODE_BUS_ARGS(ne->nodeid)); + + device_register(&ne->device); + + if (ne->guid_vendor_oui) + device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui); + nodemgr_create_ne_dev_files(ne); nodemgr_process_config_rom (hi, ne, busoptions); + nodemgr_update_ud_names(hi, ne); + HPSB_DEBUG("%s added: ID:BUS[%d-" NODE_BUS_FMT "] GUID[%016Lx]", (host->node_id == nodeid) ? "Host" : "Node", hi->id, NODE_BUS_ARGS(nodeid), (unsigned long long)guid); @@ -842,7 +894,7 @@ /* This implementation currently only scans the config rom and its * immediate unit directories looking for software_id and * software_version entries, in order to get driver autoloading working. */ -static void nodemgr_process_unit_directory(struct node_entry *ne, +static void nodemgr_process_unit_directory(struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int id) { struct unit_directory *ud; @@ -879,6 +931,10 @@ case CONFIG_ROM_VENDOR_ID: ud->vendor_id = value; ud->flags |= UNIT_DIRECTORY_VENDOR_ID; + + if (ud->vendor_id) + ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id); + if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) { length--; address += 4; @@ -941,10 +997,13 @@ memcpy(&ud->device, &nodemgr_dev_template_ud, sizeof(ud->device)); ud->device.parent = &ne->device; - sprintf(ud->device.bus_id, "%s-%u", ne->device.bus_id, ud->id); - sprintf(ud->device.name, "IEEE-1394 unit directory %s", ud->device.bus_id); + snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", + ne->device.bus_id, ud->id); + + device_register(&ud->device); - device_register(&ud->device); + if (ud->vendor_oui) + device_create_file(&ud->device, &dev_attr_ud_vendor_oui); nodemgr_create_ud_dev_files(ud); return; @@ -982,7 +1041,7 @@ return; } -static void nodemgr_process_root_directory(struct node_entry *ne) +static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne) { octlet_t address; quadlet_t quad; @@ -1015,9 +1074,8 @@ case CONFIG_ROM_VENDOR_ID: ne->vendor_id = value; - ne->oui_name = nodemgr_find_oui_name(value); - if (ne->oui_name) - device_create_file(&ne->device, &dev_attr_ne_oui_name); + if (ne->vendor_id) + ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id); /* Now check if there is a vendor name text string. */ @@ -1040,7 +1098,7 @@ break; case CONFIG_ROM_UNIT_DIRECTORY: - nodemgr_process_unit_directory(ne, address + value * 4, ud_id++); + nodemgr_process_unit_directory(hi, ne, address + value * 4, ud_id++); break; case CONFIG_ROM_DESCRIPTOR_LEAF: @@ -1183,14 +1241,12 @@ ne->busopt.cyc_clk_acc, ne->busopt.max_rec, ne->busopt.generation, ne->busopt.lnkspd); #endif + device_remove_file(&ne->device, &dev_attr_ne_vendor_oui); - sprintf(ne->device.bus_id, "%d-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(ne->nodeid)); - sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); - - device_register(&ne->device); - nodemgr_create_ne_dev_files(ne); + nodemgr_process_root_directory(hi, ne); - nodemgr_process_root_directory(ne); + if (ne->vendor_oui) + device_create_file(&ne->device, &dev_attr_ne_vendor_oui); } @@ -1234,21 +1290,32 @@ struct host_info *hi, nodeid_t nodeid, unsigned int generation) { + int update_ud_names = 0; + if (ne->nodeid != nodeid) { + sprintf(ne->device.name, "IEEE-1394 device %d-" NODE_BUS_FMT, + hi->id, NODE_BUS_ARGS(ne->nodeid)); HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT, NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid)); ne->nodeid = nodeid; + + update_ud_names++; } - /* If the node's configrom generation has changed, we unregister - * it, which in turn unregisters it's children (unit directories). */ if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) { - nodemgr_remove_ne(&ne->device); + /* If the node's configrom generation has changed, we + * unregister all the unit directories. */ + nodemgr_remove_node_uds(ne); - /* This will re-register our node + ud's */ + /* This will re-register our unitdir's */ nodemgr_process_config_rom (hi, ne, busoptions); + + update_ud_names++; } + if (update_ud_names) + nodemgr_update_ud_names(hi, ne); + /* Since that's done, we can declare this record current */ ne->generation = generation; @@ -1440,15 +1507,20 @@ nodemgr_remove_node)) { struct node_entry *ne = cleanup.ne; - HPSB_DEBUG("Device removed: ID:BUS[%s] GUID[%016Lx]", - ne->device.bus_id, (unsigned long long)ne->guid); - - /* Causes ne to be free'd when the device isn't - * referenced anymore. */ - ne->device.release = nodemgr_release_ne; + HPSB_DEBUG("Device removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid); - nodemgr_remove_ne(&ne->device); + nodemgr_remove_ne(ne); } + + /* Now let's tell the bus to rescan our devices. This may + * seem like overhead, but the driver-model core will only + * scan a device for a driver when either the device is + * added, or when a new driver is added. A bus reset is a + * good reason to rescan devices that were there before. + * For example, an sbp2 device may become available for + * login, if the host that held it was just removed. */ + bus_rescan_devices(&ieee1394_bus_type); } return; Modified: trunk/nodemgr.h ============================================================================== --- trunk/nodemgr.h (original) +++ trunk/nodemgr.h 2003-03-11 21:44:06.000000000 -0500 @@ -100,8 +100,11 @@ struct node_entry *ne; /* The node which this directory belongs to */ octlet_t address; /* Address of the unit directory on the node */ u8 flags; /* Indicates which entries were read */ + quadlet_t vendor_id; const char *vendor_name; + const char *vendor_oui; + int vendor_name_size; quadlet_t model_id; const char *model_name; @@ -121,6 +124,9 @@ struct node_entry { u64 guid; /* GUID of this node */ + u32 guid_vendor_id; /* Top 24bits of guid */ + const char *guid_vendor_oui; /* OUI name of guid vendor id */ + struct hpsb_host *host; /* Host this node is attached to */ nodeid_t nodeid; /* NodeID */ struct bus_options busopt; /* Bus Options */ @@ -128,13 +134,13 @@ /* The following is read from the config rom */ u32 vendor_id; + const char *vendor_name; + const char *vendor_oui; + u32 capabilities; struct hpsb_tlabel_pool *tpool; - const char *vendor_name; - char *oui_name; - struct device device; /* XXX Must be last in the struct! */ Modified: trunk/TODO ============================================================================== --- trunk/TODO (original) +++ trunk/TODO 2003-03-11 21:44:06.000000000 -0500 @@ -15,10 +15,15 @@ - Multiple LUN support in SBP-2 +- Need to report driver attach for information purposes (like usb does). + Driver Model: +- Convert bus_id's to use guid (need BUS_ID strlen to be larger) + - the sbp2 devices (not the driver or host) need a symlink to the unitdir it is attached to. - sbp2 devices need dev attributes for sbp2 specific settings (speed, max - packet, etc.). I want to get rid of the proc file. + packet, etc.). I want to get rid of the proc file. Need to find a way to + hook into the scsi-dev layer. |
From: SVN U. <ben...@li...> - 2003-03-10 23:32:34
|
Author: bencollins Date: 2003-03-10 18:31:53 -0500 (Mon, 10 Mar 2003) New Revision: 835 Modified: branches/linux-2.4/nodemgr.c Log: Use the unitdir's vendor_id when exporting for hotplug, not the node's vendor_id. Can't imagine user-space hotplug working like this. Modified: branches/linux-2.4/nodemgr.c ============================================================================== --- branches/linux-2.4/nodemgr.c (original) +++ branches/linux-2.4/nodemgr.c 2003-03-10 18:31:54.000000000 -0500 @@ -729,7 +729,7 @@ envp[i++] = scratch; scratch += sprintf(scratch, "ACTION=%s", verb) + 1; envp[i++] = scratch; - scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->ne->vendor_id) + 1; + scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->vendor_id) + 1; envp[i++] = scratch; scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1; envp[i++] = scratch; |
From: SVN U. <ben...@li...> - 2003-03-10 20:39:37
|
Author: bencollins Date: 2003-03-10 15:38:56 -0500 (Mon, 10 Mar 2003) New Revision: 834 Modified: trunk/TODO Log: Update Modified: trunk/TODO ============================================================================== --- trunk/TODO (original) +++ trunk/TODO 2003-03-10 15:38:57.000000000 -0500 @@ -19,3 +19,6 @@ - the sbp2 devices (not the driver or host) need a symlink to the unitdir it is attached to. + +- sbp2 devices need dev attributes for sbp2 specific settings (speed, max + packet, etc.). I want to get rid of the proc file. |
From: SVN U. <ben...@li...> - 2003-03-10 20:38:50
|
Author: bencollins Date: 2003-03-10 15:38:05 -0500 (Mon, 10 Mar 2003) New Revision: 833 Modified: trunk/TODO trunk/ieee1394_core.c trunk/ieee1394_hotplug.h trunk/nodemgr.c trunk/nodemgr.h trunk/sbp2.c trunk/sbp2.h Log: This is the huge patch you've been waiting for. This pretty much converts our entire bus management - including driver attachment, bus scanning and matching, etc. - over to the new driver model. SBP-2 has been converted over to provide a device_driver, which is then matched against unit-dir's in the same way as before. Anyone has any questions about this new model in relation to linux1394, please email the -devel list and I'll answer any questions. See Documentation/driver-model/ for questions about the driver core in general. Modified: trunk/ieee1394_hotplug.h ============================================================================== --- trunk/ieee1394_hotplug.h (original) +++ trunk/ieee1394_hotplug.h 2003-03-10 15:38:07.000000000 -0500 @@ -34,26 +34,6 @@ struct ieee1394_device_id *id_table; /* - * The probe function is called when a device is added to the - * bus and the nodemgr finds a matching entry in the drivers - * device id table or when registering this driver and a - * previously unhandled device can be handled. The driver may - * decline to handle the device based on further investigation - * of the device (or whatever reason) in which case a negative - * error code should be returned, otherwise 0 should be - * returned. The driver may use the driver_data field in the - * unit directory to store per device driver specific data. - */ - int (*probe)(struct unit_directory *ud); - - /* - * The disconnect function is called when a device is removed - * from the bus or if it wasn't possible to read the guid - * after the last bus reset. - */ - void (*disconnect)(struct unit_directory *ud); - - /* * The update function is called when the node has just * survived a bus reset, i.e. it is still present on the bus. * However, it may be necessary to reestablish the connection @@ -61,20 +41,12 @@ */ void (*update)(struct unit_directory *ud); - /* Driver in list of all registered drivers */ - struct list_head list; - - /* The list of unit directories managed by this driver */ - struct list_head unit_directories; + /* Our LDM structure */ struct device_driver driver; }; int hpsb_register_protocol(struct hpsb_protocol_driver *driver); void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); -int hpsb_claim_unit_directory(struct unit_directory *ud, - struct hpsb_protocol_driver *driver); -void hpsb_release_unit_directory(struct unit_directory *ud); - #endif /* _IEEE1394_HOTPLUG_H */ Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2003-03-10 15:38:07.000000000 -0500 @@ -52,10 +52,6 @@ MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); static int disable_nodemgr = 0; -MODULE_PARM(disable_hotplug, "i"); -MODULE_PARM_DESC(disable_hotplug, "Disable hotplug for detected nodes."); -static int disable_hotplug = 0; - /* We are GPL, so treat us special */ MODULE_LICENSE("GPL"); @@ -1179,7 +1175,7 @@ init_hpsb_highlevel(); init_csr(); if (!disable_nodemgr) - init_ieee1394_nodemgr(disable_hotplug); + init_ieee1394_nodemgr(); else HPSB_INFO("nodemgr functionality disabled"); @@ -1273,7 +1269,6 @@ EXPORT_SYMBOL(hpsb_node_lock); EXPORT_SYMBOL(hpsb_register_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol); -EXPORT_SYMBOL(hpsb_release_unit_directory); EXPORT_SYMBOL(ieee1394_bus_type); /** csr.c **/ Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-10 15:38:07.000000000 -0500 @@ -1,8 +1,8 @@ /* * Node information (ConfigROM) collection and management. * - * Copyright (C) 2000 Andreas E. Bombe - * 2001 Ben Collins <bco...@de...> + * Copyright (C) 2000 Andreas E. Bombe + * 2001-2003 Ben Collins <bco...@de...> * * This code is licensed under the GPL. See the file COPYING in the root * directory of the kernel sources for details. @@ -30,14 +30,6 @@ #include "csr.h" #include "nodemgr.h" -#ifdef CONFIG_IEEE1394_OUI_DB -struct oui_list_struct { - int oui; - char *name; -}; - -extern struct oui_list_struct oui_list[]; -#endif /* Shitty part is, 0x0 can just mean it wasn't set, but that matches an * OUI entry. We don't want that, so we take a chance and never match 0x0. @@ -45,6 +37,10 @@ static char *nodemgr_find_oui_name(int oui) { #ifdef CONFIG_IEEE1394_OUI_DB + extern struct oui_list_struct { + int oui; + char *name; + } oui_list[]; int i; for (i = 1; oui_list[i].name; i++) @@ -69,28 +65,16 @@ */ /* - * 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. + * The nodemgr relies heavily on the Drive Model for device callbacks and + * driver/device mappings. The old nodemgr used to handle all this itself, + * but now we are much simpler because of the LDM. */ static DECLARE_MUTEX(nodemgr_serialize); -static LIST_HEAD(node_list); -static LIST_HEAD(driver_list); -static LIST_HEAD(unit_directory_list); static LIST_HEAD(host_info_list); static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED; -/* Disables use of the hotplug calls. */ -static int nodemgr_disable_hotplug = 0; - struct host_info { struct hpsb_host *host; struct list_head list; @@ -102,72 +86,33 @@ }; -#define fw_ne_attr(field, type, format_string) \ -static ssize_t fw_ne_show_##field (struct device *dev, char *buf)\ -{ \ - struct node_entry *ne; \ - ne = container_of(dev, struct node_entry, device); \ - return sprintf(buf, format_string, (type)ne->field); \ -} \ -static struct device_attribute dev_attr_ne_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_ne_show_##field, \ +#define fw_attr(class, class_type, field, type, format_string) \ +static ssize_t fw_show_##class##_##field (struct device *dev, char *buf)\ +{ \ + class_type *class; \ + class = container_of(dev, class_type, device); \ + return sprintf(buf, format_string, (type)class->field); \ +} \ +static struct device_attribute dev_attr_##class##_##field = { \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_show_##class##_##field, \ }; -#define fw_ud_attr(field, type, format_string) \ -static ssize_t fw_ud_show_##field (struct device *dev, char *buf) \ -{ \ - struct unit_directory *ud; \ - ud = container_of(dev, struct unit_directory, device); \ - return sprintf(buf, format_string, (type)ud->field); \ -} \ -static struct device_attribute dev_attr_ud_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_ud_show_##field, \ -}; -#define fw_host_attr(field, type, format_string) \ -static ssize_t fw_host_show_##field (struct device *dev, char *buf) \ +#define fw_drv_attr(field, type, format_string) \ +static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \ { \ - struct hpsb_host *host; \ - host = container_of(dev, struct hpsb_host, device); \ - return sprintf(buf, format_string, (type)host->field); \ + struct hpsb_protocol_driver *driver; \ + driver = container_of(drv, struct hpsb_protocol_driver, driver); \ + return sprintf(buf, format_string, (type)driver->field);\ } \ -static struct device_attribute dev_attr_host_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_host_show_##field, \ +static struct driver_attribute driver_attr_drv_##field = { \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_drv_show_##field, \ }; -fw_ne_attr(guid, unsigned long long, "0x%016Lx\n") -fw_ne_attr(capabilities, unsigned int, "0x%06x\n") -fw_ne_attr(vendor_id, unsigned int, "0x%06x\n") -fw_ne_attr(nodeid, unsigned int, "0x%04x\n") -fw_ne_attr(vendor_name, const char *, "%s\n") -fw_ne_attr(oui_name, const char *, "%s\n") - - -fw_ud_attr(address, unsigned long long, "0x%016Lx\n") -fw_ud_attr(vendor_id, unsigned int, "0x%06x\n") -fw_ud_attr(model_id, unsigned int, "0x%06x\n") -fw_ud_attr(specifier_id, unsigned int, "0x%06x\n") -fw_ud_attr(version, unsigned int, "0x%06x\n") -fw_ud_attr(length, int, "%d\n") -fw_ud_attr(vendor_name, const char *, "%s\n") -fw_ud_attr(model_name, const char *, "%s\n") - - -fw_host_attr(node_count, int, "%d\n") -fw_host_attr(selfid_count, int, "%d\n") -fw_host_attr(nodes_active, int, "%d\n") -fw_host_attr(in_bus_reset, int, "%d\n") -fw_host_attr(is_root, int, "%d\n") -fw_host_attr(is_cycmst, int, "%d\n") -fw_host_attr(is_irm, int, "%d\n") -fw_host_attr(is_busmgr, int, "%d\n") - - -static ssize_t fw_ne_show_bus_options(struct device *dev, char *buf) +static ssize_t fw_show_ne_bus_options(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); @@ -177,26 +122,26 @@ ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, ne->busopt.max_rec, ne->busopt.cyc_clk_acc); } -static DEVICE_ATTR(bus_options,S_IRUGO,fw_ne_show_bus_options,NULL); +static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); -static ssize_t fw_ne_show_tlabels_free(struct device *dev, char *buf) +static ssize_t fw_show_ne_tlabels_free(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1); } -static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_ne_show_tlabels_free,NULL); +static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); -static ssize_t fw_ne_show_tlabels_allocations(struct device *dev, char *buf) +static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); return sprintf(buf, "%u\n", ne->tpool->allocations); } -static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_ne_show_tlabels_allocations,NULL); +static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL); -static ssize_t fw_ne_show_tlabels_mask(struct device *dev, char *buf) +static ssize_t fw_show_ne_tlabels_mask(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); #if (BITS_PER_LONG <= 32) @@ -205,49 +150,188 @@ return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); #endif } -static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_ne_show_tlabels_mask,NULL); +static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_show_ne_tlabels_mask,NULL); + + +fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n") +fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n") +fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n") +fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n") +fw_attr(ne, struct node_entry, vendor_name, const char *, "%s\n") +fw_attr(ne, struct node_entry, oui_name, const char *, "%s\n") + +static struct device_attribute *const fw_ne_attrs[] = { + &dev_attr_ne_guid, + &dev_attr_ne_capabilities, + &dev_attr_ne_vendor_id, + &dev_attr_ne_nodeid, + &dev_attr_bus_options, + &dev_attr_tlabels_free, + &dev_attr_tlabels_allocations, + &dev_attr_tlabels_mask, +}; + + + +fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n") +fw_attr(ud, struct unit_directory, length, int, "%d\n") +/* These are all dependent on if the value is preovided */ +fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n") +fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n") +fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n") +fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n") +fw_attr(ud, struct unit_directory, vendor_name, const char *, "%s\n") +fw_attr(ud, struct unit_directory, model_name, const char *, "%s\n") + +static struct device_attribute *const fw_ud_attrs[] = { + &dev_attr_ud_address, + &dev_attr_ud_length, +}; + + +fw_attr(host, struct hpsb_host, node_count, int, "%d\n") +fw_attr(host, struct hpsb_host, selfid_count, int, "%d\n") +fw_attr(host, struct hpsb_host, nodes_active, int, "%d\n") +fw_attr(host, struct hpsb_host, in_bus_reset, int, "%d\n") +fw_attr(host, struct hpsb_host, is_root, int, "%d\n") +fw_attr(host, struct hpsb_host, is_cycmst, int, "%d\n") +fw_attr(host, struct hpsb_host, is_irm, int, "%d\n") +fw_attr(host, struct hpsb_host, is_busmgr, int, "%d\n") + +static struct device_attribute *const fw_host_attrs[] = { + &dev_attr_host_node_count, + &dev_attr_host_selfid_count, + &dev_attr_host_nodes_active, + &dev_attr_host_in_bus_reset, + &dev_attr_host_is_root, + &dev_attr_host_is_cycmst, + &dev_attr_host_is_irm, + &dev_attr_host_is_busmgr, +}; + + +static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) +{ + struct hpsb_protocol_driver *driver; + struct ieee1394_device_id *id; + int length = 0; + char *scratch = buf; + + driver = container_of(drv, struct hpsb_protocol_driver, driver); + + for (id = driver->id_table; id->match_flags != 0; id++) { + int need_coma = 0; + + if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) { + length += sprintf(scratch, "vendor_id=0x%06x", id->vendor_id); + scratch = buf + length; + need_coma++; + } + + if (id->match_flags & IEEE1394_MATCH_MODEL_ID) { + length += sprintf(scratch, "%smodel_id=0x%06x", + need_coma++ ? "," : "", + id->model_id); + scratch = buf + length; + } + + if (id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) { + length += sprintf(scratch, "%sspecifier_id=0x%06x", + need_coma++ ? "," : "", + id->specifier_id); + scratch = buf + length; + } + + if (id->match_flags & IEEE1394_MATCH_VERSION) { + length += sprintf(scratch, "%sversion=0x%06x", + need_coma++ ? "," : "", + id->version); + scratch = buf + length; + } + + if (need_coma) { + *scratch++ = '\n'; + length++; + } + } + + return length; +} +static DRIVER_ATTR(device_ids,S_IRUGO,fw_show_drv_device_ids,NULL); + + +fw_drv_attr(name, const char *, "%s\n") + +static struct driver_attribute *const fw_drv_attrs[] = { + &driver_attr_drv_name, + &driver_attr_device_ids, +}; + + +static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver) +{ + struct device_driver *drv = &driver->driver; + int i; + + for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) + driver_create_file(drv, fw_drv_attrs[i]); +} + + +static void nodemgr_remove_drv_files(struct hpsb_protocol_driver *driver) +{ + struct device_driver *drv = &driver->driver; + int i; + + for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) + driver_remove_file(drv, fw_drv_attrs[i]); +} static void nodemgr_create_ne_dev_files(struct node_entry *ne) { struct device *dev = &ne->device; + int i; - device_create_file(dev, &dev_attr_ne_guid); - device_create_file(dev, &dev_attr_ne_capabilities); - device_create_file(dev, &dev_attr_ne_vendor_id); - device_create_file(dev, &dev_attr_ne_nodeid); - device_create_file(dev, &dev_attr_bus_options); - device_create_file(dev, &dev_attr_tlabels_free); - device_create_file(dev, &dev_attr_tlabels_allocations); - device_create_file(dev, &dev_attr_tlabels_mask); + for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) + device_create_file(dev, fw_ne_attrs[i]); } + static void nodemgr_create_host_dev_files(struct hpsb_host *host) { struct device *dev = &host->device; + int i; + + for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) + device_create_file(dev, fw_host_attrs[i]); +} + + +static void nodemgr_update_host_dev_links(struct hpsb_host *host) +{ + struct device *dev = &host->device; struct node_entry *ne; - device_create_file(dev, &dev_attr_host_node_count); - device_create_file(dev, &dev_attr_host_selfid_count); - device_create_file(dev, &dev_attr_host_nodes_active); - device_create_file(dev, &dev_attr_host_in_bus_reset); - device_create_file(dev, &dev_attr_host_is_root); - device_create_file(dev, &dev_attr_host_is_cycmst); - device_create_file(dev, &dev_attr_host_is_irm); - device_create_file(dev, &dev_attr_host_is_busmgr); + sysfs_remove_link(&dev->kobj, "irm_id"); + sysfs_remove_link(&dev->kobj, "busmgr_id"); + sysfs_remove_link(&dev->kobj, "host_id"); - if ((ne = hpsb_nodeid_get_entry(host->irm_id))) + if ((ne = hpsb_nodeid_get_entry(host, host->irm_id))) sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"); - if ((ne = hpsb_nodeid_get_entry(host->busmgr_id))) + if ((ne = hpsb_nodeid_get_entry(host, host->busmgr_id))) sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"); + if ((ne = hpsb_nodeid_get_entry(host, host->node_id))) + sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"); } static void nodemgr_create_ud_dev_files(struct unit_directory *ud) { struct device *dev = &ud->device; + int i; - device_create_file(dev, &dev_attr_ud_address); - device_create_file(dev, &dev_attr_ud_length); + for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) + device_create_file(dev, fw_ud_attrs[i]); if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) device_create_file(dev, &dev_attr_ud_specifier_id); @@ -271,16 +355,137 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) { + struct hpsb_protocol_driver *driver; + struct unit_directory *ud; + struct ieee1394_device_id *id; + + if (dev->class_num != DEV_CLASS_UNIT_DIRECTORY) + return 0; + + ud = container_of(dev, struct unit_directory, device); + driver = container_of(drv, struct hpsb_protocol_driver, driver); + + for (id = driver->id_table; id->match_flags != 0; id++) { + if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && + id->vendor_id != ud->vendor_id) + continue; + + if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && + id->model_id != ud->model_id) + continue; + + if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && + id->specifier_id != ud->specifier_id) + continue; + + if ((id->match_flags & IEEE1394_MATCH_VERSION) && + id->version != ud->version) + continue; + + return 1; + } + return 0; } + +static void nodemgr_release_ud(struct device *dev) +{ + kfree(container_of(dev, struct unit_directory, device)); +} + + +static void nodemgr_release_ne(struct device *dev) +{ + kfree(container_of(dev, struct node_entry, device)); +} + + +static void nodemgr_remove_ud(struct device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) + device_remove_file(dev, fw_ud_attrs[i]); + + device_remove_file(dev, &dev_attr_ud_specifier_id); + device_remove_file(dev, &dev_attr_ud_version); + device_remove_file(dev, &dev_attr_ud_vendor_id); + device_remove_file(dev, &dev_attr_ud_vendor_name); + device_remove_file(dev, &dev_attr_ud_model_id); + device_remove_file(dev, &dev_attr_ud_model_name); + + device_unregister(dev); +} + + +static void nodemgr_remove_ne(struct device *dev) +{ + int i; + struct list_head *lh, *next; + + list_for_each_safe(lh, next, &dev->children) + nodemgr_remove_ud(list_to_dev(lh)); + + for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) + device_remove_file(dev, fw_ne_attrs[i]); + + device_unregister(dev); +} + + +static void nodemgr_remove_host_dev(struct device *dev) +{ + int i; + struct list_head *lh, *next; + + list_for_each_safe(lh, next, &dev->children) { + struct device *child_dev = list_to_dev(lh); + struct node_entry *ne; + + ne = container_of(child_dev, struct node_entry, device); + /* Force free'ing of ne struct aswell */ + ne->device.release = nodemgr_release_ne; + + nodemgr_remove_ne(child_dev); + } + + for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) + device_remove_file(dev, fw_host_attrs[i]); + + sysfs_remove_link(&dev->kobj, "irm_id"); + sysfs_remove_link(&dev->kobj, "busmgr_id"); + sysfs_remove_link(&dev->kobj, "host_id"); +} + + +static struct device nodemgr_dev_template_ud = { + .bus = &ieee1394_bus_type, + .release = nodemgr_release_ud, + .class_num = DEV_CLASS_UNIT_DIRECTORY, +}; + +static struct device nodemgr_dev_template_ne = { + .bus = &ieee1394_bus_type, + .class_num = DEV_CLASS_NODE, +}; + +static struct device nodemgr_dev_template_host = { + .bus = &ieee1394_bus_type, + .class_num = DEV_CLASS_HOST, +}; + + +static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size); + + struct bus_type ieee1394_bus_type = { .name = "ieee1394", .match = nodemgr_bus_match, + .hotplug = nodemgr_hotplug, }; -static void nodemgr_process_config_rom(struct node_entry *ne, - quadlet_t busoptions); static int nodemgr_read_quadlet(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation, @@ -356,7 +561,8 @@ ret = -ENXIO; for (; size > 0; size--, address += 4, quadp++) { for (i = 0; i < 3; i++) { - ret = hpsb_read(ne->host, ne->nodeid, ne->generation, address, quadp, 4); + + ret = hpsb_node_read(ne, address, quadp, 4); if (ret != -EAGAIN) break; } @@ -426,9 +632,13 @@ return ne; } + +static void nodemgr_process_config_rom(struct host_info *hi, + struct node_entry *ne, quadlet_t busoptions); + static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions, - struct host_info *hi, - nodeid_t nodeid, unsigned int generation) + struct host_info *hi, nodeid_t nodeid, + unsigned int generation) { struct hpsb_host *host = hi->host; struct node_entry *ne; @@ -436,9 +646,6 @@ ne = nodemgr_scan_root_directory (host, nodeid, generation); if (!ne) return NULL; - INIT_LIST_HEAD(&ne->list); - INIT_LIST_HEAD(&ne->unit_directories); - ne->tpool = &host->tpool[nodeid & NODE_MASK]; ne->host = host; @@ -446,50 +653,92 @@ ne->guid = guid; ne->generation = generation; - list_add_tail(&ne->list, &node_list); - + memcpy(&ne->device, &nodemgr_dev_template_ne, + sizeof(ne->device)); ne->device.parent = &host->device; - sprintf(ne->device.bus_id, "%d-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(nodeid)); - sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); - ne->device.bus = &ieee1394_bus_type; - - device_register(&ne->device); - nodemgr_create_ne_dev_files(ne); - nodemgr_process_config_rom (ne, busoptions); + nodemgr_process_config_rom (hi, ne, busoptions); - HPSB_DEBUG("%s added: ID:BUS[%s] GUID[%016Lx] [%s] (%s)", + HPSB_DEBUG("%s added: ID:BUS[%d-" NODE_BUS_FMT "] GUID[%016Lx]", (host->node_id == nodeid) ? "Host" : "Node", - ne->device.bus_id, (unsigned long long)guid, - ne->oui_name, ne->vendor_name ?: "Unknown"); + hi->id, NODE_BUS_ARGS(nodeid), (unsigned long long)guid); return ne; } -static struct node_entry *find_entry_by_guid(u64 guid) + +struct guid_search_baton { + u64 guid; + struct node_entry *ne; +}; + +static int nodemgr_guid_search_cb(struct device *dev, void *__data) { - struct list_head *lh; + struct guid_search_baton *search = __data; struct node_entry *ne; - - list_for_each(lh, &node_list) { - ne = list_entry(lh, struct node_entry, list); - if (ne->guid == guid) return ne; - } - return NULL; + if (dev->class_num != DEV_CLASS_NODE) + return 0; + + ne = container_of(dev, struct node_entry, device); + + if (ne->guid == search->guid) { + search->ne = ne; + return 1; + } + + return 0; } -static struct node_entry *find_entry_by_nodeid(nodeid_t nodeid) +static struct node_entry *find_entry_by_guid(u64 guid) { - struct list_head *lh; + struct guid_search_baton search; + + search.guid = guid; + search.ne = NULL; + + bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_guid_search_cb); + + return search.ne; +} + + +struct nodeid_search_baton { + nodeid_t nodeid; + struct node_entry *ne; + struct hpsb_host *host; +}; + +static int nodemgr_nodeid_search_cb(struct device *dev, void *__data) +{ + struct nodeid_search_baton *search = __data; struct node_entry *ne; - list_for_each(lh, &node_list) { - ne = list_entry(lh, struct node_entry, list); - if (ne->nodeid == nodeid) return ne; + if (dev->class_num != DEV_CLASS_NODE) + return 0; + + ne = container_of(dev, struct node_entry, device); + + if (ne->host == search->host && ne->nodeid == search->nodeid) { + search->ne = ne; + /* Returning 1 stops the iteration */ + return 1; } - return NULL; + return 0; +} + +static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) +{ + struct nodeid_search_baton search; + + search.nodeid = nodeid; + search.ne = NULL; + search.host = host; + + bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_nodeid_search_cb); + + return search.ne; } static struct unit_directory *nodemgr_scan_unit_directory @@ -589,11 +838,10 @@ return ud; } + /* This implementation currently only scans the config rom and its * 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 node_entry *ne, octlet_t address, unsigned int id) { @@ -690,13 +938,11 @@ } } - list_add_tail(&ud->node_list, &ne->unit_directories); - list_add_tail(&ud->driver_list, &unit_directory_list); - + memcpy(&ud->device, &nodemgr_dev_template_ud, + sizeof(ud->device)); ud->device.parent = &ne->device; sprintf(ud->device.bus_id, "%s-%u", ne->device.bus_id, ud->id); sprintf(ud->device.name, "IEEE-1394 unit directory %s", ud->device.bus_id); - ud->device.bus = &ieee1394_bus_type; device_register(&ud->device); nodemgr_create_ud_dev_files(ud); @@ -809,79 +1055,54 @@ #ifdef CONFIG_HOTPLUG -static void nodemgr_call_policy(char *verb, struct unit_directory *ud) +static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { - char *argv [3], **envp, *buf, *scratch; - int i = 0, value; - - /* User requested to disable hotplug when module was loaded. */ - if (nodemgr_disable_hotplug) - return; - - if (!hotplug_path [0]) - return; - if (!current->fs->root) - return; - if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) { - HPSB_DEBUG ("ENOMEM"); - return; - } - if (!(buf = kmalloc(256, GFP_KERNEL))) { - kfree(envp); - HPSB_DEBUG("ENOMEM2"); - return; - } + struct unit_directory *ud; + char *scratch; + int i = 0; + int length = 0; + + if (!dev) + return -ENODEV; + + if (dev->class_num != DEV_CLASS_UNIT_DIRECTORY) + return -ENODEV; + + ud = container_of(dev, struct unit_directory, device); + + scratch = buffer; + +#define PUT_ENVP(fmt,val) \ +do { \ + envp[i++] = scratch; \ + length += snprintf(scratch, buffer_size - length, \ + fmt, val); \ + if ((buffer_size - length <= 0) || (i >= num_envp)) \ + return -ENOMEM; \ + ++length; \ + scratch = buffer + length; \ +} while(0) + + PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); + PUT_ENVP("MODEL_ID=%06x", ud->model_id); + PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid); + PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id); + PUT_ENVP("VERSION=%06x", ud->version); - /* only one standardized param to hotplug command: type */ - argv[0] = hotplug_path; - argv[1] = "ieee1394"; - argv[2] = 0; - - /* minimal command environment */ - envp[i++] = "HOME=/"; - envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; +#undef PUT_ENVP -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - /* hint that policy agent should enter no-stdout debug mode */ - envp[i++] = "DEBUG=kernel"; -#endif - /* extensible set of named bus-specific parameters, - * supporting multiple driver selection algorithms. - */ - scratch = buf; - - envp[i++] = scratch; - scratch += sprintf(scratch, "ACTION=%s", verb) + 1; - envp[i++] = scratch; - scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->ne->vendor_id) + 1; - envp[i++] = scratch; - scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1; - envp[i++] = scratch; - scratch += sprintf(scratch, "SPECIFIER_ID=%06x", ud->specifier_id) + 1; - envp[i++] = scratch; - scratch += sprintf(scratch, "VERSION=%06x", ud->version) + 1; - envp[i++] = 0; + envp[i] = 0; - /* NOTE: user mode daemons can call the agents too */ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid); -#endif - value = call_usermodehelper(argv[0], argv, envp, 0); - kfree(buf); - kfree(envp); - if (value != 0) - HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value); + return 0; } #else -static inline void -nodemgr_call_policy(char *verb, struct unit_directory *ud) +static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled"); -#endif - return; + return -ENODEV; } #endif /* CONFIG_HOTPLUG */ @@ -919,135 +1140,11 @@ } } -static void nodemgr_claim_unit_directory(struct unit_directory *ud, - struct hpsb_protocol_driver *driver) -{ - ud->driver = driver; - list_del(&ud->driver_list); - list_add_tail(&ud->driver_list, &driver->unit_directories); -} - -static void nodemgr_release_unit_directory(struct unit_directory *ud) -{ - ud->driver = NULL; - list_del(&ud->driver_list); - list_add_tail(&ud->driver_list, &unit_directory_list); -} - -void hpsb_release_unit_directory(struct unit_directory *ud) -{ - down(&nodemgr_serialize); - nodemgr_release_unit_directory(ud); - up(&nodemgr_serialize); -} - -static void nodemgr_free_unit_directories(struct node_entry *ne) -{ - struct list_head *lh; - struct unit_directory *ud; - - lh = ne->unit_directories.next; - while (lh != &ne->unit_directories) { - ud = list_entry(lh, struct unit_directory, node_list); - lh = lh->next; - if (ud->driver && ud->driver->disconnect) - ud->driver->disconnect(ud); - nodemgr_release_unit_directory(ud); - nodemgr_call_policy("remove", ud); - list_del(&ud->driver_list); - device_unregister(&ud->device); - kfree(ud); - } -} - -static struct ieee1394_device_id * -nodemgr_match_driver(struct hpsb_protocol_driver *driver, - struct unit_directory *ud) -{ - struct ieee1394_device_id *id; - - for (id = driver->id_table; id->match_flags != 0; id++) { - if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && - id->vendor_id != ud->vendor_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && - id->model_id != ud->model_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && - id->specifier_id != ud->specifier_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_VERSION) && - id->version != ud->version) - continue; - - return id; - } - - return NULL; -} - -static struct hpsb_protocol_driver * -nodemgr_find_driver(struct unit_directory *ud) -{ - struct list_head *l; - struct hpsb_protocol_driver *match, *driver; - struct ieee1394_device_id *device_id; - - match = NULL; - list_for_each(l, &driver_list) { - driver = list_entry(l, struct hpsb_protocol_driver, list); - device_id = nodemgr_match_driver(driver, ud); - - if (device_id != NULL) { - match = driver; - break; - } - } - - return match; -} - -static void nodemgr_bind_drivers (struct node_entry *ne) -{ - struct list_head *lh; - struct hpsb_protocol_driver *driver; - struct unit_directory *ud; - - list_for_each(lh, &ne->unit_directories) { - ud = list_entry(lh, struct unit_directory, node_list); - driver = nodemgr_find_driver(ud); - if (driver != NULL && driver->probe(ud) == 0) - nodemgr_claim_unit_directory(ud, driver); - nodemgr_call_policy("add", ud); - } -} int hpsb_register_protocol(struct hpsb_protocol_driver *driver) { - struct unit_directory *ud; - struct list_head *lh; - - if (down_interruptible(&nodemgr_serialize)) - return -EINTR; - - if (driver->driver.name[0]) - driver_register(&driver->driver); - - list_add_tail(&driver->list, &driver_list); - - INIT_LIST_HEAD(&driver->unit_directories); - lh = unit_directory_list.next; - while (lh != &unit_directory_list) { - ud = list_entry(lh, struct unit_directory, driver_list); - lh = lh->next; - if (nodemgr_match_driver(driver, ud) && driver->probe(ud) == 0) - nodemgr_claim_unit_directory(ud, driver); - } - - up(&nodemgr_serialize); + driver_register(&driver->driver); + nodemgr_create_drv_files(driver); /* * Right now registration always succeeds, but maybe we should @@ -1059,26 +1156,14 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) { - struct list_head *lh; - struct unit_directory *ud; - - down(&nodemgr_serialize); - - list_del(&driver->list); - lh = driver->unit_directories.next; - while (lh != &driver->unit_directories) { - ud = list_entry(lh, struct unit_directory, driver_list); - lh = lh->next; - if (ud->driver && ud->driver->disconnect) - ud->driver->disconnect(ud); - nodemgr_release_unit_directory(ud); - } - - up(&nodemgr_serialize); + nodemgr_remove_drv_files(driver); + /* This will subsequently disconnect all devices that our driver + * is attached to. */ + driver_unregister(&driver->driver); } -static void nodemgr_process_config_rom(struct node_entry *ne, - quadlet_t busoptions) +static void nodemgr_process_config_rom(struct host_info *hi, + struct node_entry *ne, quadlet_t busoptions) { ne->busopt.irmc = (busoptions >> 31) & 1; ne->busopt.cmc = (busoptions >> 30) & 1; @@ -1099,15 +1184,43 @@ ne->busopt.generation, ne->busopt.lnkspd); #endif - /* - * When the config rom changes we disconnect all drivers and - * free the cached unit directories and reread the whole - * thing. If this was a new device, the call to - * nodemgr_disconnect_drivers is a no-op and all is well. - */ - nodemgr_free_unit_directories(ne); + sprintf(ne->device.bus_id, "%d-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(ne->nodeid)); + sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); + + device_register(&ne->device); + nodemgr_create_ne_dev_files(ne); + nodemgr_process_root_directory(ne); - nodemgr_bind_drivers(ne); +} + + +/* Searches the list of ud's that match a ne as the parent. If the ud has + * a driver associated with it, we call that driver's update function + * with the ud as the argument. */ +static int nodemgr_driver_search_cb(struct device *dev, void *__data) +{ + struct node_entry *ne = __data; + struct unit_directory *ud; + + if (dev->class_num != DEV_CLASS_UNIT_DIRECTORY) + return 0; + + ud = container_of(dev, struct unit_directory, device); + + if (&ne->device != ud->device.parent) + return 0; + + if (ud->device.driver) { + struct hpsb_protocol_driver *pdrv; + + pdrv = container_of(ud->device.driver, + struct hpsb_protocol_driver, driver); + + if (pdrv->update) + pdrv->update(ud); + } + + return 0; } /* @@ -1118,29 +1231,30 @@ * the to take whatever actions required. */ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions, - struct hpsb_host *host, - nodeid_t nodeid, unsigned int generation) + struct host_info *hi, nodeid_t nodeid, + unsigned int generation) { - struct list_head *lh; - struct unit_directory *ud; - 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->nodeid = nodeid; } - if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) - nodemgr_process_config_rom (ne, busoptions); + /* If the node's configrom generation has changed, we unregister + * it, which in turn unregisters it's children (unit directories). */ + if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) { + nodemgr_remove_ne(&ne->device); + + /* This will re-register our node + ud's */ + nodemgr_process_config_rom (hi, ne, busoptions); + } /* Since that's done, we can declare this record current */ ne->generation = generation; - list_for_each (lh, &ne->unit_directories) { - ud = list_entry (lh, struct unit_directory, node_list); - if (ud->driver != NULL && ud->driver->update != NULL) - ud->driver->update(ud); - } + /* Update unit_dirs with attached drivers */ + bus_for_each_dev(&ieee1394_bus_type, NULL, ne, + nodemgr_driver_search_cb); } static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation, @@ -1204,19 +1318,6 @@ return 0; } -static void nodemgr_remove_node(struct node_entry *ne) -{ - HPSB_DEBUG("Device removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", - NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid, - ne->vendor_name ?: "Unknown"); - - nodemgr_free_unit_directories(ne); - list_del(&ne->list); - device_unregister(&ne->device); - kfree(ne); - - return; -} /* This is where we probe the nodes for their information and provided * features. */ @@ -1253,36 +1354,40 @@ if (!ne) nodemgr_create_node(guid, buffer[2], hi, nodeid, generation); else - nodemgr_update_node(ne, buffer[2], host, nodeid, generation); + nodemgr_update_node(ne, buffer[2], hi, nodeid, generation); return; } -static void nodemgr_node_probe_cleanup(struct hpsb_host *host, unsigned int generation) + +struct cleanup_baton { + unsigned int generation; + struct hpsb_host *host; + struct node_entry *ne; +}; + +static int nodemgr_remove_node(struct device *dev, void *__data) { - struct list_head *lh, *next; + struct cleanup_baton *cleanup = __data; struct node_entry *ne; - /* Now check to see if we have any nodes that aren't referenced - * any longer. */ - list_for_each_safe(lh, next, &node_list) { - ne = list_entry(lh, struct node_entry, list); + if (dev->class_num != DEV_CLASS_NODE) + return 0; - /* Only checking this host */ - if (ne->host != host) - continue; + ne = container_of(dev, struct node_entry, device); - /* If the generation didn't get updated, then either the - * node was removed, or it failed the above probe. Either - * way, we remove references to it, since they are - * invalid. */ - if (ne->generation != generation) - nodemgr_remove_node(ne); + if (ne->host != cleanup->host) + return 0; + + if (ne->generation != cleanup->generation) { + cleanup->ne = ne; + return 1; } - return; + return 0; } + static void nodemgr_node_probe(struct host_info *hi) { int count; @@ -1314,7 +1419,6 @@ nodeid++; continue; } - nodemgr_node_probe_one(hi, nodeid++, generation); } @@ -1324,8 +1428,28 @@ * were still on the bus. The bus reset increased * hi->reset_sem, so there's a bus scan pending which will do * the clean up eventually. */ - if (generation == get_hpsb_generation(host)) - nodemgr_node_probe_cleanup(host, generation); + if (generation == get_hpsb_generation(host)) { + struct cleanup_baton cleanup; + + cleanup.generation = generation; + cleanup.host = host; + + /* This will iterate until all devices that do not match + * the generation are removed. */ + while (bus_for_each_dev(&ieee1394_bus_type, NULL, &cleanup, + nodemgr_remove_node)) { + struct node_entry *ne = cleanup.ne; + + HPSB_DEBUG("Device removed: ID:BUS[%s] GUID[%016Lx]", + ne->device.bus_id, (unsigned long long)ne->guid); + + /* Causes ne to be free'd when the device isn't + * referenced anymore. */ + ne->device.release = nodemgr_release_ne; + + nodemgr_remove_ne(&ne->device); + } + } return; } @@ -1346,8 +1470,7 @@ hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), - &bc, - sizeof(quadlet_t)); + &bc, sizeof(quadlet_t)); } /* We need to ensure that if we are not the IRM, that the IRM node is capable of @@ -1379,33 +1502,34 @@ static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; - int host_dev_files = 0; + struct hpsb_host *host = hi->host; /* No userlevel access needed */ daemonize(hi->daemon_name); allow_signal(SIGTERM); + /* Setup our device-model entries */ + device_register(&host->device); + nodemgr_create_host_dev_files(host); + /* 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) && !down_interruptible(&nodemgr_serialize)) { - if (!nodemgr_check_root_capability(hi->host)) { + if (!nodemgr_check_root_capability(host)) { /* Do nothing, we are resetting */ up(&nodemgr_serialize); continue; } nodemgr_node_probe(hi); - nodemgr_do_irm_duties(hi->host); + nodemgr_do_irm_duties(host); up(&nodemgr_serialize); - /* First time around, let's also create the host dev files */ - if (!host_dev_files) { - nodemgr_create_host_dev_files(hi->host); - host_dev_files = 1; - } + /* Update some of our sysfs symlinks */ + nodemgr_update_host_dev_links(host); } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name); @@ -1425,24 +1549,24 @@ return ne; } -struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid) +struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid) { struct node_entry *ne; down(&nodemgr_serialize); - ne = find_entry_by_nodeid(nodeid); + ne = find_entry_by_nodeid(host, nodeid); up(&nodemgr_serialize); return ne; } -struct node_entry *hpsb_check_nodeid(nodeid_t nodeid) +struct node_entry *hpsb_check_nodeid(struct hpsb_host *host, nodeid_t nodeid) { struct node_entry *ne; if (down_trylock(&nodemgr_serialize)) return NULL; - ne = find_entry_by_nodeid(nodeid); + ne = find_entry_by_nodeid(host, nodeid); up(&nodemgr_serialize); return ne; @@ -1523,14 +1647,13 @@ hi->id = nodemgr_alloc_host_num(); + memcpy(&host->device, &nodemgr_dev_template_host, + sizeof(host->device)); host->device.parent = &host->pdev->dev; sprintf(host->device.bus_id, "fw-host%d", hi->id); sprintf(host->device.name, "IEEE-1394 Host %s-%d", host->driver->name, hi->id); - host->device.bus = &ieee1394_bus_type; - sprintf(hi->daemon_name, "knodemgrd/%d", hi->id); - - device_register(&host->device); + sprintf(hi->daemon_name, "knodemgrd_%d", hi->id); hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); @@ -1538,7 +1661,6 @@ if (hi->pid < 0) { HPSB_ERR ("NodeMgr: failed to start %s thread for %s", hi->daemon_name, host->driver->name); - device_unregister(&host->device); kfree(hi); return; } @@ -1581,7 +1703,6 @@ static void nodemgr_remove_host(struct hpsb_host *host) { struct list_head *lh, *next; - struct node_entry *ne; unsigned long flags; struct host_info *hi = NULL; @@ -1600,28 +1721,14 @@ if (hi->pid >= 0) { kill_proc(hi->pid, SIGTERM, 1); wait_for_completion(&hi->exited); + nodemgr_remove_host_dev(&host->device); + device_unregister(&host->device); } kfree(hi); - } - else + } 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. */ - list_for_each_safe(lh, next, &node_list) { - ne = list_entry(lh, struct node_entry, list); - - if (ne->host == host) - nodemgr_remove_node(ne); - } - - device_unregister(&host->device); - - up(&nodemgr_serialize); - return; } @@ -1633,10 +1740,8 @@ static struct hpsb_highlevel *hl; -void init_ieee1394_nodemgr(int disable_hotplug) +void init_ieee1394_nodemgr(void) { - nodemgr_disable_hotplug = disable_hotplug; - bus_register(&ieee1394_bus_type); hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); Modified: trunk/nodemgr.h ============================================================================== --- trunk/nodemgr.h (original) +++ trunk/nodemgr.h 2003-03-10 15:38:07.000000000 -0500 @@ -78,6 +78,12 @@ u16 max_rec; /* Maximum packet size node can receive */ }; +enum { + DEV_CLASS_NODE, + DEV_CLASS_UNIT_DIRECTORY, + DEV_CLASS_HOST, +}; + #define UNIT_DIRECTORY_VENDOR_ID 0x01 #define UNIT_DIRECTORY_MODEL_ID 0x02 #define UNIT_DIRECTORY_SPECIFIER_ID 0x04 @@ -89,11 +95,6 @@ * A unit directory corresponds to a protocol supported by the * node. If a node supports eg. IP/1394 and AV/C, its config rom has a * unit directory for each of these protocols. - * - * Unit directories appear on two types of lists: for each node we - * maintain a list of the unit directories found in its config rom and - * for each driver we maintain a list of the unit directories - * (ie. devices) the driver manages. */ struct unit_directory { struct node_entry *ne; /* The node which this directory belongs to */ @@ -108,15 +109,6 @@ quadlet_t specifier_id; quadlet_t version; - struct hpsb_protocol_driver *driver; - void *driver_data; - - /* For linking the nodes managed by the driver, or unmanaged nodes */ - struct list_head driver_list; - - /* For linking directories belonging to a node */ - struct list_head node_list; - unsigned int id; int length; /* Number of quadlets */ @@ -128,7 +120,6 @@ }; struct node_entry { - struct list_head list; u64 guid; /* GUID of this node */ struct hpsb_host *host; /* Host this node is attached to */ nodeid_t nodeid; /* NodeID */ @@ -138,7 +129,6 @@ /* The following is read from the config rom */ u32 vendor_id; u32 capabilities; - struct list_head unit_directories; struct hpsb_tlabel_pool *tpool; @@ -165,11 +155,11 @@ /* Same as above, but use the nodeid to get an node entry. This is not * fool-proof by itself, since the nodeid can change. */ -struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid); +struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid); /* Same as above except that it will not block waiting for the nodemgr * serialize semaphore. */ -struct node_entry *hpsb_check_nodeid(nodeid_t nodeid); +struct node_entry *hpsb_check_nodeid(struct hpsb_host *host, nodeid_t nodeid); /* * If the entry refers to a local host, this function will return the pointer @@ -199,7 +189,7 @@ int extcode, quadlet_t *data, quadlet_t arg); -void init_ieee1394_nodemgr(int disable_hotplug); +void init_ieee1394_nodemgr(void); void cleanup_ieee1394_nodemgr(void); #endif /* _IEEE1394_NODEMGR_H */ Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c 2003-03-10 15:38:07.000000000 -0500 @@ -444,12 +444,10 @@ * Globals */ -static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, +static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, u32 status); -static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, +static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); @@ -464,7 +462,6 @@ static struct hpsb_highlevel *sbp2_hl_handle = NULL; static struct hpsb_highlevel_ops sbp2_hl_ops = { - .add_host = sbp2_add_host, .remove_host = sbp2_remove_host, }; @@ -482,12 +479,12 @@ static struct hpsb_protocol_driver sbp2_driver = { .name = "SBP2 Driver", .id_table = sbp2_id_table, - .probe = sbp2_probe, - .disconnect = sbp2_disconnect, .update = sbp2_update, .driver = { - .name = "sbp2", + .name = SBP2_DEVICE_NAME, .bus = &ieee1394_bus_type, + .probe = sbp2_probe, + .remove = sbp2_remove, }, }; @@ -631,9 +628,9 @@ * This function is called to create a pool of command orbs used for * command processing. It is called when a new sbp2 device is detected. */ -static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id, - struct sbp2scsi_host_info *hi) +static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; int i; unsigned long flags, orbs; struct sbp2_command_info *command; @@ -669,9 +666,9 @@ /* * This function is called to delete a pool of command orbs. */ -static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id, - struct sbp2scsi_host_info *hi) +static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id) { + struct hpsb_host *host = scsi_id->hi->host; struct list_head *lh, *next; struct sbp2_command_info *command; unsigned long flags; @@ -682,11 +679,11 @@ command = list_entry(lh, struct sbp2_command_info, list); /* Release our generic DMA's */ - pci_unmap_single(hi->host->pdev, command->command_orb_dma, + pci_unmap_single(host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), PCI_DMA_BIDIRECTIONAL); SBP2_DMA_FREE("single command orb DMA"); - pci_unmap_single(hi->host->pdev, command->sge_dma, + pci_unmap_single(host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), PCI_DMA_BIDIRECTIONAL); SBP2_DMA_FREE("scatter_gather_element"); @@ -756,8 +753,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *Current_SCpnt, - void (*Current_done)(Scsi_Cmnd *), - struct sbp2scsi_host_info *hi) + void (*Current_done)(Scsi_Cmnd *)) { struct list_head *lh; struct sbp2_command_info *command = NULL; @@ -832,78 +828,86 @@ * IEEE-1394 core driver stack related section *********************************************/ -static int sbp2_probe(struct unit_directory *ud) +static int sbp2_probe(struct device *dev) { + struct unit_directory *ud; struct sbp2scsi_host_info *hi; - SBP2_DEBUG("sbp2_probe"); - hi = sbp2_find_host_info(ud->ne->host); + SBP2_DEBUG(__FUNCTION__); + + ud = container_of(dev, struct unit_directory, device); + + /* This will only add it if it doesn't exist */ + hi = sbp2_add_host(ud->ne->host); + + if (!hi) + return -ENODEV; return sbp2_start_device(hi, ud); } -static void sbp2_disconnect(struct unit_directory *ud) +static int sbp2_remove(struct device *dev) { - struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct unit_directory *ud; + struct scsi_id_instance_data *scsi_id; + + SBP2_DEBUG(__FUNCTION__); - SBP2_DEBUG("sbp2_disconnect"); - hi = sbp2_find_host_info(ud->ne->host); + ud = container_of(dev, struct unit_directory, device); + scsi_id = ud->device.driver_data; + ud->device.driver_data = NULL; - if (hi != NULL) { - sbp2_logout_device(hi, scsi_id); - sbp2_remove_device(hi, scsi_id); + if (scsi_id != NULL) { + sbp2_logout_device(scsi_id); + sbp2_remove_device(scsi_id); } + + return 0; } static void sbp2_update(struct unit_directory *ud) { - struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct scsi_id_instance_data *scsi_id = ud->device.driver_data; + struct sbp2scsi_host_info *hi = scsi_id->hi; unsigned long flags; SBP2_DEBUG("sbp2_update"); - hi = sbp2_find_host_info(ud->ne->host); - if (sbp2_reconnect_device(hi, scsi_id)) { + if (sbp2_reconnect_device(scsi_id)) { /* * Ok, reconnect has failed. Perhaps we didn't * reconnect fast enough. Try doing a regular login. */ - if (sbp2_login_device(hi, scsi_id)) { - + if (sbp2_login_device(scsi_id)) { /* Login failed too, just remove the device. */ SBP2_ERR("sbp2_reconnect_device failed!"); - sbp2_remove_device(hi, scsi_id); - hpsb_release_unit_directory(ud); + sbp2_remove_device(scsi_id); return; } } /* Set max retries to something large on the device. */ - sbp2_set_busy_timeout(hi, scsi_id); + sbp2_set_busy_timeout(scsi_id); /* Do a SBP-2 fetch agent reset. */ - sbp2_agent_reset(hi, scsi_id, 1); + sbp2_agent_reset(scsi_id, 1); /* Get the max speed and packet size that we can use. */ - sbp2_max_speed_and_size(hi, scsi_id); + sbp2_max_speed_and_size(scsi_id); /* Complete any pending commands with busy (so they get * retried) and remove them from our queue */ spin_lock_irqsave(&hi->sbp2_command_lock, flags); - sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); + sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); } -/* - * This function is called after registering our operations in sbp2_init. - * We go ahead and allocate some memory for our host info structure, and - * init some structures. - */ -static void sbp2_add_host(struct hpsb_host *host) +/* This functions is called by the sbp2_probe, for each new device. If the + * host_info already exists, it will return it. If not, it allocated a new + * host_info entry and a corresponding scsi_host. */ +static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; unsigned long flags; @@ -911,11 +915,15 @@ SBP2_DEBUG("sbp2_add_host"); + hi = sbp2_find_host_info(host); + if (hi) + return hi; + /* Register our host with the SCSI stack. */ scsi_host = scsi_register (&scsi_driver_template, sizeof(struct sbp2scsi_host_info)); if (!scsi_host) { SBP2_ERR("failed to register scsi host"); - return; + return NULL; } hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata; @@ -945,7 +953,7 @@ scsi_unregister(hi->scsi_host); } - return; + return hi; } /* @@ -1030,6 +1038,8 @@ goto alloc_fail_first; memset(scsi_id, 0, sizeof(struct scsi_id_instance_data)); + scsi_id->hi = hi; + /* Login FIFO DMA */ scsi_id->login_response = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response), @@ -1058,7 +1068,7 @@ scsi_id->login_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb), &scsi_id->login_orb_dma); - if (scsi_id->login_orb == NULL) { + if (!scsi_id->login_orb) { alloc_fail: if (scsi_id->logout_orb) { pci_free_consistent(hi->host->pdev, @@ -1087,7 +1097,8 @@ kfree(scsi_id); alloc_fail_first: SBP2_ERR ("Could not allocate memory for scsi_id"); - return(-ENOMEM); + + return -ENOMEM; } SBP2_DMA_ALLOC("consistent DMA region for login ORB"); @@ -1098,7 +1109,7 @@ scsi_id->ud = ud; scsi_id->speed_code = SPEED_100; scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100]; - ud->driver_data = scsi_id; + ud->device.driver_data = scsi_id; atomic_set(&scsi_id->sbp2_login_complete, 0); @@ -1131,9 +1142,9 @@ /* * Create our command orb pool */ - if (sbp2util_create_command_orb_pool(scsi_id, hi)) { + if (sbp2util_create_command_orb_pool(scsi_id)) { SBP2_ERR("sbp2util_create_command_orb_pool failed!"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -ENOMEM; } @@ -1142,35 +1153,33 @@ */ if (i == hi->scsi_host->max_id) { SBP2_ERR("No slots left for SBP-2 device"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -EBUSY; } /* * Login to the sbp-2 device */ - if (sbp2_login_device(hi, scsi_id)) { - + if (sbp2_login_device(scsi_id)) { /* Login failed, just remove the device. */ - SBP2_ERR("sbp2_login_device failed"); - sbp2_remove_device(hi, scsi_id); + sbp2_remove_device(scsi_id); return -EBUSY; } /* * Set max retries to something large on the device */ - sbp2_set_busy_timeout(hi, scsi_id); + sbp2_set_busy_timeout(scsi_id); /* * Do a SBP-2 fetch agent reset */ - sbp2_agent_reset(hi, scsi_id, 1); + sbp2_agent_reset(scsi_id, 1); /* * Get the max speed and packet size that we can use */ - sbp2_max_speed_and_size(hi, scsi_id); + sbp2_max_speed_and_size(scsi_id); /* Add this device to the scsi layer now */ sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0); @@ -1185,21 +1194,21 @@ /* * 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) +static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; struct scsi_device *sdev = scsi_find_device(hi->scsi_host, 0, scsi_id->id, 0); SBP2_DEBUG("sbp2_remove_device"); /* Complete any pending commands with selection timeout */ - sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT); + sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* Remove it from the scsi layer now */ - if (scsi_remove_device(sdev)) + if (sdev && scsi_remove_device(sdev)) SBP2_ERR("scsi_remove_device failed"); - sbp2util_remove_command_orb_pool(scsi_id, hi); + sbp2util_remove_command_orb_pool(scsi_id); hi->scsi_id[scsi_id->id] = NULL; @@ -1293,8 +1302,9 @@ * This function is called in order to login to a particular SBP-2 device, * after a bus reset. */ -static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_login_device"); @@ -1420,8 +1430,9 @@ * This function is called in order to logout from a particular SBP-2 * device, usually called during driver unload. */ -static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_logout_device"); @@ -1478,8 +1489,9 @@ * This function is called in order to reconnect to a particular SBP-2 * device, after a bus reset. */ -static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; SBP2_DEBUG("sbp2_reconnect_device"); @@ -1566,8 +1578,8 @@ * This function is called in order to set the busy timeout (number of * retries to attempt) on the sbp2 device. */ -static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) -{ +static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) +{ quadlet_t data; SBP2_DEBUG("sbp2_set_busy_timeout"); @@ -1719,8 +1731,10 @@ * the speed that it needs to use, and the max_rec the host supports, and * it takes care of the rest. */ -static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) +static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) { + struct sbp2scsi_host_info *hi = scsi_id->hi; + SBP2_DEBUG("sbp2_max_speed_and_size"); /* Initial setting comes from the hosts speed map */ @@ -1749,8 +1763,9 @@ /* * This function is called in order to perform a SBP-2 agent reset. */ -static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, int wait) +static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) { + struct sbp2scsi_host_info *hi = scsi_id->hi; struct hpsb_packet *packet; quadlet_t data; @@ -1793,8 +1808,7 @@ * This function is called to create the actual command orb and s/g list * out of the scsi command itself. */ -static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, - struct scsi_id_instance_data *scsi_id, +static int sbp2_create_command_o... [truncated message content] |
From: SVN U. <ben...@li...> - 2003-03-10 20:34:50
|
Author: bencollins Date: 2003-03-10 15:34:07 -0500 (Mon, 10 Mar 2003) New Revision: 832 Modified: trunk/highlevel.c Log: The highlevel ops should not force an add_host callback. So check for it. Modified: trunk/highlevel.c ============================================================================== --- trunk/highlevel.c (original) +++ trunk/highlevel.c 2003-03-10 15:34:08.000000000 -0500 @@ -57,7 +57,8 @@ list_add_tail(&hl->hl_list, &hl_drivers); up(&hl_drivers_lock); - hl_all_hosts(hl->op->add_host); + if (hl->op->add_host) + hl_all_hosts(hl->op->add_host); return hl; } @@ -202,7 +203,8 @@ list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - hl->op->add_host(host); + if (hl->op->add_host) + hl->op->add_host(host); } up(&hl_drivers_lock); } @@ -245,14 +247,11 @@ int channel = (data[0] >> 8) & 0x3f; down(&hl_drivers_lock); - entry = hl_drivers.next; - - while (entry != &hl_drivers) { + list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->iso_receive) { + + if (hl->op->iso_receive) hl->op->iso_receive(host, channel, data, length); - } - entry = entry->next; } up(&hl_drivers_lock); } @@ -265,15 +264,10 @@ int cts = data[0] >> 4; down(&hl_drivers_lock); - entry = hl_drivers.next; - - while (entry != &hl_drivers) { + list_for_each(entry, &hl_drivers) { hl = list_entry(entry, struct hpsb_highlevel, hl_list); - if (hl->op->fcp_request) { - hl->op->fcp_request(host, nodeid, direction, cts, data, - length); - } - entry = entry->next; + if (hl->op->fcp_request) + hl->op->fcp_request(host, nodeid, direction, cts, data, length); } up(&hl_drivers_lock); } @@ -295,7 +289,7 @@ if (as->end > addr) { partlength = min(as->end - addr, (u64) length); - if (as->op->read != NULL) { + if (as->op->read) { rcode = as->op->read(host, nodeid, buffer, addr, partlength, flags); } else { @@ -340,7 +334,7 @@ if (as->end > addr) { partlength = min(as->end - addr, (u64) length); - if (as->op->write != NULL) { + if (as->op->write) { rcode = as->op->write(host, nodeid, destid, data, addr, partlength, flags); } else { @@ -383,7 +377,7 @@ while (as->start <= addr) { if (as->end > addr) { - if (as->op->lock != NULL) { + if (as->op->lock) { rcode = as->op->lock(host, nodeid, store, addr, data, arg, ext_tcode, flags); } else { @@ -416,7 +410,7 @@ while (as->start <= addr) { if (as->end > addr) { - if (as->op->lock64 != NULL) { + if (as->op->lock64) { rcode = as->op->lock64(host, nodeid, store, addr, data, arg, ext_tcode, flags); |
From: SVN U. <ben...@li...> - 2003-03-10 20:14:01
|
Author: bencollins Date: 2003-03-10 15:13:20 -0500 (Mon, 10 Mar 2003) New Revision: 831 Modified: branches/linux-2.4/iso.c Log: Fix hpsb_stop_iso, backport from trunk. Forgot to mention that this was noticed by John Levon. Modified: branches/linux-2.4/iso.c ============================================================================== --- branches/linux-2.4/iso.c (original) +++ branches/linux-2.4/iso.c 2003-03-10 15:13:21.000000000 -0500 @@ -14,7 +14,7 @@ void hpsb_iso_stop(struct hpsb_iso *iso) { - if(!iso->flags & HPSB_ISO_DRIVER_STARTED) + if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) return; iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? |
From: SVN U. <ben...@li...> - 2003-03-10 20:10:47
|
Author: bencollins Date: 2003-03-10 15:09:53 -0500 (Mon, 10 Mar 2003) New Revision: 830 Modified: trunk/iso.c Log: Fix thinko in hpsb_iso_stop where it would never allow it to stop the iso xmit. Modified: trunk/iso.c ============================================================================== --- trunk/iso.c (original) +++ trunk/iso.c 2003-03-10 15:09:54.000000000 -0500 @@ -14,7 +14,7 @@ void hpsb_iso_stop(struct hpsb_iso *iso) { - if(!iso->flags & HPSB_ISO_DRIVER_STARTED) + if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) return; iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? |
From: SVN U. <ben...@li...> - 2003-03-08 07:11:40
|
Author: bencollins Date: 2003-03-08 02:10:59 -0500 (Sat, 08 Mar 2003) New Revision: 829 Modified: trunk/nodemgr.c Log: Hell, let's get real slick and make irm_id and busmgr_id a symlink to the device which is irm or busmgr. Re-arrange a bit for upcoming changes for probe/register of drivers. Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-08 02:11:00.000000000 -0500 @@ -101,11 +101,6 @@ char daemon_name[15]; }; -struct bus_type ieee1394_bus_type = { - .name = "ieee1394", - .hotplug = NULL, - .add = NULL, -}; #define fw_ne_attr(field, type, format_string) \ static ssize_t fw_ne_show_##field (struct device *dev, char *buf)\ @@ -213,22 +208,6 @@ static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_ne_show_tlabels_mask,NULL); -static ssize_t fw_host_show_irm(struct device *dev, char *buf) -{ - struct hpsb_host *host = container_of(dev, struct hpsb_host, device); - return sprintf(buf, NODE_BUS_FMT "\n", NODE_BUS_ARGS(host->irm_id)); -} -static DEVICE_ATTR(irm_id,S_IRUGO,fw_host_show_irm,NULL); - - -static ssize_t fw_host_show_busmgr(struct device *dev, char *buf) -{ - struct hpsb_host *host = container_of(dev, struct hpsb_host, device); - return sprintf(buf, NODE_BUS_FMT "\n", NODE_BUS_ARGS(host->busmgr_id)); -} -static DEVICE_ATTR(busmgr_id,S_IRUGO,fw_host_show_busmgr,NULL); - - static void nodemgr_create_ne_dev_files(struct node_entry *ne) { struct device *dev = &ne->device; @@ -246,6 +225,7 @@ static void nodemgr_create_host_dev_files(struct hpsb_host *host) { struct device *dev = &host->device; + struct node_entry *ne; device_create_file(dev, &dev_attr_host_node_count); device_create_file(dev, &dev_attr_host_selfid_count); @@ -255,8 +235,11 @@ device_create_file(dev, &dev_attr_host_is_cycmst); device_create_file(dev, &dev_attr_host_is_irm); device_create_file(dev, &dev_attr_host_is_busmgr); - device_create_file(dev, &dev_attr_irm_id); - device_create_file(dev, &dev_attr_busmgr_id); + + if ((ne = hpsb_nodeid_get_entry(host->irm_id))) + sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"); + if ((ne = hpsb_nodeid_get_entry(host->busmgr_id))) + sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"); } static void nodemgr_create_ud_dev_files(struct unit_directory *ud) @@ -285,6 +268,17 @@ } } + +static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) +{ + return 0; +} + +struct bus_type ieee1394_bus_type = { + .name = "ieee1394", + .match = nodemgr_bus_match, +}; + static void nodemgr_process_config_rom(struct node_entry *ne, quadlet_t busoptions); @@ -1385,6 +1379,7 @@ static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; + int host_dev_files = 0; /* No userlevel access needed */ daemonize(hi->daemon_name); @@ -1405,6 +1400,12 @@ nodemgr_do_irm_duties(hi->host); up(&nodemgr_serialize); + + /* First time around, let's also create the host dev files */ + if (!host_dev_files) { + nodemgr_create_host_dev_files(hi->host); + host_dev_files = 1; + } } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name); @@ -1530,7 +1531,6 @@ sprintf(hi->daemon_name, "knodemgrd/%d", hi->id); device_register(&host->device); - nodemgr_create_host_dev_files(host); hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); |
From: SVN U. <ben...@li...> - 2003-03-08 06:42:42
|
Author: bencollins Date: 2003-03-08 01:41:48 -0500 (Sat, 08 Mar 2003) New Revision: 828 Modified: trunk/ieee1394_core.c trunk/ieee1394_hotplug.h trunk/nodemgr.c trunk/sbp2.c Log: Add irm_id and busmgr_id to fw-host attributes. Export ieee1394_bus_type. Add device_driver member to hpsb_protocol_driver struct. Start of moving hotplug probe/register to driver-model. Modified: trunk/ieee1394_hotplug.h ============================================================================== --- trunk/ieee1394_hotplug.h (original) +++ trunk/ieee1394_hotplug.h 2003-03-08 01:41:49.000000000 -0500 @@ -1,6 +1,8 @@ #ifndef _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H +#include <linux/device.h> + #include "ieee1394_core.h" #include "nodemgr.h" @@ -64,6 +66,8 @@ /* The list of unit directories managed by this driver */ struct list_head unit_directories; + + struct device_driver driver; }; int hpsb_register_protocol(struct hpsb_protocol_driver *driver); Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2003-03-08 01:41:49.000000000 -0500 @@ -1274,6 +1274,7 @@ EXPORT_SYMBOL(hpsb_register_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol); EXPORT_SYMBOL(hpsb_release_unit_directory); +EXPORT_SYMBOL(ieee1394_bus_type); /** csr.c **/ EXPORT_SYMBOL(hpsb_update_config_rom); Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-08 01:41:49.000000000 -0500 @@ -112,7 +112,7 @@ { \ struct node_entry *ne; \ ne = container_of(dev, struct node_entry, device); \ - return sprintf (buf, format_string, (type)ne->field); \ + return sprintf(buf, format_string, (type)ne->field); \ } \ static struct device_attribute dev_attr_ne_##field = { \ .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ @@ -124,7 +124,7 @@ { \ struct unit_directory *ud; \ ud = container_of(dev, struct unit_directory, device); \ - return sprintf (buf, format_string, (type)ud->field); \ + return sprintf(buf, format_string, (type)ud->field); \ } \ static struct device_attribute dev_attr_ud_##field = { \ .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ @@ -136,7 +136,7 @@ { \ struct hpsb_host *host; \ host = container_of(dev, struct hpsb_host, device); \ - return sprintf (buf, format_string, (type)host->field); \ + return sprintf(buf, format_string, (type)host->field); \ } \ static struct device_attribute dev_attr_host_##field = { \ .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ @@ -176,7 +176,7 @@ { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf (buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) " + return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) " "LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n", ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, @@ -188,7 +188,7 @@ static ssize_t fw_ne_show_tlabels_free(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf (buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1); + return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1); } static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_ne_show_tlabels_free,NULL); @@ -196,7 +196,7 @@ static ssize_t fw_ne_show_tlabels_allocations(struct device *dev, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf (buf, "%u\n", ne->tpool->allocations); + return sprintf(buf, "%u\n", ne->tpool->allocations); } static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_ne_show_tlabels_allocations,NULL); @@ -205,14 +205,30 @@ { struct node_entry *ne = container_of(dev, struct node_entry, device); #if (BITS_PER_LONG <= 32) - return sprintf (buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); + return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); #else - return sprintf (buf, "0x%016lx\n", ne->tpool->pool[0]); + return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); #endif } static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_ne_show_tlabels_mask,NULL); +static ssize_t fw_host_show_irm(struct device *dev, char *buf) +{ + struct hpsb_host *host = container_of(dev, struct hpsb_host, device); + return sprintf(buf, NODE_BUS_FMT "\n", NODE_BUS_ARGS(host->irm_id)); +} +static DEVICE_ATTR(irm_id,S_IRUGO,fw_host_show_irm,NULL); + + +static ssize_t fw_host_show_busmgr(struct device *dev, char *buf) +{ + struct hpsb_host *host = container_of(dev, struct hpsb_host, device); + return sprintf(buf, NODE_BUS_FMT "\n", NODE_BUS_ARGS(host->busmgr_id)); +} +static DEVICE_ATTR(busmgr_id,S_IRUGO,fw_host_show_busmgr,NULL); + + static void nodemgr_create_ne_dev_files(struct node_entry *ne) { struct device *dev = &ne->device; @@ -239,6 +255,8 @@ device_create_file(dev, &dev_attr_host_is_cycmst); device_create_file(dev, &dev_attr_host_is_irm); device_create_file(dev, &dev_attr_host_is_busmgr); + device_create_file(dev, &dev_attr_irm_id); + device_create_file(dev, &dev_attr_busmgr_id); } static void nodemgr_create_ud_dev_files(struct unit_directory *ud) @@ -1021,6 +1039,9 @@ if (down_interruptible(&nodemgr_serialize)) return -EINTR; + if (driver->driver.name[0]) + driver_register(&driver->driver); + list_add_tail(&driver->list, &driver_list); INIT_LIST_HEAD(&driver->unit_directories); @@ -1354,7 +1375,7 @@ if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { /* The root node does not have a valid BROADCAST_CHANNEL * register and we do, so reset the bus with force_root set */ - HPSB_INFO("Remote root is not IRM capable, resetting..."); + HPSB_DEBUG("Remote root is not IRM capable, resetting..."); hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); return 0; } Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c 2003-03-08 01:41:49.000000000 -0500 @@ -480,13 +480,18 @@ #endif static struct hpsb_protocol_driver sbp2_driver = { - .name = "SBP2 Driver", - .id_table = sbp2_id_table, - .probe = sbp2_probe, - .disconnect = sbp2_disconnect, - .update = sbp2_update + .name = "SBP2 Driver", + .id_table = sbp2_id_table, + .probe = sbp2_probe, + .disconnect = sbp2_disconnect, + .update = sbp2_update, + .driver = { + .name = "sbp2", + .bus = &ieee1394_bus_type, + }, }; + /* List of device firmware's that require a forced 36 byte inquiry. */ static u32 sbp2_broken_inquiry_list[] = { 0x00002800, /* Stefan Richter <ric...@ba...> */ |
From: SVN U. <dm...@li...> - 2003-03-08 05:56:56
|
Author: dmaas Date: 2003-03-08 00:56:14 -0500 (Sat, 08 Mar 2003) New Revision: 827 Modified: branches/linux-2.4/csr.c branches/linux-2.4/csr.h branches/linux-2.4/eth1394.c branches/linux-2.4/eth1394.h branches/linux-2.4/hosts.h branches/linux-2.4/ieee1394_core.c branches/linux-2.4/ieee1394_transactions.c branches/linux-2.4/ieee1394_transactions.h branches/linux-2.4/ieee1394_types.h branches/linux-2.4/nodemgr.c branches/linux-2.4/ohci1394.c Log: * Steve Kinneberg (kin...@ac...) wrote: > Attached is a patch to the 2.4 SVN branch that implements the rest of > the GASP support. - added ohci1394 bus reset taxonomy - added hpsb_lock64 - updated eth1394 Modified: branches/linux-2.4/ieee1394_core.c ============================================================================== --- branches/linux-2.4/ieee1394_core.c (original) +++ branches/linux-2.4/ieee1394_core.c 2003-03-08 00:56:16.000000000 -0500 @@ -1196,6 +1196,8 @@ EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_lock); +EXPORT_SYMBOL(hpsb_lock64); +EXPORT_SYMBOL(hpsb_send_gasp); /** highlevel.c **/ EXPORT_SYMBOL(hpsb_register_highlevel); Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-03-08 00:56:16.000000000 -0500 @@ -30,8 +30,10 @@ * . DMA mmap for iso receive * . Config ROM generation * + * Things implemented, but still in test phase: + * . Async Stream Packets Transmit (Receive done via Iso interface) + * * Things not implemented: - * . Async Stream Packets * . DMA error recovery * * Known bugs: @@ -890,12 +892,63 @@ struct ti_ohci *ohci = host->hostdata; int retval = 0; unsigned long flags; + int phy_reg; switch (cmd) { case RESET_BUS: DBGMSG(ohci->id, "devctl: Bus reset requested%s", attempt_root ? " and attempting to become root" : ""); set_phy_reg_mask (ohci, 1, 0x40 | (attempt_root ? 0x80 : 0)); + //set_phy_reg_mask (ohci, 1, 0x40 | (attempt_root ? 0x80 : 0)); + switch (arg) { + case SHORT_RESET: + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0x40 | (attempt_root ? 0x80 : 0); + set_phy_reg(ohci, 1, phy_reg); /* set IBR */ + break; + case SHORT_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (phy_reg & 0x80) { + phy_reg &= ~0x80 | (attempt_root ? 0x80 : 0); + set_phy_reg(ohci, 1, phy_reg); /* clear RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg &= ~0x80; + phy_reg |= 0x40 | (attempt_root ? 0x80 : 0); + set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (!(phy_reg & 0x80)) { + phy_reg |= 0x80; + set_phy_reg(ohci, 1, phy_reg); /* set RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0xc0; + set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */ + break; + default: + retval = -1; + } + + break; case GET_CYCLE_COUNTER: Modified: branches/linux-2.4/ieee1394_transactions.c ============================================================================== --- branches/linux-2.4/ieee1394_transactions.c (original) +++ branches/linux-2.4/ieee1394_transactions.c 2003-03-08 00:56:16.000000000 -0500 @@ -12,6 +12,7 @@ #include <linux/sched.h> #include <asm/errno.h> #include <asm/bitops.h> +#include <linux/interrupt.h> #include "ieee1394.h" #include "ieee1394_types.h" @@ -146,6 +147,17 @@ packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */ } +void fill_async_stream_packet(struct hpsb_packet *packet, int length, + int channel, int tag, int sync) +{ + packet->header[0] = (length << 16) | (tag << 14) | (channel << 8) + | (TCODE_STREAM_DATA << 4) | sync; + + packet->header_size = 4; + packet->data_size = length; + packet->type = hpsb_async; + packet->tcode = TCODE_ISO_DATA; +} /** * get_tlabel - allocate a transaction label @@ -537,7 +549,6 @@ } -/* We need a hpsb_lock64 function for the 64 bit equivalent. Probably. */ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, quadlet_t *data, quadlet_t arg) { @@ -591,3 +602,109 @@ return retval; } + +int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, + u64 addr, int extcode, octlet_t *data, octlet_t arg) +{ + struct hpsb_packet *packet; + int retval = 0; + + BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet + + packet = hpsb_make_lock64packet(host, node, addr, extcode); + + switch (extcode) { + case EXTCODE_MASK_SWAP: + case EXTCODE_COMPARE_SWAP: + case EXTCODE_BOUNDED_ADD: + case EXTCODE_WRAP_ADD: + packet->data[0] = (arg >> 32); + packet->data[1] = (arg & 0xffffffff); + packet->data[2] = (*data >> 32); + packet->data[3] = (*data & 0xffffffff); + break; + case EXTCODE_FETCH_ADD: + case EXTCODE_LITTLE_ADD: + packet->data[0] = (*data >> 32); + packet->data[1] = (*data & 0xffffffff); + break; + default: + return -EINVAL; + } + + if (!packet) + return -ENOMEM; + + packet->generation = generation; + if (!hpsb_send_packet(packet)) { + retval = -EINVAL; + goto hpsb_lock64_fail; + } + down(&packet->state_change); + down(&packet->state_change); + retval = hpsb_packet_success(packet); + + if (retval == 0) + *data = (u64)packet->data[1] << 32 | packet->data[0]; + +hpsb_lock64_fail: + free_tlabel(host, node, packet->tlabel); + free_hpsb_packet(packet); + + return retval; +} + +int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, + quadlet_t *buffer, size_t length, u32 specifier_id, + unsigned int version) +{ +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG + int i; +#endif + + struct hpsb_packet *packet; + int retval = 0; + u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8; + u8 specifier_id_lo = specifier_id & 0xff; + +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG + HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length); +#endif + + length += 8; + + packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + if (!packet) + return -ENOMEM; + + if (length % 4) { + packet->data[length / 4] = 0; + } + + packet->host = host; + fill_async_stream_packet(packet, length, channel, 3, 0); + + packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi); + packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff)); + + memcpy(&(packet->data[2]), buffer, length - 4); + +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG + HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size); + HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size); + + for(i=0; i<(packet->data_size/4); i++) + HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i])); +#endif + + packet->generation = generation; + + packet->no_waiter = 1; + + if (!hpsb_send_packet(packet)) { + free_hpsb_packet(packet); + retval = -EINVAL; + } + + return retval; +} Modified: branches/linux-2.4/ieee1394_transactions.h ============================================================================== --- branches/linux-2.4/ieee1394_transactions.h (original) +++ branches/linux-2.4/ieee1394_transactions.h 2003-03-08 00:56:16.000000000 -0500 @@ -75,6 +75,11 @@ u64 addr, quadlet_t *buffer, size_t length); int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, quadlet_t *data, quadlet_t arg); +int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, + u64 addr, int extcode, octlet_t *data, octlet_t arg); +int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, + quadlet_t *buffer, size_t length, u32 specifier_id, + unsigned int version); /* Generic packet creation. Used by hpsb_write. Also useful for protocol * drivers that want to implement their own hpsb_write replacement. */ Modified: branches/linux-2.4/nodemgr.c ============================================================================== --- branches/linux-2.4/nodemgr.c (original) +++ branches/linux-2.4/nodemgr.c 2003-03-08 00:56:16.000000000 -0500 @@ -1170,6 +1170,52 @@ return; } +/* 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 + * bit). */ +static void nodemgr_do_irm_duties(struct hpsb_host *host) +{ + quadlet_t bc; + + if (!host->is_irm) + return; + + host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ + + bc = cpu_to_be32(host->csr.broadcast_channel); + + hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, + sizeof(quadlet_t)); +} + +/* 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 + * ourselves. */ +static int nodemgr_check_root_capability(struct hpsb_host *host) +{ + quadlet_t bc; + int status; + + if (host->is_irm) + return 1; + + status = hpsb_read(host, LOCAL_BUS | (host->irm_id), + get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, sizeof(quadlet_t)); + + if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { + /* The root node does not have a valid BROADCAST_CHANNEL + * register and we do, so reset the bus with force_root set */ + HPSB_INFO("Remote root is not IRM capable, resetting..."); + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + return 0; + } + return 1; +} + static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; @@ -1183,7 +1229,16 @@ * happens when we get a bus reset. */ while (!down_interruptible(&hi->reset_sem) && !down_interruptible(&nodemgr_serialize)) { + + if (!nodemgr_check_root_capability(hi->host)) { + /* Do nothing, we are resetting */ + up(&nodemgr_serialize); + continue; + } + nodemgr_node_probe(hi->host); + nodemgr_do_irm_duties(hi->host); + up(&nodemgr_serialize); } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG Modified: branches/linux-2.4/eth1394.c ============================================================================== --- branches/linux-2.4/eth1394.c (original) +++ branches/linux-2.4/eth1394.c 2003-03-08 00:56:16.000000000 -0500 @@ -65,6 +65,7 @@ #include "ieee1394_transactions.h" #include "ieee1394.h" #include "highlevel.h" +#include "iso.h" #include "eth1394.h" #define ETH1394_PRINT_G(level, fmt, args...) \ @@ -101,6 +102,9 @@ MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); MODULE_LICENSE("GPL"); +static void ether1394_iso(struct hpsb_iso *iso); + + /* Find our host_info struct for a given host pointer. Must be called * under spinlock. */ static inline struct host_info *find_host_info (struct hpsb_host *host) @@ -178,15 +182,26 @@ * XXX: This is where we need to create a list of skb's for fragmented * packets. */ static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev, - int proto) + int proto, struct packet_task *ptask) { union eth1394_hdr *hdr = (union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]); + hdr->words.word1 = 0; hdr->common.lf = ETH1394_HDR_LF_UF; hdr->words.word1 = htons(hdr->words.word1); hdr->uf.ether_type = proto; + /* Set the transmission type for the packet. Right now only ARP + * packets are sent via GASP. IP broadcast and IP multicast are not + * yet supported properly, they too should use GASP. */ + switch(proto) { + case __constant_htons(ETH_P_ARP): + ptask->tx_type = ETH1394_GASP; + break; + default: + ptask->tx_type = ETH1394_WRREQ; + } return; } @@ -199,7 +214,7 @@ { struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); - u16 phy_id = priv->host->node_id & NODE_MASK; + u16 phy_id = NODEID_TO_NODE(priv->host->node_id); unsigned char *arp_ptr = (unsigned char *)skb->data; struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; @@ -279,7 +294,8 @@ { unsigned long flags; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - int phy_id = priv->host->node_id & NODE_MASK; + int phy_id = NODEID_TO_NODE(priv->host->node_id); + struct hpsb_host *host = priv->host; spin_lock_irqsave (&priv->lock, flags); @@ -289,20 +305,23 @@ memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi)); memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo)); + priv->bc_state = ETHER1394_BC_CHECK; + /* Register our limits now */ - ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf, - priv->host->speed_map[(phy_id << 6) + phy_id], - (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) | - be32_to_cpu(priv->host->csr.rom[4])), + ether1394_register_limits (phy_id, (be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf, + host->speed_map[(phy_id << 6) + phy_id], + (u64)(((u64)be32_to_cpu(host->csr.rom[3]) << 32) | + be32_to_cpu(host->csr.rom[4])), ETHER1394_REGION_ADDR >> 32, ETHER1394_REGION_ADDR & 0xffffffff, priv); /* We'll use our max_rec as the default mtu */ if (set_mtu) - dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr); + dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */ + (sizeof (union eth1394_hdr) + 8); /* (hdr + GASP) */ /* Set our hardware address while we're at it */ - *(nodeid_t *)dev->dev_addr = htons (priv->host->node_id); + *(nodeid_t *)dev->dev_addr = htons (host->node_id); spin_unlock_irqrestore (&priv->lock, flags); } @@ -360,7 +379,7 @@ priv->host = host; hi = (struct host_info *)kmalloc (sizeof (struct host_info), - GFP_KERNEL); + in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); if (hi == NULL) goto out; @@ -383,6 +402,15 @@ list_add_tail (&hi->list, &host_info_list); spin_unlock_irq (&host_info_lock); + /* Ignore validity in hopes that it will be set in the future. It'll + * check it on transmit. */ + priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; + + priv->iso = hpsb_iso_recv_init(host, 8 * 4096, 8, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + priv->bc_state = ETHER1394_BC_CLOSED; + } return; out: @@ -396,11 +424,14 @@ /* Remove a card from our list */ static void ether1394_remove_host (struct hpsb_host *host) { + struct eth1394_priv *priv; struct host_info *hi; spin_lock_irq (&host_info_lock); hi = find_host_info (host); if (hi != NULL) { + priv = (struct eth1394_priv *)hi->dev->priv; + priv->bc_state = ETHER1394_BC_CLOSED; unregister_netdev (hi->dev); kfree (hi->dev); list_del (&hi->list); @@ -480,7 +511,7 @@ * about the sending machine. */ if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) { unsigned long flags; - u16 phy_id = srcid & NODE_MASK; + u16 phy_id = NODEID_TO_NODE(srcid); struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_arp arp1394; @@ -591,6 +622,104 @@ return RCODE_COMPLETE; } +static void ether1394_iso(struct hpsb_iso *iso) +{ + struct sk_buff *skb; + quadlet_t *data; + char *buf; + int flags; + struct net_device *dev = ether1394_find_dev(iso->host); + struct eth1394_priv *priv; + unsigned int len; + u32 specifier_id; + u16 source_id; + int i; + int nready; + + if (dev == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n", + iso->host->driver->name); + return; + } + + nready = hpsb_iso_n_ready(iso); + for(i = 0; i < nready; i++) { + struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; + data = (quadlet_t*) (iso->data_buf.kvirt + info->offset); + + /* skip over GASP header */ + buf = (char *)data + 8; + len = info->len - 8; + + specifier_id = (((be32_to_cpu(data[0]) & 0xffff) << 8) | + ((be32_to_cpu(data[1]) & 0xff000000) >> 24)); + source_id = be32_to_cpu(data[0]) >> 16; + + priv = (struct eth1394_priv *)dev->priv; + + if (info->channel != priv->broadcast_channel || + specifier_id != ETHER1394_GASP_SPECIFIER_ID) { + /* This packet is not for us */ + continue; + } + + /* A packet has been received by the ieee1394 bus. Build an skbuff + * around it so we can pass it to the high level network layer. */ + skb = dev_alloc_skb (len + dev->hard_header_len + 15); + if (!skb) { + HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n"); + priv->stats.rx_dropped++; + break; + } + + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); + + memcpy (skb_put (skb, len), buf, len); + + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + + /* Parse the encapsulation header. This actually does the job of + * converting to an ethernet frame header, aswell as arp + * conversion if needed. ARP conversion is easier in this + * direction, since we are using ethernet as our backend. */ + skb->protocol = ether1394_parse_encap (skb, dev, source_id, + LOCAL_BUS | ALL_NODES); + + spin_lock_irqsave (&priv->lock, flags); + if (!skb->protocol) { + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + goto bad_proto; + } + + netif_stop_queue(dev); + if (netif_rx (skb) == NET_RX_DROP) { + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + goto bad_proto; + } + + /* Statistics */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + bad_proto: + spin_unlock_irqrestore (&priv->lock, flags); + } + + hpsb_iso_recv_release_packets(iso, i); + + netif_start_queue(dev); + + dev->last_rx = jiffies; + + return; +} + + /* This function is our scheduled write */ static void hpsb_write_sched (void *__ptask) { @@ -599,12 +728,25 @@ struct net_device *dev = ptask->skb->dev; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; unsigned long flags; + int status; + + if (ptask->tx_type == ETH1394_GASP) { + status = hpsb_send_gasp(priv->host, priv->broadcast_channel, + get_hpsb_generation(priv->host), + (quadlet_t *)skb->data, skb->len, + ETHER1394_GASP_SPECIFIER_ID, + ETHER1394_GASP_VERSION); + } else { + status = hpsb_write(priv->host, ptask->dest_node, + get_hpsb_generation(priv->host), + ptask->addr, (quadlet_t *)skb->data, + skb->len); + } + /* Statistics */ spin_lock_irqsave (&priv->lock, flags); - if (!hpsb_write(priv->host, ptask->dest_node, - get_hpsb_generation(priv->host), - ptask->addr, (quadlet_t *)skb->data, skb->len)) { + if (!status) { priv->stats.tx_bytes += skb->len; priv->stats.tx_packets++; } else { @@ -636,6 +778,67 @@ struct packet_task *ptask = NULL; int ret = 0; + spin_lock_irqsave (&priv->lock, flags); + if (priv->bc_state == ETHER1394_BC_CLOSED) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Cannot send packet, no broadcast channel available."); + ret = -EAGAIN; + goto fail; + } + + /* First time sending? Need a broadcast channel for ARP and for + * listening on */ + if (priv->bc_state == ETHER1394_BC_CHECK) { + quadlet_t bc; + + /* Get the local copy of the broadcast channel and check its + * validity (the IRM should validate it for us) */ + + bc = priv->host->csr.broadcast_channel; + + if ((bc & 0xc0000000) != 0xc0000000) { + /* broadcast channel not validated yet */ + ETH1394_PRINT(KERN_WARNING, dev->name, + "Error BROADCAST_CHANNEL register valid " + "bit not set, can't send IP traffic\n"); + hpsb_iso_shutdown(priv->iso); + priv->bc_state = ETHER1394_BC_CLOSED; + ret = -EAGAIN; + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + if (priv->broadcast_channel != (bc & 0x3f)) { + /* This really shouldn't be possible, but just in case + * the IEEE 1394 spec changes regarding broadcast + * channels in the future. */ + hpsb_iso_shutdown(priv->iso); + + priv->broadcast_channel = bc & 0x3f; + ETH1394_PRINT(KERN_WARNING, dev->name, + "Changing to broadcast channel %d...\n", + priv->broadcast_channel); + + priv->iso = hpsb_iso_recv_init(priv->host, 8 * 4096, + 8, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + ret = -EAGAIN; + goto fail; + } + } + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Could not start async reception\n"); + hpsb_iso_shutdown(priv->iso); + priv->bc_state = ETHER1394_BC_CLOSED; + ret = -EAGAIN; + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + priv->bc_state = ETHER1394_BC_OPENED; + } + spin_unlock_irqrestore (&priv->lock, flags); + if ((skb = skb_share_check (skb, kmflags)) == NULL) { ret = -ENOMEM; goto fail; @@ -654,8 +857,14 @@ if (proto == __constant_htons (ETH_P_ARP)) ether1394_arp_to_1394arp (skb, dev); + ptask = kmem_cache_alloc(packet_task_cache, kmflags); + if (ptask == NULL) { + ret = -ENOMEM; + goto fail; + } + /* Now add our encapsulation header */ - ether1394_encapsulate (skb, dev, proto); + ether1394_encapsulate (skb, dev, proto, ptask); /* TODO: The above encapsulate function needs to recognize when a * packet needs to be split for a specified node. It should create @@ -663,26 +872,22 @@ * call to schedule our writes. */ /* XXX: Right now we accept that we don't exactly follow RFC. When - * we do, we will send ARP requests via GASP format, and so we wont + * we do, we will send ARP requests via GASP format, and so we won't * need this hack. */ spin_lock_irqsave (&priv->lock, flags); - addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 | - priv->fifo_lo[dest_node & NODE_MASK]; + addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 | + priv->fifo_lo[NODEID_TO_NODE(dest_node)]; spin_unlock_irqrestore (&priv->lock, flags); if (!addr) addr = ETHER1394_REGION_ADDR; - ptask = kmem_cache_alloc(packet_task_cache, kmflags); - if (ptask == NULL) { - ret = -ENOMEM; - goto fail; - } - ptask->skb = skb; ptask->addr = addr; ptask->dest_node = dest_node; + /* TODO: When 2.4 is out of the way, give each of our ethernet + * dev's a workqueue to handle these. */ INIT_TQUEUE(&ptask->tq, hpsb_write_sched, ptask); schedule_task(&ptask->tq); @@ -700,7 +905,7 @@ netif_wake_queue (dev); spin_unlock_irqrestore (&priv->lock, flags); - return ret; + return 0; /* returning non-zero causes serious problems */ } /* Function for incoming 1394 packets */ @@ -736,6 +941,19 @@ static void __exit ether1394_exit_module (void) { + struct list_head *lh; + struct host_info *hi; + struct eth1394_priv *priv; + + lh = host_info_list.next; + while (lh != &host_info_list) { + hi = list_entry (lh, struct host_info, list); + priv = (struct eth1394_priv*)hi->dev->priv; + if (priv->bc_state != ETHER1394_BC_CLOSED) { + hpsb_iso_shutdown(priv->iso); + } + lh = lh->next; + } hpsb_unregister_highlevel (hl_handle); kmem_cache_destroy(packet_task_cache); } Modified: branches/linux-2.4/hosts.h ============================================================================== --- branches/linux-2.4/hosts.h (original) +++ branches/linux-2.4/hosts.h 2003-03-08 00:56:17.000000000 -0500 @@ -142,7 +142,13 @@ /* Short (arbitrated) reset -- only available on 1394a capable IEEE 1394 capable controllers */ - SHORT_RESET + SHORT_RESET, + + /* Variants, that set force_root before issueing the bus reset */ + LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT, + + /* Variants, that clear force_root before issueing the bus reset */ + LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT }; struct hpsb_host_driver { Modified: branches/linux-2.4/eth1394.h ============================================================================== --- branches/linux-2.4/eth1394.h (original) +++ branches/linux-2.4/eth1394.h 2003-03-08 00:56:17.000000000 -0500 @@ -30,9 +30,16 @@ #define ETHER1394_REGION_ADDR 0xfffff0200000ULL #define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) +/* GASP identifier numbers for IPv4 over IEEE 1394 */ +#define ETHER1394_GASP_SPECIFIER_ID 0x00005E +#define ETHER1394_GASP_VERSION 1 + /* Node set == 64 */ #define NODE_SET (ALL_NODES + 1) +enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, + ETHER1394_BC_CHECK }; + /* Private structure for our ethernet driver */ struct eth1394_priv { struct net_device_stats stats; /* Device stats */ @@ -43,6 +50,9 @@ u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */ u64 eui[ALL_NODES]; /* EUI-64 per node */ spinlock_t lock; /* Private lock */ + int broadcast_channel; /* Async stream Broadcast Channel */ + enum eth1394_bc_states bc_state; /* broadcast channel state */ + struct hpsb_iso *iso; /* Async stream recv handle */ }; struct host_info { @@ -51,12 +61,15 @@ struct net_device *dev; }; +typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; + /* This is our task struct. It's used for the packet complete callback. */ struct packet_task { struct sk_buff *skb; /* Socket buffer we are sending */ nodeid_t dest_node; /* Destination of the packet */ u64 addr; /* Address */ struct tq_struct tq; /* The task */ + eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */ }; /* IP1394 headers */ Modified: branches/linux-2.4/ieee1394_types.h ============================================================================== --- branches/linux-2.4/ieee1394_types.h (original) +++ branches/linux-2.4/ieee1394_types.h 2003-03-08 00:56:17.000000000 -0500 @@ -32,6 +32,9 @@ #define LOCAL_BUS 0xffc0 #define ALL_NODES 0x003f +#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT) +#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK) + /* Can be used to consistently print a node/bus ID. */ #define NODE_BUS_FMT "%02d:%04d" #define NODE_BUS_ARGS(nodeid) \ Modified: branches/linux-2.4/csr.c ============================================================================== --- branches/linux-2.4/csr.c (original) +++ branches/linux-2.4/csr.c 2003-03-08 00:56:17.000000000 -0500 @@ -54,8 +54,15 @@ host->csr.bus_manager_id = 0x3f; host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = ~0; + host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ host->csr.channels_available_lo = ~0; + host->csr.broadcast_channel = 0x80000000 | 31; + + if (host->is_irm) { + if (host->driver->hw_csr_reg) { + host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); + } + } host->csr.node_ids = host->node_id << 16; @@ -95,8 +102,15 @@ host->csr.bus_time = 0; host->csr.bus_manager_id = 0x3f; host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = ~0; + host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ host->csr.channels_available_lo = ~0; + host->csr.broadcast_channel = 0x80000000 | 31; + + if (host->is_irm) { + if (host->driver->hw_csr_reg) { + host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); + } + } } int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, @@ -268,6 +282,10 @@ *(buf++) = cpu_to_be32(ret); out; + case CSR_BROADCAST_CHANNEL: + *(buf++) = cpu_to_be32(host->csr.broadcast_channel); + out; + /* address gap to end - fall through to default */ default: return RCODE_ADDRESS_ERROR; @@ -345,6 +363,12 @@ /* these are not writable, only lockable */ return RCODE_TYPE_ERROR; + case CSR_BROADCAST_CHANNEL: + /* only the valid bit can be written */ + host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000) + | (be32_to_cpu(*data) & 0x40000000); + out; + /* address gap to end - fall through */ default: return RCODE_ADDRESS_ERROR; @@ -373,6 +397,18 @@ data = be32_to_cpu(data); arg = be32_to_cpu(arg); + /* Is somebody releasing the broadcast_channel on us? */ + if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) { + /* Note: this is may not be the right way to handle + * the problem, so we should look into the proper way + * eventually. */ + HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " + "broadcast channel 31. Ignoring.", + NODE_BUS_ARGS(nodeid)); + + data &= ~0x1; /* keep broadcast channel allocated */ + } + if (host->driver->hw_csr_reg) { quadlet_t old; @@ -389,23 +425,84 @@ switch (csraddr) { case CSR_BUS_MANAGER_ID: regptr = &host->csr.bus_manager_id; + *store = cpu_to_be32(*regptr); + if (*regptr == arg) + *regptr = data; break; case CSR_BANDWIDTH_AVAILABLE: + { + quadlet_t bandwidth; + quadlet_t old; + quadlet_t new; + regptr = &host->csr.bandwidth_available; + old = *regptr; + + /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */ + if (arg > 0x1fff) { + *store = cpu_to_be32(old); /* change nothing */ break; + } + data &= 0x1fff; + if (arg >= data) { + /* allocate bandwidth */ + bandwidth = arg - data; + if (old >= bandwidth) { + new = old - bandwidth; + *store = cpu_to_be32(arg); + *regptr = new; + } else { + *store = cpu_to_be32(old); + } + } else { + /* deallocate bandwidth */ + bandwidth = data - arg; + if (old + bandwidth < 0x2000) { + new = old + bandwidth; + *store = cpu_to_be32(arg); + *regptr = new; + } else { + *store = cpu_to_be32(old); + } + } + break; + } case CSR_CHANNELS_AVAILABLE_HI: + { + /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ + quadlet_t affected_channels = arg ^ data; + regptr = &host->csr.channels_available_hi; + + if ((arg & affected_channels) == (*regptr & affected_channels)) { + *regptr ^= affected_channels; + *store = cpu_to_be32(arg); + } else { + *store = cpu_to_be32(*regptr); + } + break; + } case CSR_CHANNELS_AVAILABLE_LO: + { + /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ + quadlet_t affected_channels = arg ^ data; + regptr = &host->csr.channels_available_lo; + + if ((arg & affected_channels) == (*regptr & affected_channels)) { + *regptr ^= affected_channels; + *store = cpu_to_be32(arg); + } else { + *store = cpu_to_be32(*regptr); + } break; } + } - *store = cpu_to_be32(*regptr); - if (*regptr == arg) *regptr = data; spin_unlock_irqrestore(&host->csr.lock, flags); return RCODE_COMPLETE; @@ -420,10 +517,7 @@ case CSR_SPLIT_TIMEOUT_LO: case CSR_CYCLE_TIME: case CSR_BUS_TIME: - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: + case CSR_BROADCAST_CHANNEL: return RCODE_TYPE_ERROR; case CSR_BUSY_TIMEOUT: @@ -433,6 +527,97 @@ } } +static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, + u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl) +{ + int csraddr = addr - CSR_REGISTER_BASE; + unsigned long flags; + + data = be64_to_cpu(data); + arg = be64_to_cpu(arg); + + if (csraddr & 0x3) + return RCODE_TYPE_ERROR; + + if (csraddr != CSR_CHANNELS_AVAILABLE + || extcode != EXTCODE_COMPARE_SWAP) + goto unsupported_lock64req; + + /* Is somebody releasing the broadcast_channel on us? */ + if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) { + /* Note: this is may not be the right way to handle + * the problem, so we should look into the proper way + * eventually. */ + HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " + "broadcast channel 31. Ignoring.", + NODE_BUS_ARGS(nodeid)); + + data &= ~0x100000000ULL; /* keep broadcast channel allocated */ + } + + if (host->driver->hw_csr_reg) { + quadlet_t data_hi, data_lo; + quadlet_t arg_hi, arg_lo; + quadlet_t old_hi, old_lo; + + data_hi = data >> 32; + data_lo = data & 0xFFFFFFFF; + arg_hi = arg >> 32; + arg_lo = arg & 0xFFFFFFFF; + + old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2, + data_hi, arg_hi); + + old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2, + data_lo, arg_lo); + + *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo); + } else { + octlet_t old; + octlet_t affected_channels = arg ^ data; + + spin_lock_irqsave(&host->csr.lock, flags); + + old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo; + + if ((arg & affected_channels) == (old & affected_channels)) { + host->csr.channels_available_hi ^= (affected_channels >> 32); + host->csr.channels_available_lo ^= (affected_channels & 0xffffffff); + *store = cpu_to_be64(arg); + } else { + *store = cpu_to_be64(old); + } + + spin_unlock_irqrestore(&host->csr.lock, flags); + } + + /* Is somebody erroneously releasing the broadcast_channel on us? */ + if (host->csr.channels_available_hi & 0x1) + host->csr.channels_available_hi &= ~0x1; + + return RCODE_COMPLETE; + + unsupported_lock64req: + switch (csraddr) { + case CSR_STATE_CLEAR: + case CSR_STATE_SET: + case CSR_RESET_START: + case CSR_NODE_IDS: + case CSR_SPLIT_TIMEOUT_HI: + case CSR_SPLIT_TIMEOUT_LO: + case CSR_CYCLE_TIME: + case CSR_BUS_TIME: + case CSR_BUS_MANAGER_ID: + case CSR_BROADCAST_CHANNEL: + case CSR_BUSY_TIMEOUT: + case CSR_BANDWIDTH_AVAILABLE: + return RCODE_TYPE_ERROR; + + default: + return RCODE_ADDRESS_ERROR; + } +} + static int write_fcp(struct hpsb_host *host, int nodeid, int dest, quadlet_t *data, u64 addr, unsigned int length, u16 flags) { @@ -474,6 +659,7 @@ .read = read_regs, .write = write_regs, .lock = lock_regs, + .lock64 = lock64_regs, }; static struct hpsb_highlevel *hl; Modified: branches/linux-2.4/csr.h ============================================================================== --- branches/linux-2.4/csr.h (original) +++ branches/linux-2.4/csr.h 2003-03-08 00:56:17.000000000 -0500 @@ -16,8 +16,10 @@ #define CSR_BUSY_TIMEOUT 0x210 #define CSR_BUS_MANAGER_ID 0x21c #define CSR_BANDWIDTH_AVAILABLE 0x220 +#define CSR_CHANNELS_AVAILABLE 0x224 #define CSR_CHANNELS_AVAILABLE_HI 0x224 #define CSR_CHANNELS_AVAILABLE_LO 0x228 +#define CSR_BROADCAST_CHANNEL 0x234 #define CSR_CONFIG_ROM 0x400 #define CSR_CONFIG_ROM_END 0x800 #define CSR_FCP_COMMAND 0xB00 @@ -40,6 +42,7 @@ quadlet_t bus_manager_id; quadlet_t bandwidth_available; quadlet_t channels_available_hi, channels_available_lo; + quadlet_t broadcast_channel; quadlet_t *rom; size_t rom_size; |
From: SVN U. <dm...@li...> - 2003-03-08 05:39:45
|
Author: dmaas Date: 2003-03-08 00:38:58 -0500 (Sat, 08 Mar 2003) New Revision: 826 Modified: branches/linux-2.4/ohci1394.c Log: revert bogus ohci1394 bus reset IRQ handler patch from rev 818 - cures infinite loop on module load Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-03-08 00:39:00.000000000 -0500 @@ -2251,25 +2251,21 @@ } if (event & OHCI1394_busReset) { - int loops = 0; - /* The busReset event bit can't be cleared during the * selfID phase, so we disable busReset interrupts, to * avoid burying the cpu in interrupt requests. */ spin_lock_irqsave(&ohci->event_lock, flags); reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); - udelay(10); - while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { - if (loops++ > 10000) { - hpsb_reset_bus(host, 1); - loops = 0; - DBGMSG(ohci->id, "Out of control loop, resetting"); - } - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - spin_unlock_irqrestore(&ohci->event_lock, flags); - udelay(10); - spin_lock_irqsave(&ohci->event_lock, flags); + 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); |
From: SVN U. <ben...@li...> - 2003-03-08 03:28:23
|
Author: bencollins Date: 2003-03-07 22:27:27 -0500 (Fri, 07 Mar 2003) New Revision: 825 Modified: trunk/nodemgr.c trunk/nodemgr.h trunk/sbp2.c Log: Go Ben, Go Ben! All of the old /proc/bus/ieee1394/devices information is now stuffed into sysfs attributes. I feel like I am programming hardware in a database environment. The sysfs stuff is really cool. Now on to the next major change of converting the drivers over to the driver-model for register/probe/bind. Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-07 22:27:28.000000000 -0500 @@ -17,7 +17,6 @@ #include <linux/kmod.h> #include <linux/completion.h> #include <linux/delay.h> -#include <linux/proc_fs.h> #include <linux/pci.h> #include <asm/atomic.h> #include <asm/byteorder.h> @@ -38,17 +37,22 @@ }; extern struct oui_list_struct oui_list[]; +#endif -static char *nodemgr_find_oui_name(int oui) { +/* Shitty part is, 0x0 can just mean it wasn't set, but that matches an + * OUI entry. We don't want that, so we take a chance and never match 0x0. + * Sorry XEROX. */ +static char *nodemgr_find_oui_name(int oui) +{ +#ifdef CONFIG_IEEE1394_OUI_DB int i; - for (i = 0; oui_list[i].name; i++) + for (i = 1; oui_list[i].name; i++) if (oui_list[i].oui == oui) return oui_list[i].name; - +#endif return NULL; } -#endif /* * Basically what we do here is start off retrieving the bus_info block. @@ -93,7 +97,7 @@ struct completion exited; struct semaphore reset_sem; int pid; - unsigned int id; + int id; char daemon_name[15]; }; @@ -103,128 +107,165 @@ .add = NULL, }; -#ifdef CONFIG_PROC_FS +#define fw_ne_attr(field, type, format_string) \ +static ssize_t fw_ne_show_##field (struct device *dev, char *buf)\ +{ \ + struct node_entry *ne; \ + ne = container_of(dev, struct node_entry, device); \ + return sprintf (buf, format_string, (type)ne->field); \ +} \ +static struct device_attribute dev_attr_ne_##field = { \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_ne_show_##field, \ +}; + +#define fw_ud_attr(field, type, format_string) \ +static ssize_t fw_ud_show_##field (struct device *dev, char *buf) \ +{ \ + struct unit_directory *ud; \ + ud = container_of(dev, struct unit_directory, device); \ + return sprintf (buf, format_string, (type)ud->field); \ +} \ +static struct device_attribute dev_attr_ud_##field = { \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_ud_show_##field, \ +}; + +#define fw_host_attr(field, type, format_string) \ +static ssize_t fw_host_show_##field (struct device *dev, char *buf) \ +{ \ + struct hpsb_host *host; \ + host = container_of(dev, struct hpsb_host, device); \ + return sprintf (buf, format_string, (type)host->field); \ +} \ +static struct device_attribute dev_attr_host_##field = { \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_host_show_##field, \ +}; + -#define PUTF(fmt, args...) out += sprintf(out, fmt, ## args) +fw_ne_attr(guid, unsigned long long, "0x%016Lx\n") +fw_ne_attr(capabilities, unsigned int, "0x%06x\n") +fw_ne_attr(vendor_id, unsigned int, "0x%06x\n") +fw_ne_attr(nodeid, unsigned int, "0x%04x\n") +fw_ne_attr(vendor_name, const char *, "%s\n") +fw_ne_attr(oui_name, const char *, "%s\n") -static int raw1394_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) + +fw_ud_attr(address, unsigned long long, "0x%016Lx\n") +fw_ud_attr(vendor_id, unsigned int, "0x%06x\n") +fw_ud_attr(model_id, unsigned int, "0x%06x\n") +fw_ud_attr(specifier_id, unsigned int, "0x%06x\n") +fw_ud_attr(version, unsigned int, "0x%06x\n") +fw_ud_attr(length, int, "%d\n") +fw_ud_attr(vendor_name, const char *, "%s\n") +fw_ud_attr(model_name, const char *, "%s\n") + + +fw_host_attr(node_count, int, "%d\n") +fw_host_attr(selfid_count, int, "%d\n") +fw_host_attr(nodes_active, int, "%d\n") +fw_host_attr(in_bus_reset, int, "%d\n") +fw_host_attr(is_root, int, "%d\n") +fw_host_attr(is_cycmst, int, "%d\n") +fw_host_attr(is_irm, int, "%d\n") +fw_host_attr(is_busmgr, int, "%d\n") + + +static ssize_t fw_ne_show_bus_options(struct device *dev, char *buf) { - struct list_head *lh; - struct node_entry *ne; - int len; - char *out = page; - unsigned long flags; + struct node_entry *ne = container_of(dev, struct node_entry, device); - if (down_interruptible(&nodemgr_serialize)) - return -EINTR; + return sprintf (buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) " + "LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n", ne->busopt.irmc, + ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, + ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, + ne->busopt.max_rec, ne->busopt.cyc_clk_acc); +} +static DEVICE_ATTR(bus_options,S_IRUGO,fw_ne_show_bus_options,NULL); - list_for_each(lh, &node_list) { - struct list_head *l; - int ud_count = 0; - ne = list_entry(lh, struct node_entry, list); - if (!ne) - continue; +static ssize_t fw_ne_show_tlabels_free(struct device *dev, char *buf) +{ + struct node_entry *ne = container_of(dev, struct node_entry, device); + return sprintf (buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1); +} +static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_ne_show_tlabels_free,NULL); - PUTF("Node[" NODE_BUS_FMT "] GUID[%016Lx]:\n", - NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid); - /* Generic Node information */ - PUTF(" Vendor ID : `%s' [0x%06x]\n", ne->oui_name, ne->vendor_id); - if (ne->vendor_name) - PUTF(" Vendor text : `%s'\n", ne->vendor_name); - PUTF(" Capabilities: 0x%06x\n", ne->capabilities); - PUTF(" Tlabel stats:\n"); - spin_lock_irqsave(&ne->tpool->lock, flags); - PUTF(" Free : %d\n", atomic_read(&ne->tpool->count.count) + 1); - PUTF(" Total : %u\n", ne->tpool->allocations); - PUTF(" Mask0 : %0lx\n", ne->tpool->pool[0]); +static ssize_t fw_ne_show_tlabels_allocations(struct device *dev, char *buf) +{ + struct node_entry *ne = container_of(dev, struct node_entry, device); + return sprintf (buf, "%u\n", ne->tpool->allocations); +} +static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_ne_show_tlabels_allocations,NULL); + + +static ssize_t fw_ne_show_tlabels_mask(struct device *dev, char *buf) +{ + struct node_entry *ne = container_of(dev, struct node_entry, device); #if (BITS_PER_LONG <= 32) - PUTF(" Mask1 : %0lx\n", ne->tpool->pool[1]); + return sprintf (buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); +#else + return sprintf (buf, "0x%016lx\n", ne->tpool->pool[0]); #endif - spin_unlock_irqrestore(&ne->tpool->lock, flags); - PUTF(" Bus Options :\n"); - PUTF(" IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d)\n" - " LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n", - ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, - ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, - ne->busopt.max_rec, ne->busopt.cyc_clk_acc); - - /* If this is the host entry, output some info about it aswell */ - if (ne->host != NULL && ne->host->node_id == ne->nodeid) { - PUTF(" Host Node Status:\n"); - PUTF(" Host Driver : %s\n", ne->host->driver->name); - PUTF(" Nodes connected : %d\n", ne->host->node_count); - PUTF(" Nodes active : %d\n", ne->host->nodes_active); - PUTF(" SelfIDs received: %d\n", ne->host->selfid_count); - PUTF(" Irm ID : [" NODE_BUS_FMT "]\n", - NODE_BUS_ARGS(ne->host->irm_id)); - PUTF(" BusMgr ID : [" NODE_BUS_FMT "]\n", - NODE_BUS_ARGS(ne->host->busmgr_id)); - PUTF(" In Bus Reset : %s\n", ne->host->in_bus_reset ? "yes" : "no"); - PUTF(" Root : %s\n", ne->host->is_root ? "yes" : "no"); - PUTF(" Cycle Master : %s\n", ne->host->is_cycmst ? "yes" : "no"); - PUTF(" IRM : %s\n", ne->host->is_irm ? "yes" : "no"); - PUTF(" Bus Manager : %s\n", ne->host->is_busmgr ? "yes" : "no"); - } +} +static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_ne_show_tlabels_mask,NULL); - /* Now the unit directories */ - list_for_each (l, &ne->unit_directories) { - struct unit_directory *ud = list_entry (l, struct unit_directory, node_list); - int printed = 0; // small hack - - PUTF(" Unit Directory %d:\n", ud_count++); - - if (ud->flags & UNIT_DIRECTORY_VENDOR_ID || - ud->flags & UNIT_DIRECTORY_MODEL_ID) { - PUTF(" Vendor/Model ID : "); - } - if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { - PUTF("%s [%06x]", ud->vendor_name ?: "Unknown", - ud->vendor_id); - printed = 1; - } - if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { - if (!printed) { - PUTF("%s [%06x]", ne->vendor_name ?: "Unknown", - ne->vendor_id); - } - PUTF(" / %s [%06x]", ud->model_name ?: "Unknown", ud->model_id); - printed = 1; - } - if (printed) - PUTF("\n"); - if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) - PUTF(" Software Spec ID : %06x\n", ud->specifier_id); - if (ud->flags & UNIT_DIRECTORY_VERSION) - PUTF(" Software Version : %06x\n", ud->version); - if (ud->driver) - PUTF(" Driver : %s\n", ud->driver->name); - PUTF(" Length (in quads): %d\n", ud->count); - } +static void nodemgr_create_ne_dev_files(struct node_entry *ne) +{ + struct device *dev = &ne->device; - } + device_create_file(dev, &dev_attr_ne_guid); + device_create_file(dev, &dev_attr_ne_capabilities); + device_create_file(dev, &dev_attr_ne_vendor_id); + device_create_file(dev, &dev_attr_ne_nodeid); + device_create_file(dev, &dev_attr_bus_options); + device_create_file(dev, &dev_attr_tlabels_free); + device_create_file(dev, &dev_attr_tlabels_allocations); + device_create_file(dev, &dev_attr_tlabels_mask); +} - up(&nodemgr_serialize); +static void nodemgr_create_host_dev_files(struct hpsb_host *host) +{ + struct device *dev = &host->device; - len = out - page; - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) - return 0; - } else - len = count; + device_create_file(dev, &dev_attr_host_node_count); + device_create_file(dev, &dev_attr_host_selfid_count); + device_create_file(dev, &dev_attr_host_nodes_active); + device_create_file(dev, &dev_attr_host_in_bus_reset); + device_create_file(dev, &dev_attr_host_is_root); + device_create_file(dev, &dev_attr_host_is_cycmst); + device_create_file(dev, &dev_attr_host_is_irm); + device_create_file(dev, &dev_attr_host_is_busmgr); +} - *start = page + off; +static void nodemgr_create_ud_dev_files(struct unit_directory *ud) +{ + struct device *dev = &ud->device; - return len; -} + device_create_file(dev, &dev_attr_ud_address); + device_create_file(dev, &dev_attr_ud_length); + + if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) + device_create_file(dev, &dev_attr_ud_specifier_id); -#undef PUTF -#endif /* CONFIG_PROC_FS */ + if (ud->flags & UNIT_DIRECTORY_VERSION) + device_create_file(dev, &dev_attr_ud_version); + + if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { + device_create_file(dev, &dev_attr_ud_vendor_id); + if (ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) + device_create_file(dev, &dev_attr_ud_vendor_name); + } + + if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { + device_create_file(dev, &dev_attr_ud_model_id); + if (ud->flags & UNIT_DIRECTORY_MODEL_TEXT) + device_create_file(dev, &dev_attr_ud_model_name); + } +} static void nodemgr_process_config_rom(struct node_entry *ne, quadlet_t busoptions); @@ -396,11 +437,12 @@ list_add_tail(&ne->list, &node_list); ne->device.parent = &host->device; - sprintf(ne->device.bus_id, "%u-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(nodeid)); + sprintf(ne->device.bus_id, "%d-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(nodeid)); sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); ne->device.bus = &ieee1394_bus_type; device_register(&ne->device); + nodemgr_create_ne_dev_files(ne); nodemgr_process_config_rom (ne, busoptions); @@ -527,12 +569,9 @@ if (ud != NULL) { memset (ud, 0, total_size); ud->flags = flags; - ud->count = count; + ud->length = count; ud->vendor_name_size = vendor_name_size; ud->model_name_size = model_name_size; - /* If there is no vendor name in the unit directory, - use the one in the root directory. */ - ud->vendor_name = ne->vendor_name; } return ud; @@ -583,11 +622,9 @@ if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) { length--; address += 4; - quadp = &(ud->quadlets[ud->count]); - if (nodemgr_read_text_leaf(ne, address, - quadp) == 0 - && quadp[0] == 0 - && quadp[1] == 0) { + quadp = &(ud->quadlets[ud->length]); + if (nodemgr_read_text_leaf(ne, address, quadp) == 0 + && quadp[0] == 0 && quadp[1] == 0) { /* We only support minimal ASCII and English. */ quadp[ud->vendor_name_size] = 0; @@ -603,11 +640,9 @@ if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) { length--; address += 4; - quadp = &(ud->quadlets[ud->count + ud->vendor_name_size + 1]); - if (nodemgr_read_text_leaf(ne, address, - quadp) == 0 - && quadp[0] == 0 - && quadp[1] == 0) { + quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]); + if (nodemgr_read_text_leaf(ne, address, quadp) == 0 + && quadp[0] == 0 && quadp[1] == 0) { /* We only support minimal ASCII and English. */ quadp[ud->model_name_size] = 0; @@ -652,6 +687,7 @@ ud->device.bus = &ieee1394_bus_type; device_register(&ud->device); + nodemgr_create_ud_dev_files(ud); return; @@ -720,24 +756,24 @@ switch (code) { case CONFIG_ROM_VENDOR_ID: ne->vendor_id = value; -#ifdef CONFIG_IEEE1394_OUI_DB + ne->oui_name = nodemgr_find_oui_name(value); -#else - ne->oui_name = "Unknown"; -#endif + if (ne->oui_name) + device_create_file(&ne->device, &dev_attr_ne_oui_name); + /* Now check if there is a vendor name text string. */ if (ne->vendor_name != NULL) { length--; address += 4; - if (nodemgr_read_text_leaf(ne, address, - ne->quadlets) - != 0 - || ne->quadlets [0] != 0 - || ne->quadlets [1] != 0) + if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0 + || ne->quadlets[0] != 0 || ne->quadlets[1] != 0) /* We only support minimal ASCII and English. */ ne->vendor_name = NULL; + else + device_create_file(&ne->device, + &dev_attr_ne_vendor_name); } break; @@ -838,6 +874,39 @@ #endif /* CONFIG_HOTPLUG */ + +static struct host_info *nodemgr_find_host_by_num(int hostnum) +{ + unsigned long flags; + struct list_head *lh; + struct host_info *hi = NULL; + + spin_lock_irqsave (&host_info_lock, flags); + list_for_each(lh, &host_info_list) { + struct host_info *myhi = list_entry(lh, struct host_info, list); + if (hi->id == hostnum) { + hi = myhi; + break; + } + } + spin_unlock_irqrestore (&host_info_lock, flags); + + return hi; +} + + +static int nodemgr_alloc_host_num(void) +{ + int hostnum = 0; + + while (1) { + if (!nodemgr_find_host_by_num(hostnum)) + return hostnum; + + hostnum++; + } +} + static void nodemgr_claim_unit_directory(struct unit_directory *ud, struct hpsb_protocol_driver *driver) { @@ -848,7 +917,6 @@ static void nodemgr_release_unit_directory(struct unit_directory *ud) { - device_unregister(&ud->device); ud->driver = NULL; list_del(&ud->driver_list); list_add_tail(&ud->driver_list, &unit_directory_list); @@ -875,6 +943,7 @@ nodemgr_release_unit_directory(ud); nodemgr_call_policy("remove", ud); list_del(&ud->driver_list); + device_unregister(&ud->device); kfree(ud); } } @@ -1414,7 +1483,6 @@ { struct host_info *hi; unsigned long flags; - static unsigned int host_id = 0; hi = kmalloc(sizeof (struct host_info), in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); @@ -1431,16 +1499,17 @@ init_completion(&hi->exited); sema_init(&hi->reset_sem, 0); - hi->id = host_id++; + hi->id = nodemgr_alloc_host_num(); host->device.parent = &host->pdev->dev; - sprintf(host->device.bus_id, "fw-host%u", hi->id); - sprintf(host->device.name, "IEEE-1394 Host %s-%u", host->driver->name, hi->id); + sprintf(host->device.bus_id, "fw-host%d", hi->id); + sprintf(host->device.name, "IEEE-1394 Host %s-%d", host->driver->name, hi->id); host->device.bus = &ieee1394_bus_type; - sprintf(hi->daemon_name, "knodemgrd/%u", hi->id); + sprintf(hi->daemon_name, "knodemgrd/%d", hi->id); device_register(&host->device); + nodemgr_create_host_dev_files(host); hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); @@ -1543,20 +1612,12 @@ static struct hpsb_highlevel *hl; -#define PROC_ENTRY "devices" - void init_ieee1394_nodemgr(int disable_hotplug) { nodemgr_disable_hotplug = disable_hotplug; bus_register(&ieee1394_bus_type); -#ifdef CONFIG_PROC_FS - if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, - raw1394_read_proc, NULL)) - HPSB_ERR("Can't create devices procfs entry"); -#endif - hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); if (!hl) { HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); @@ -1566,9 +1627,6 @@ void cleanup_ieee1394_nodemgr(void) { hpsb_unregister_highlevel(hl); -#ifdef CONFIG_PROC_FS - remove_proc_entry(PROC_ENTRY, ieee1394_procfs_entry); -#endif bus_unregister(&ieee1394_bus_type); } Modified: trunk/nodemgr.h ============================================================================== --- trunk/nodemgr.h (original) +++ trunk/nodemgr.h 2003-03-07 22:27:28.000000000 -0500 @@ -119,7 +119,7 @@ unsigned int id; - int count; /* Number of quadlets */ + int length; /* Number of quadlets */ struct device device; Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c 2003-03-07 22:27:28.000000000 -0500 @@ -926,11 +926,10 @@ list_add_tail(&hi->list, &sbp2_host_info_list); spin_unlock_irqrestore(&sbp2_host_info_lock, flags); - /* - * XXX(hch): Hopefully the ieee1394 code will be converted - * to the driver model at some point. Until that happens - * we'll have to pass in NULL here. - */ + /* XXX We need a device to pass here as the scsi-host class. Can't + * use the PCI device, since it is already bound to the ieee1394 + * host. Can't use the fw-host device since it is multi-class + * enabled (scsi-host uses classdata member of the device). */ if (scsi_add_host(hi->scsi_host, NULL)) { SBP2_ERR("failed to add scsi host"); @@ -1603,7 +1602,7 @@ ud = scsi_id->ud; /* Handle different fields in the unit directory, based on keys */ - for (i = 0; i < ud->count; i++) { + for (i = 0; i < ud->length; i++) { switch (CONFIG_ROM_KEY(ud->quadlets[i])) { case SBP2_CSR_OFFSET_KEY: /* Save off the management agent address */ |
From: SVN U. <ben...@li...> - 2003-03-07 22:45:40
|
Author: bencollins Date: 2003-03-07 17:44:46 -0500 (Fri, 07 Mar 2003) New Revision: 824 Modified: branches/linux-2.4/ohci1394.c Log: Remove extraneous selfid_complete call. Noticed by Jim Radford. Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-03-07 17:44:47.000000000 -0500 @@ -348,8 +348,6 @@ DBGMSG(ohci->id, "SelfID complete"); - hpsb_selfid_complete(host, phyid, isroot); - return; } |
From: SVN U. <ben...@li...> - 2003-03-07 19:12:37
|
Author: bencollins Date: 2003-03-07 14:11:50 -0500 (Fri, 07 Mar 2003) New Revision: 823 Modified: trunk/nodemgr.c trunk/nodemgr.h Log: Add devices for unit directories aswell. Next step will be to move all the info we normally export in /proc/bus/ieee1394/devices into attributes of the ne and ud devices. Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-07 14:11:51.000000000 -0500 @@ -395,8 +395,6 @@ list_add_tail(&ne->list, &node_list); - nodemgr_process_config_rom (ne, busoptions); - ne->device.parent = &host->device; sprintf(ne->device.bus_id, "%u-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(nodeid)); sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); @@ -404,6 +402,8 @@ device_register(&ne->device); + nodemgr_process_config_rom (ne, busoptions); + HPSB_DEBUG("%s added: ID:BUS[%s] GUID[%016Lx] [%s] (%s)", (host->node_id == nodeid) ? "Host" : "Node", ne->device.bus_id, (unsigned long long)guid, @@ -520,10 +520,12 @@ return NULL; } } + total_size += count * sizeof (quadlet_t); ud = kmalloc (total_size, GFP_KERNEL); + if (ud != NULL) { - memset (ud, 0, sizeof *ud); + memset (ud, 0, total_size); ud->flags = flags; ud->count = count; ud->vendor_name_size = vendor_name_size; @@ -532,6 +534,7 @@ use the one in the root directory. */ ud->vendor_name = ne->vendor_name; } + return ud; } @@ -541,7 +544,7 @@ */ static void nodemgr_process_unit_directory(struct node_entry *ne, - octlet_t address) + octlet_t address, unsigned int id) { struct unit_directory *ud; quadlet_t quad; @@ -553,6 +556,7 @@ ud->ne = ne; ud->address = address; + ud->id = id; if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)) @@ -642,6 +646,13 @@ list_add_tail(&ud->node_list, &ne->unit_directories); list_add_tail(&ud->driver_list, &unit_directory_list); + ud->device.parent = &ne->device; + sprintf(ud->device.bus_id, "%s-%u", ne->device.bus_id, ud->id); + sprintf(ud->device.name, "IEEE-1394 unit directory %s", ud->device.bus_id); + ud->device.bus = &ieee1394_bus_type; + + device_register(&ud->device); + return; unit_directory_error: @@ -682,6 +693,7 @@ octlet_t address; quadlet_t quad; int length; + unsigned int ud_id = 0; address = CSR_REGISTER_BASE + CSR_CONFIG_ROM; @@ -734,7 +746,7 @@ break; case CONFIG_ROM_UNIT_DIRECTORY: - nodemgr_process_unit_directory(ne, address + value * 4); + nodemgr_process_unit_directory(ne, address + value * 4, ud_id++); break; case CONFIG_ROM_DESCRIPTOR_LEAF: @@ -836,6 +848,7 @@ static void nodemgr_release_unit_directory(struct unit_directory *ud) { + device_unregister(&ud->device); ud->driver = NULL; list_del(&ud->driver_list); list_add_tail(&ud->driver_list, &unit_directory_list); Modified: trunk/nodemgr.h ============================================================================== --- trunk/nodemgr.h (original) +++ trunk/nodemgr.h 2003-03-07 14:11:51.000000000 -0500 @@ -117,6 +117,8 @@ /* For linking directories belonging to a node */ struct list_head node_list; + unsigned int id; + int count; /* Number of quadlets */ struct device device; |
From: SVN U. <ben...@li...> - 2003-03-07 18:25:51
|
Author: bencollins Date: 2003-03-07 13:25:09 -0500 (Fri, 07 Mar 2003) New Revision: 822 Modified: trunk/hosts.h trunk/ieee1394_core.h trunk/nodemgr.c trunk/nodemgr.h Log: First crack at sysfs support. This makes the hosts register as fw-hostX where X is an ID. This ID is used for knodemgrd/X, /sys/bus/ieee1394/fw-hostX, and a few other places to keep things inline. Each node also creates a device. I will add device creation on a per unit-directory aswell. Then I'll make nodemgr start using driver core callbacks for probe/matching. Modified: trunk/ieee1394_core.h ============================================================================== --- trunk/ieee1394_core.h (original) +++ trunk/ieee1394_core.h 2003-03-07 13:25:10.000000000 -0500 @@ -231,4 +231,7 @@ /* the proc_fs entry for /proc/ieee1394 */ extern struct proc_dir_entry *ieee1394_procfs_entry; +/* Our sysfs bus entry */ +extern struct bus_type ieee1394_bus_type; + #endif /* _IEEE1394_CORE_H */ Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-07 13:25:10.000000000 -0500 @@ -17,9 +17,8 @@ #include <linux/kmod.h> #include <linux/completion.h> #include <linux/delay.h> -#ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> -#endif +#include <linux/pci.h> #include <asm/atomic.h> #include <asm/byteorder.h> @@ -60,20 +59,21 @@ * complete directory entry (be it a leaf or a directory). We then process * it and add the info to our structure for that particular node. * - * We verify CRC's along the way for each directory/block/leaf. The - * entire node structure is generic, and simply stores the information in - * a way that's easy to parse by the protocol interface. + * We verify CRC's along the way for each directory/block/leaf. The entire + * node structure is generic, and simply stores the information in a way + * that's easy to parse by the protocol interface. */ -/* 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. +/* + * 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); @@ -93,6 +93,14 @@ struct completion exited; struct semaphore reset_sem; int pid; + unsigned int id; + char daemon_name[15]; +}; + +struct bus_type ieee1394_bus_type = { + .name = "ieee1394", + .hotplug = NULL, + .add = NULL, }; #ifdef CONFIG_PROC_FS @@ -352,6 +360,8 @@ if (!ne) return NULL; + memset(ne, 0, total_size); + if (size != 0) { ne->vendor_name = (const char *) &(ne->quadlets[2]); @@ -364,9 +374,10 @@ } static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions, - struct hpsb_host *host, + struct host_info *hi, nodeid_t nodeid, unsigned int generation) { + struct hpsb_host *host = hi->host; struct node_entry *ne; ne = nodemgr_scan_root_directory (host, nodeid, generation); @@ -386,11 +397,17 @@ nodemgr_process_config_rom (ne, busoptions); - HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx] [%s] (%s)", + ne->device.parent = &host->device; + sprintf(ne->device.bus_id, "%u-" NODE_BUS_FMT, hi->id, NODE_BUS_ARGS(nodeid)); + sprintf(ne->device.name, "IEEE-1394 device %s", ne->device.bus_id); + ne->device.bus = &ieee1394_bus_type; + + device_register(&ne->device); + + HPSB_DEBUG("%s added: ID:BUS[%s] GUID[%016Lx] [%s] (%s)", (host->node_id == nodeid) ? "Host" : "Node", - NODE_BUS_ARGS(nodeid), (unsigned long long)guid, - ne->oui_name, - ne->vendor_name ?: "Unknown"); + ne->device.bus_id, (unsigned long long)guid, + ne->oui_name, ne->vendor_name ?: "Unknown"); return ne; } @@ -1098,6 +1115,7 @@ nodemgr_free_unit_directories(ne); list_del(&ne->list); + device_unregister(&ne->device); kfree(ne); return; @@ -1105,9 +1123,10 @@ /* This is where we probe the nodes for their information and provided * features. */ -static void nodemgr_node_probe_one(struct hpsb_host *host, +static void nodemgr_node_probe_one(struct host_info *hi, nodeid_t nodeid, int generation) { + struct hpsb_host *host = hi->host; struct node_entry *ne; quadlet_t buffer[5]; octlet_t guid; @@ -1135,7 +1154,7 @@ ne = find_entry_by_guid(guid); if (!ne) - nodemgr_create_node(guid, buffer[2], host, nodeid, generation); + nodemgr_create_node(guid, buffer[2], hi, nodeid, generation); else nodemgr_update_node(ne, buffer[2], host, nodeid, generation); @@ -1167,9 +1186,10 @@ return; } -static void nodemgr_node_probe(struct hpsb_host *host) +static void nodemgr_node_probe(struct host_info *hi) { int count; + struct hpsb_host *host = hi->host; struct selfid *sid = (struct selfid *)host->topology_map; nodeid_t nodeid = LOCAL_BUS; unsigned int generation; @@ -1198,7 +1218,7 @@ continue; } - nodemgr_node_probe_one(host, nodeid++, generation); + nodemgr_node_probe_one(hi, nodeid++, generation); } /* If we had a bus reset while we were scanning the bus, it is @@ -1264,9 +1284,9 @@ struct host_info *hi = (struct host_info *)__hi; /* No userlevel access needed */ - daemonize("knodemgrd"); + daemonize(hi->daemon_name); allow_signal(SIGTERM); - + /* 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) && @@ -1278,7 +1298,7 @@ continue; } - nodemgr_node_probe(hi->host); + nodemgr_node_probe(hi); nodemgr_do_irm_duties(hi->host); up(&nodemgr_serialize); @@ -1381,6 +1401,7 @@ { struct host_info *hi; unsigned long flags; + static unsigned int host_id = 0; hi = kmalloc(sizeof (struct host_info), in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); @@ -1397,12 +1418,24 @@ init_completion(&hi->exited); sema_init(&hi->reset_sem, 0); + hi->id = host_id++; + + host->device.parent = &host->pdev->dev; + sprintf(host->device.bus_id, "fw-host%u", hi->id); + sprintf(host->device.name, "IEEE-1394 Host %s-%u", host->driver->name, hi->id); + host->device.bus = &ieee1394_bus_type; + + sprintf(hi->daemon_name, "knodemgrd/%u", hi->id); + + device_register(&host->device); + hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); if (hi->pid < 0) { - HPSB_ERR ("NodeMgr: failed to start NodeMgr thread for %s", - host->driver->name); + HPSB_ERR ("NodeMgr: failed to start %s thread for %s", + hi->daemon_name, host->driver->name); + device_unregister(&host->device); kfree(hi); return; } @@ -1482,6 +1515,8 @@ nodemgr_remove_node(ne); } + device_unregister(&host->device); + up(&nodemgr_serialize); return; @@ -1500,10 +1535,15 @@ void init_ieee1394_nodemgr(int disable_hotplug) { nodemgr_disable_hotplug = disable_hotplug; + + bus_register(&ieee1394_bus_type); + #ifdef CONFIG_PROC_FS - if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, raw1394_read_proc, NULL)) + if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, + raw1394_read_proc, NULL)) HPSB_ERR("Can't create devices procfs entry"); #endif + hl = hpsb_register_highlevel("Node manager", &nodemgr_ops); if (!hl) { HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization"); @@ -1516,4 +1556,6 @@ #ifdef CONFIG_PROC_FS remove_proc_entry(PROC_ENTRY, ieee1394_procfs_entry); #endif + + bus_unregister(&ieee1394_bus_type); } Modified: trunk/nodemgr.h ============================================================================== --- trunk/nodemgr.h (original) +++ trunk/nodemgr.h 2003-03-07 13:25:10.000000000 -0500 @@ -20,6 +20,8 @@ #ifndef _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H +#include <linux/device.h> + #define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24) #define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff) #define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff) @@ -116,6 +118,10 @@ struct list_head node_list; int count; /* Number of quadlets */ + + struct device device; + + /* XXX Must be last in the struct! */ quadlet_t quadlets[0]; }; @@ -137,6 +143,9 @@ const char *vendor_name; char *oui_name; + struct device device; + + /* XXX Must be last in the struct! */ quadlet_t quadlets[0]; }; Modified: trunk/hosts.h ============================================================================== --- trunk/hosts.h (original) +++ trunk/hosts.h 2003-03-07 13:25:10.000000000 -0500 @@ -1,6 +1,7 @@ #ifndef _IEEE1394_HOSTS_H #define _IEEE1394_HOSTS_H +#include <linux/device.h> #include <linux/wait.h> #include <linux/list.h> #include <asm/semaphore.h> @@ -64,6 +65,8 @@ struct hpsb_host_driver *driver; struct pci_dev *pdev; + + struct device device; }; |
From: SVN U. <ben...@li...> - 2003-03-07 18:22:50
|
Author: bencollins Date: 2003-03-07 13:22:10 -0500 (Fri, 07 Mar 2003) New Revision: 821 Modified: trunk/ieee1394.h Log: Add more speed defines. Modified: trunk/ieee1394.h ============================================================================== --- trunk/ieee1394.h (original) +++ trunk/ieee1394.h 2003-03-07 13:22:11.000000000 -0500 @@ -46,9 +46,13 @@ #define ACKX_TIMEOUT (-4) -#define SPEED_100 0x0 -#define SPEED_200 0x1 -#define SPEED_400 0x2 +#define SPEED_100 0x00 +#define SPEED_200 0x01 +#define SPEED_400 0x02 +#define SPEED_800 0x03 +#define SPEED_1600 0x04 +#define SPEED_3200 0x05 + /* Maps speed values above to a string representation */ extern const char *hpsb_speedto_str[]; |
From: SVN U. <ben...@li...> - 2003-03-07 18:21:27
|
Author: bencollins Date: 2003-03-07 13:20:46 -0500 (Fri, 07 Mar 2003) New Revision: 820 Modified: trunk/ohci1394.c Log: User PCI_ANY_ID for class mask Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-03-07 13:20:48.000000000 -0500 @@ -3489,7 +3489,7 @@ static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { { .class = PCI_CLASS_FIREWIRE_OHCI, - .class_mask = ~0, + .class_mask = PCI_ANY_ID, .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, |
From: SVN U. <ben...@li...> - 2003-03-07 18:21:08
|
Author: bencollins Date: 2003-03-07 13:20:25 -0500 (Fri, 07 Mar 2003) New Revision: 819 Modified: trunk/ieee1394_core.c Log: Add some higher speed str's. Couple style nitpicks. Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2003-03-07 13:20:26.000000000 -0500 @@ -62,7 +62,7 @@ static kmem_cache_t *hpsb_packet_cache; /* Some globals used */ -const char *hpsb_speedto_str[] = { "S100", "S200", "S400" }; +const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; static void dump_packet(const char *text, quadlet_t *data, int size) { @@ -1120,7 +1120,7 @@ /* follow through with the open() */ retval = file_ops->open(inode, file); - if(retval == 0) { + if (retval == 0) { /* If the open() succeeded, then ieee1394 will be left * with an extra module reference, so we discard it here. @@ -1166,7 +1166,7 @@ #ifdef CONFIG_PROC_FS /* Must be done before we start everything else, since the drivers * may use it. */ - ieee1394_procfs_entry = proc_mkdir( "ieee1394", proc_bus); + ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus); if (ieee1394_procfs_entry == NULL) { HPSB_ERR("unable to create /proc/bus/ieee1394\n"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); |
From: SVN U. <ben...@li...> - 2003-03-07 18:06:34
|
Author: bencollins Date: 2003-03-07 13:05:46 -0500 (Fri, 07 Mar 2003) New Revision: 818 Modified: branches/linux-2.4/nodemgr.c branches/linux-2.4/ohci1394.c Log: ne needs to be memset after kmalloc. Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-03-07 13:05:48.000000000 -0500 @@ -2253,22 +2253,28 @@ } if (event & OHCI1394_busReset) { + int loops = 0; + /* The busReset event bit can't be cleared during the * selfID phase, so we disable busReset interrupts, to * avoid burying the cpu in interrupt requests. */ spin_lock_irqsave(&ohci->event_lock, flags); reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); - 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); - } + udelay(10); + while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { + if (loops++ > 10000) { + hpsb_reset_bus(host, 1); + loops = 0; + DBGMSG(ohci->id, "Out of control loop, resetting"); + } + + 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", (attempt_root) ? " and attempting to become root" Modified: branches/linux-2.4/nodemgr.c ============================================================================== --- branches/linux-2.4/nodemgr.c (original) +++ branches/linux-2.4/nodemgr.c 2003-03-07 13:05:48.000000000 -0500 @@ -312,6 +312,7 @@ } ne = kmalloc(total_size, SLAB_ATOMIC); if (ne != NULL) { + memset(ne, 0, total_size); if (size != 0) { ne->vendor_name = (const char *) &(ne->quadlets[2]); |
From: SVN U. <ben...@li...> - 2003-03-07 03:22:11
|
Author: bencollins Date: 2003-03-06 22:21:27 -0500 (Thu, 06 Mar 2003) New Revision: 817 Modified: trunk/TODO Log: Updated Modified: trunk/TODO ============================================================================== --- trunk/TODO (original) +++ trunk/TODO 2003-03-06 22:21:28.000000000 -0500 @@ -12,6 +12,3 @@ - Implement per-node queueing options for SBP-2 (look at sym2 driver for example). - -- Fix Video1394 to use the PCI DMA routines, so it works with non-32bit - machines and > 1gig of ram (especially with highmem support). |
From: SVN U. <ben...@li...> - 2003-03-06 16:31:07
|
Author: bencollins Date: 2003-03-06 11:30:26 -0500 (Thu, 06 Mar 2003) New Revision: 816 Modified: branches/linux-2.4/ohci1394.c branches/linux-2.4/ohci1394.h Log: Fix logic for soft_reset. Noticed by Peter Yao. Also add some subdefs for HCControl reg. (backported from trunk) Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-03-06 11:30:27.000000000 -0500 @@ -356,10 +356,10 @@ static void ohci_soft_reset(struct ti_ohci *ohci) { int i; - reg_write(ohci, OHCI1394_HCControlSet, 0x00010000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (reg_read(ohci, OHCI1394_HCControlSet) & 0x00010000) + if (!reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset) break; mdelay(1); } @@ -516,7 +516,7 @@ reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); /* Enable posted writes */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00040000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); /* Clear link control register */ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); @@ -579,7 +579,7 @@ (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); /* We don't want hardware swapping */ - reg_write(ohci, OHCI1394_HCControlClear, 0x40000000); + reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); /* Enable interrupts */ reg_write(ohci, OHCI1394_IntMaskSet, @@ -596,7 +596,7 @@ OHCI1394_cycleInconsistent); /* Enable link */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " @@ -3330,7 +3330,7 @@ * accessing registers in the SClk domain without LPS enabled * will lock up the machine. Wait 50msec to make sure we have * full link enabled. */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00080000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); mdelay(50); /* Determine the number of available IR and IT contexts. */ Modified: branches/linux-2.4/ohci1394.h ============================================================================== --- branches/linux-2.4/ohci1394.h (original) +++ branches/linux-2.4/ohci1394.h 2003-03-06 11:30:28.000000000 -0500 @@ -288,6 +288,13 @@ #define OHCI1394_VendorID 0x040 #define OHCI1394_HCControlSet 0x050 #define OHCI1394_HCControlClear 0x054 +#define OHCI1394_HCControl_noByteSwap 0x40000000 +#define OHCI1394_HCControl_programPhyEnable 0x00800000 +#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 +#define OHCI1394_HCControl_LPS 0x00080000 +#define OHCI1394_HCControl_postedWriteEnable 0x00040000 +#define OHCI1394_HCControl_linkEnable 0x00020000 +#define OHCI1394_HCControl_softReset 0x00010000 #define OHCI1394_SelfIDBuffer 0x064 #define OHCI1394_SelfIDCount 0x068 #define OHCI1394_IRMultiChanMaskHiSet 0x070 |
From: SVN U. <ben...@li...> - 2003-03-06 16:30:07
|
Author: bencollins Date: 2003-03-06 11:29:18 -0500 (Thu, 06 Mar 2003) New Revision: 815 Modified: trunk/ohci1394.c trunk/ohci1394.h Log: Fix logic for soft_reset. Noticed by Peter Yao. Also add some subdefs for HCControl reg. Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-03-06 11:29:19.000000000 -0500 @@ -354,10 +354,10 @@ static void ohci_soft_reset(struct ti_ohci *ohci) { int i; - reg_write(ohci, OHCI1394_HCControlSet, 0x00010000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (reg_read(ohci, OHCI1394_HCControlSet) & 0x00010000) + if (!reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset) break; mdelay(1); } @@ -514,7 +514,7 @@ reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); /* Enable posted writes */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00040000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); /* Clear link control register */ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); @@ -577,7 +577,7 @@ (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); /* We don't want hardware swapping */ - reg_write(ohci, OHCI1394_HCControlClear, 0x40000000); + reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); /* Enable interrupts */ reg_write(ohci, OHCI1394_IntMaskSet, @@ -594,7 +594,7 @@ OHCI1394_cycleInconsistent); /* Enable link */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " @@ -3363,7 +3363,7 @@ * accessing registers in the SClk domain without LPS enabled * will lock up the machine. Wait 50msec to make sure we have * full link enabled. */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00080000); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); mdelay(50); /* Determine the number of available IR and IT contexts. */ Modified: trunk/ohci1394.h ============================================================================== --- trunk/ohci1394.h (original) +++ trunk/ohci1394.h 2003-03-06 11:29:19.000000000 -0500 @@ -288,6 +288,13 @@ #define OHCI1394_VendorID 0x040 #define OHCI1394_HCControlSet 0x050 #define OHCI1394_HCControlClear 0x054 +#define OHCI1394_HCControl_noByteSwap 0x40000000 +#define OHCI1394_HCControl_programPhyEnable 0x00800000 +#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 +#define OHCI1394_HCControl_LPS 0x00080000 +#define OHCI1394_HCControl_postedWriteEnable 0x00040000 +#define OHCI1394_HCControl_linkEnable 0x00020000 +#define OHCI1394_HCControl_softReset 0x00010000 #define OHCI1394_SelfIDBuffer 0x064 #define OHCI1394_SelfIDCount 0x068 #define OHCI1394_IRMultiChanMaskHiSet 0x070 |
From: SVN U. <dde...@li...> - 2003-03-06 01:20:49
|
Author: ddennedy Date: 2003-03-05 20:19:53 -0500 (Wed, 05 Mar 2003) New Revision: 814 Modified: branches/linux-2.4/dv1394.c branches/linux-2.4/ieee1394_hotplug.h branches/linux-2.4/nodemgr.c branches/linux-2.4/raw1394.c branches/linux-2.4/video1394.c branches/linux-2.4/video1394.h Log: hotplugging for AV/C and Digital Camera Modified: branches/linux-2.4/ieee1394_hotplug.h ============================================================================== --- branches/linux-2.4/ieee1394_hotplug.h (original) +++ branches/linux-2.4/ieee1394_hotplug.h 2003-03-05 20:19:54.000000000 -0500 @@ -9,6 +9,14 @@ #define IEEE1394_MATCH_SPECIFIER_ID 0x0004 #define IEEE1394_MATCH_VERSION 0x0008 +/* + * Unit spec id and sw version entry for some protocols + */ +#define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D +#define AVC_SW_VERSION_ENTRY 0x00010001 +#define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D +#define CAMERA_SW_VERSION_ENTRY 0x00000100 + struct ieee1394_device_id { u32 match_flags; u32 vendor_id; Modified: branches/linux-2.4/raw1394.c ============================================================================== --- branches/linux-2.4/raw1394.c (original) +++ branches/linux-2.4/raw1394.c 2003-03-05 20:19:54.000000000 -0500 @@ -48,6 +48,7 @@ #include "highlevel.h" #include "iso.h" #include "ieee1394_transactions.h" +#include "ieee1394_hotplug.h" #include "raw1394.h" #include "raw1394-private.h" @@ -2484,6 +2485,66 @@ return 0; } +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id raw1394_id_table[] = { + { + .match_flags =IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = AVC_SW_VERSION_ENTRY & 0xffffff + }, + { + .match_flags =IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = CAMERA_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +static int raw1394_probe(struct unit_directory *ud); +static void raw1394_disconnect(struct unit_directory *ud); +static void raw1394_update(struct unit_directory *ud); + +static struct hpsb_protocol_driver raw1394_AVC_driver = { + .name = "raw1394 AV/C Driver", + .id_table = raw1394_id_table, + .probe = raw1394_probe, + .disconnect = raw1394_disconnect, + .update = raw1394_update +}; + +static struct hpsb_protocol_driver raw1394_CAMERA_driver = { + .name = "raw1394 Digital Camera Driver", + .id_table = raw1394_id_table, + .probe = raw1394_probe, + .disconnect = raw1394_disconnect, + .update = raw1394_update +}; + +MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); + +static int raw1394_probe(struct unit_directory *ud) +{ + /* we should do an AV/C transaction to get a valid subunit, but since + Tape Recorder Player subunit is nearly the only thing on the market.... + */ + return 0; +} + +static void raw1394_disconnect(struct unit_directory *ud) +{ +} + +static void raw1394_update(struct unit_directory *ud) +{ +} + +/******************************************************************************/ + static struct hpsb_highlevel_ops hl_ops = { .add_host = add_host, .remove_host = remove_host, @@ -2526,6 +2587,8 @@ return -EBUSY; } printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); + hpsb_register_protocol(&raw1394_AVC_driver); + hpsb_register_protocol(&raw1394_CAMERA_driver); return 0; } Modified: branches/linux-2.4/nodemgr.c ============================================================================== --- branches/linux-2.4/nodemgr.c (original) +++ branches/linux-2.4/nodemgr.c 2003-03-05 20:19:54.000000000 -0500 @@ -890,6 +890,9 @@ /* * Right now registration always succeeds, but maybe we should * 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. */ return 0; Modified: branches/linux-2.4/video1394.c ============================================================================== --- branches/linux-2.4/video1394.c (original) +++ branches/linux-2.4/video1394.c 2003-03-05 20:19:55.000000000 -0500 @@ -52,6 +52,7 @@ #include "highlevel.h" #include "video1394.h" #include "dma.h" +#include "ieee1394_hotplug.h" #include "ohci1394.h" @@ -1241,6 +1242,50 @@ return 0; } +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id video1394_id_table[] = { + { + .match_flags =IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = CAMERA_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +static int video1394_probe(struct unit_directory *ud); +static void video1394_disconnect(struct unit_directory *ud); +static void video1394_update(struct unit_directory *ud); + +static struct hpsb_protocol_driver video1394_driver = { + .name = "1394 Digital Camera Driver", + .id_table = video1394_id_table, + .probe = video1394_probe, + .disconnect = video1394_disconnect, + .update = video1394_update +}; + +MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); + +static int video1394_probe(struct unit_directory *ud) +{ + return 0; +} + +static void video1394_disconnect(struct unit_directory *ud) +{ + /* hmmm... unlisten? */ +} + +static void video1394_update(struct unit_directory *ud) +{ +} + +/******************************************************************************/ + static struct file_operations video1394_fops= { .owner = THIS_MODULE, @@ -1281,6 +1326,7 @@ S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL); + hpsb_register_protocol(&video1394_driver); return 0; } Modified: branches/linux-2.4/dv1394.c ============================================================================== --- branches/linux-2.4/dv1394.c (original) +++ branches/linux-2.4/dv1394.c 2003-03-05 20:19:55.000000000 -0500 @@ -117,6 +117,7 @@ #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" +#include "ieee1394_hotplug.h" #include "dv1394.h" #include "dv1394-private.h" @@ -2564,6 +2565,53 @@ } #endif /* CONFIG_DEVFS_FS */ + +/*** HOTPLUG STUFF **********************************************************/ +/* + * Export information about protocols/devices supported by this driver. + */ +static struct ieee1394_device_id dv1394_id_table[] = { + { + .match_flags =IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = AVC_SW_VERSION_ENTRY & 0xffffff + }, + { } +}; + +static int dv1394_probe(struct unit_directory *ud); +static void dv1394_disconnect(struct unit_directory *ud); +static void dv1394_update(struct unit_directory *ud); + +static struct hpsb_protocol_driver dv1394_driver = { + .name = "DV/1394 Driver", + .id_table = dv1394_id_table, + .probe = dv1394_probe, + .disconnect = dv1394_disconnect, + .update = dv1394_update +}; + +MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); + +static int dv1394_probe(struct unit_directory *ud) +{ + /* we should do an AV/C transaction to get a valid subunit, but since + Tape Recorder Player subunit is nearly the only thing on the market.... + */ + return 0; +} + +static void dv1394_disconnect(struct unit_directory *ud) +{ + /* hmmm... shutdown? */ +} + +static void dv1394_update(struct unit_directory *ud) +{ + /* research integration with dv1394_host_reset */ +} + /*** IEEE1394 HPSB CALLBACKS ***********************************************/ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode) @@ -2642,6 +2690,8 @@ goto err_free; #endif + hpsb_register_protocol(&dv1394_driver); + debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); return 0; Modified: branches/linux-2.4/video1394.h ============================================================================== --- branches/linux-2.4/video1394.h (original) +++ branches/linux-2.4/video1394.h 2003-03-05 20:19:55.000000000 -0500 @@ -75,5 +75,4 @@ struct timeval filltime; /* time of buffer full */ }; - #endif |
From: SVN U. <ben...@li...> - 2003-03-05 16:04:44
|
Author: bencollins Date: 2003-03-05 11:04:02 -0500 (Wed, 05 Mar 2003) New Revision: 813 Modified: trunk/ieee1394_transactions.c trunk/ieee1394_types.h trunk/nodemgr.c Log: The bitops always operate on unsigned long, and not on u64 as used by the ieee1394 code. Use the *_BITMAP to always get a 64bit array of ulongs. -- Christoph Hellwig Modified: trunk/ieee1394_transactions.c ============================================================================== --- trunk/ieee1394_transactions.c (original) +++ trunk/ieee1394_transactions.c 2003-03-05 11:04:04.000000000 -0500 @@ -146,10 +146,10 @@ spin_lock_irqsave(&tp->lock, flags); - packet->tlabel = find_next_zero_bit(&tp->pool, 64, tp->next); + packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); tp->next = (packet->tlabel + 1) % 64; /* Should _never_ happen */ - BUG_ON(test_and_set_bit(packet->tlabel, &tp->pool)); + BUG_ON(test_and_set_bit(packet->tlabel, tp->pool)); tp->allocations++; spin_unlock_irqrestore(&tp->lock, flags); @@ -177,7 +177,7 @@ BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); spin_lock_irqsave(&tp->lock, flags); - BUG_ON(!test_and_clear_bit(packet->tlabel, &tp->pool)); + BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool)); spin_unlock_irqrestore(&tp->lock, flags); up(&tp->count); Modified: trunk/nodemgr.c ============================================================================== --- trunk/nodemgr.c (original) +++ trunk/nodemgr.c 2003-03-05 11:04:04.000000000 -0500 @@ -131,7 +131,10 @@ spin_lock_irqsave(&ne->tpool->lock, flags); PUTF(" Free : %d\n", atomic_read(&ne->tpool->count.count) + 1); PUTF(" Total : %u\n", ne->tpool->allocations); - PUTF(" Mask : %016Lx\n", (unsigned long long)ne->tpool->pool); + PUTF(" Mask0 : %0lx\n", ne->tpool->pool[0]); +#if (BITS_PER_LONG <= 32) + PUTF(" Mask1 : %0lx\n", ne->tpool->pool[1]); +#endif spin_unlock_irqrestore(&ne->tpool->lock, flags); PUTF(" Bus Options :\n"); PUTF(" IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d)\n" Modified: trunk/ieee1394_types.h ============================================================================== --- trunk/ieee1394_types.h (original) +++ trunk/ieee1394_types.h 2003-03-05 11:04:04.000000000 -0500 @@ -72,19 +72,20 @@ /* Transaction Label handling */ struct hpsb_tlabel_pool { - u64 pool; + DECLARE_BITMAP(pool, 64); spinlock_t lock; u8 next; u32 allocations; struct semaphore count; }; -#define HPSB_TPOOL_INIT(_tp) \ -do { \ - sema_init(&(_tp)->count, 63); \ - spin_lock_init(&(_tp)->lock); \ - (_tp)->next = 0; \ - (_tp)->pool = 0; \ +#define HPSB_TPOOL_INIT(_tp) \ +do { \ + CLEAR_BITMAP((_tp)->pool, 64); \ + spin_lock_init(&(_tp)->lock); \ + (_tp)->next = 0; \ + (_tp)->allocations = 0; \ + sema_init(&(_tp)->count, 63); \ } while(0) |
From: SVN U. <ben...@li...> - 2003-03-05 16:02:07
|
Author: bencollins Date: 2003-03-05 11:01:19 -0500 (Wed, 05 Mar 2003) New Revision: 812 Modified: trunk/sbp2.c Log: Fix SBP-2 comments concerning hotplug of SCSI devices. Patch from Christoph Hellwig. Modified: trunk/sbp2.c ============================================================================== --- trunk/sbp2.c (original) +++ trunk/sbp2.c 2003-03-05 11:01:20.000000000 -0500 @@ -27,30 +27,8 @@ * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * - * The easiest way to add/detect new SBP-2 devices is to run the shell script - * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be - * found at: - * http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh - * - * As an alternative, you may manually add/remove SBP-2 devices via the procfs with - * add-single-device <h> <b> <t> <l> or remove-single-device <h> <b> <t> <l>, where: - * <h> = host (starting at zero for first SCSI adapter) - * <b> = bus (normally zero) - * <t> = target (starting at zero for first SBP-2 device) - * <l> = lun (normally zero) - * - * e.g. To manually add/detect a new SBP-2 device - * echo "scsi add-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To manually remove a SBP-2 device after it's been unplugged - * echo "scsi remove-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To check to see which SBP-2/SCSI devices are currently registered - * cat /proc/scsi/scsi - * - * After scanning for new SCSI devices (above), you may access any attached - * SBP-2 storage devices as if they were SCSI devices (e.g. mount /dev/sda1, - * fdisk, mkfs, etc.). + * You may access any attached SBP-2 storage devices as if they were SCSI + * devices (e.g. mount /dev/sda1, fdisk, mkfs, etc.). * * * Module Load Options: |