* directory of the kernel sources for details.
*/
-#include <linux/bitmap.h>
#include <linux/kernel.h>
+#include <linux/config.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
struct hpsb_host *host;
nodeid_t nodeid;
unsigned int generation;
- unsigned int speed_unverified:1;
};
return NULL;
}
-/*
- * Correct the speed map entry. This is necessary
- * - for nodes with link speed < phy speed,
- * - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX.
- * A possible speed is determined by trial and error, using quadlet reads.
- */
-static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
- quadlet_t *buffer)
-{
- quadlet_t q;
- u8 i, *speed, old_speed, good_speed;
- int ret;
-
- speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid);
- old_speed = *speed;
- good_speed = IEEE1394_SPEED_MAX + 1;
-
- /* Try every speed from S100 to old_speed.
- * If we did it the other way around, a too low speed could be caught
- * if the retry succeeded for some other reason, e.g. because the link
- * just finished its initialization. */
- for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
- *speed = i;
- ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
- &q, sizeof(quadlet_t));
- if (ret)
- break;
- *buffer = q;
- good_speed = i;
- }
- if (good_speed <= IEEE1394_SPEED_MAX) {
- HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s",
- NODE_BUS_ARGS(ci->host, ci->nodeid),
- hpsb_speedto_str[good_speed]);
- *speed = good_speed;
- ci->speed_unverified = 0;
- return 0;
- }
- *speed = old_speed;
- return ret;
-}
static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
void *buffer, void *__ci)
{
struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
- int i, ret;
+ int i, ret = 0;
for (i = 1; ; i++) {
ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
buffer, length);
- if (!ret) {
- ci->speed_unverified = 0;
- break;
- }
- /* Give up after 3rd failure. */
- if (i == 3)
+ if (!ret || i == 3)
break;
- /* The ieee1394_core guessed the node's speed capability from
- * the self ID. Check whether a lower speed works. */
- if (ci->speed_unverified && length == sizeof(quadlet_t)) {
- ret = nodemgr_check_speed(ci, addr, buffer);
- if (!ret)
- break;
- }
if (msleep_interruptible(334))
return -EINTR;
}
+
return ret;
}
static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
-/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically
- * here, therefore displayed values may be occasionally wrong. */
static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
- return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64));
+ return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1);
}
static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
ci->host = host;
ci->nodeid = nodeid;
ci->generation = generation;
- ci->speed_unverified =
- host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100;
/* We need to detect when the ConfigROM's generation has changed,
* so we only update the node's info when it needs to be. */
}
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
static void nodemgr_suspend_ne(struct node_entry *ne)
{
struct class_device *cdev;
}
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
static void nodemgr_update_pdrv(struct node_entry *ne)
{
struct unit_directory *ud;
struct hpsb_protocol_driver *pdrv;
+ struct class *class = &nodemgr_ud_class;
struct class_device *cdev;
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
+ down_read(&class->subsys.rwsem);
+ list_for_each_entry(cdev, &class->children, node) {
ud = container_of(cdev, struct unit_directory, class_dev);
if (ud->ne != ne || !ud->device.driver)
continue;
up_write(&ud->device.bus->subsys.rwsem);
}
}
+ up_read(&class->subsys.rwsem);
}
}
-/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the
- * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
{
struct device *dev;