V4L/DVB: tvp5150: support new vbi ops to set/get VBI format
[safe/jmp/linux-2.6] / drivers / ieee1394 / nodemgr.c
index b9d3f46..1835021 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/kernel.h>
+#include <linux/kmemcheck.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -18,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
-#include <linux/semaphore.h>
 #include <asm/atomic.h>
 
 #include "csr.h"
@@ -39,7 +39,10 @@ struct nodemgr_csr_info {
        struct hpsb_host *host;
        nodeid_t nodeid;
        unsigned int generation;
+
+       kmemcheck_bitfield_begin(flags);
        unsigned int speed_unverified:1;
+       kmemcheck_bitfield_end(flags);
 };
 
 
@@ -67,7 +70,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
        for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
                *speed = i;
                error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 &q, sizeof(quadlet_t));
+                                 &q, 4);
                if (error)
                        break;
                *buffer = q;
@@ -85,7 +88,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
        return error;
 }
 
-static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
+static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
                            void *buffer, void *__ci)
 {
        struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
@@ -93,7 +96,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
 
        for (i = 1; ; i++) {
                error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 buffer, length);
+                                 buffer, 4);
                if (!error) {
                        ci->speed_unverified = 0;
                        break;
@@ -104,7 +107,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
 
                /* 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)) {
+               if (ci->speed_unverified) {
                        error = nodemgr_check_speed(ci, addr, buffer);
                        if (!error)
                                break;
@@ -115,14 +118,8 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
        return error;
 }
 
-static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
-{
-       return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3;
-}
-
 static struct csr1212_bus_ops nodemgr_csr_ops = {
        .bus_read =     nodemgr_bus_read,
-       .get_max_rom =  nodemgr_get_max_rom
 };
 
 
@@ -154,9 +151,6 @@ struct host_info {
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
 static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
-static void nodemgr_reactivate_ne(struct node_entry *ne);
-static void nodemgr_remove_ne(struct node_entry *ne);
-static struct node_entry *find_entry_by_guid(u64 guid);
 
 struct bus_type ieee1394_bus_type = {
        .name           = "ieee1394",
@@ -385,27 +379,6 @@ static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute
 static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
 
 
-static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count)
-{
-       struct node_entry *ne;
-       u64 guid = (u64)simple_strtoull(buf, NULL, 16);
-
-       ne = find_entry_by_guid(guid);
-
-       if (ne == NULL || !ne->in_limbo)
-               return -EINVAL;
-
-       nodemgr_remove_ne(ne);
-
-       return count;
-}
-static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n");
-}
-static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
-
-
 static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
                             size_t count)
 {
@@ -442,7 +415,6 @@ static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set
 
 
 struct bus_attribute *const fw_bus_attrs[] = {
-       &bus_attr_destroy_node,
        &bus_attr_rescan,
        &bus_attr_ignore_drivers,
        NULL
@@ -515,7 +487,7 @@ static struct device_attribute *const fw_host_attrs[] = {
 static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf)
 {
        struct hpsb_protocol_driver *driver;
-       struct ieee1394_device_id *id;
+       const struct ieee1394_device_id *id;
        int length = 0;
        char *scratch = buf;
 
@@ -689,7 +661,7 @@ 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;
+       const struct ieee1394_device_id *id;
 
        /* We only match unit directories */
        if (dev->platform_data != &nodemgr_ud_platform_data)
@@ -851,13 +823,11 @@ static struct node_entry *nodemgr_create_node(octlet_t guid,
        memcpy(&ne->device, &nodemgr_dev_template_ne,
               sizeof(ne->device));
        ne->device.parent = &host->device;
-       snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
-                (unsigned long long)(ne->guid));
+       dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid));
 
        ne->node_dev.parent = &ne->device;
        ne->node_dev.class = &nodemgr_ne_class;
-       snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
-               (unsigned long long)(ne->guid));
+       dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid));
 
        if (device_register(&ne->device))
                goto fail_devreg;
@@ -957,13 +927,11 @@ static void nodemgr_register_device(struct node_entry *ne,
 
        ud->device.parent = parent;
 
-       snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
-                ne->device.bus_id, ud->id);
+       dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id);
 
        ud->unit_dev.parent = &ud->device;
        ud->unit_dev.class = &nodemgr_ud_class;
-       snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
-                ne->device.bus_id, ud->id);
+       dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id);
 
        if (device_register(&ud->device))
                goto fail_devreg;
@@ -978,7 +946,7 @@ static void nodemgr_register_device(struct node_entry *ne,
 fail_classdevreg:
        device_unregister(&ud->device);
 fail_devreg:
-       HPSB_ERR("Failed to create unit %s", ud->device.bus_id);
+       HPSB_ERR("Failed to create unit %s", dev_name(&ud->device));
 }      
 
 
@@ -1006,6 +974,9 @@ static struct unit_directory *nodemgr_process_unit_directory
        ud->ud_kv = ud_kv;
        ud->id = (*id)++;
 
+       /* inherit vendor_id from root directory if none exists in unit dir */
+       ud->vendor_id = ne->vendor_id;
+
        csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
                switch (kv->key.id) {
                case CSR1212_KV_ID_VENDOR:
@@ -1300,14 +1271,20 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
                csr1212_destroy_csr(csr);
        }
 
-       if (ne->in_limbo)
-               nodemgr_reactivate_ne(ne);
-
-       /* Mark the node current */
+       /* Finally, mark the node current */
+       smp_wmb();
        ne->generation = generation;
-}
 
+       if (ne->in_limbo) {
+               device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
+               ne->in_limbo = false;
 
+               HPSB_DEBUG("Node reactivated: "
+                          "ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+                          NODE_BUS_ARGS(ne->host, ne->nodeid),
+                          (unsigned long long)ne->guid);
+       }
+}
 
 static void nodemgr_node_scan_one(struct hpsb_host *host,
                                  nodeid_t nodeid, int generation)
@@ -1319,6 +1296,7 @@ static void nodemgr_node_scan_one(struct hpsb_host *host,
        u8 *speed;
 
        ci = kmalloc(sizeof(*ci), GFP_KERNEL);
+       kmemcheck_annotate_bitfield(ci, flags);
        if (!ci)
                return;
 
@@ -1392,75 +1370,14 @@ static void nodemgr_node_scan(struct hpsb_host *host, int generation)
        }
 }
 
-static int pause_ne(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct node_entry *ne = data;
-       int error;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       error = 1; /* release if suspend is not implemented */
-                       if (drv->suspend) {
-                               down(&ud->device.sem);
-                               error = drv->suspend(&ud->device, PMSG_SUSPEND);
-                               up(&ud->device.sem);
-                       }
-                       if (error)
-                               device_release_driver(&ud->device);
-                       put_driver(drv);
-               }
-       }
-
-       return 0;
-}
-
 static void nodemgr_pause_ne(struct node_entry *ne)
 {
-       HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+       HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
                   NODE_BUS_ARGS(ne->host, ne->nodeid),
                   (unsigned long long)ne->guid);
 
-       ne->in_limbo = 1;
+       ne->in_limbo = true;
        WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
-
-       class_for_each_device(&nodemgr_ud_class, NULL, ne, pause_ne);
-}
-
-static int reactivate_ne(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct node_entry *ne = data;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       if (drv->resume) {
-                               down(&ud->device.sem);
-                               drv->resume(&ud->device);
-                               up(&ud->device.sem);
-                       }
-                       put_driver(drv);
-               }
-       }
-
-       return 0;
-}
-
-static void nodemgr_reactivate_ne(struct node_entry *ne)
-{
-       ne->in_limbo = 0;
-       device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-
-       class_for_each_device(&nodemgr_ud_class, NULL, ne, reactivate_ne);
-       HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid),
-                  (unsigned long long)ne->guid);
 }
 
 static int update_pdrv(struct device *dev, void *data)
@@ -1479,9 +1396,9 @@ static int update_pdrv(struct device *dev, void *data)
                        pdrv = container_of(drv, struct hpsb_protocol_driver,
                                            driver);
                        if (pdrv->update) {
-                               down(&ud->device.sem);
+                               device_lock(&ud->device);
                                error = pdrv->update(ud);
-                               up(&ud->device.sem);
+                               device_unlock(&ud->device);
                        }
                        if (error)
                                device_release_driver(&ud->device);
@@ -1497,7 +1414,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
        class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
 }
 
-
 /* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
  * seems like an optional service but in the end it is practically mandatory
  * as a consequence of these clauses.
@@ -1574,7 +1490,7 @@ static int node_probe(struct device *dev, void *data)
        return 0;
 }
 
-static void nodemgr_node_probe(struct hpsb_host *host, int generation)
+static int nodemgr_node_probe(struct hpsb_host *host, int generation)
 {
        struct node_probe_parameter p;
 
@@ -1595,11 +1511,11 @@ static void nodemgr_node_probe(struct hpsb_host *host, int generation)
         */
        p.probe_now = false;
        if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return;
+               return 0;
 
        p.probe_now = true;
        if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return;
+               return 0;
        /*
         * Now let's tell the bus to rescan our devices. This may seem
         * like overhead, but the driver-model core will only scan a
@@ -1611,6 +1527,27 @@ static void nodemgr_node_probe(struct hpsb_host *host, int generation)
         */
        if (bus_rescan_devices(&ieee1394_bus_type) != 0)
                HPSB_DEBUG("bus_rescan_devices had an error");
+
+       return 1;
+}
+
+static int remove_nodes_in_limbo(struct device *dev, void *data)
+{
+       struct node_entry *ne;
+
+       if (dev->bus != &ieee1394_bus_type)
+               return 0;
+
+       ne = container_of(dev, struct node_entry, device);
+       if (ne->in_limbo)
+               nodemgr_remove_ne(ne);
+
+       return 0;
+}
+
+static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
+{
+       device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
 }
 
 static int nodemgr_send_resume_packet(struct hpsb_host *host)
@@ -1750,6 +1687,7 @@ static int nodemgr_host_thread(void *data)
                g = get_hpsb_generation(host);
                for (i = 0; i < 4 ; i++) {
                        msleep_interruptible(63);
+                       try_to_freeze();
                        if (kthread_should_stop())
                                goto exit;
 
@@ -1781,10 +1719,25 @@ static int nodemgr_host_thread(void *data)
 
                /* This actually does the full probe, with sysfs
                 * registration. */
-               nodemgr_node_probe(host, generation);
+               if (!nodemgr_node_probe(host, generation))
+                       continue;
 
                /* Update some of our sysfs symlinks */
                nodemgr_update_host_dev_links(host);
+
+               /* Sleep 3 seconds */
+               for (i = 3000/200; i; i--) {
+                       msleep_interruptible(200);
+                       try_to_freeze();
+                       if (kthread_should_stop())
+                               goto exit;
+
+                       if (generation != get_hpsb_generation(host))
+                               break;
+               }
+               /* Remove nodes which are gone, unless a bus reset happened */
+               if (!i)
+                       nodemgr_remove_nodes_in_limbo(host);
        }
 exit:
        HPSB_VERBOSE("NodeMgr: Exiting thread");
@@ -1853,7 +1806,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
 {
        packet->host = ne->host;
        packet->generation = ne->generation;
-       barrier();
+       smp_rmb();
        packet->node_id = ne->nodeid;
 }
 
@@ -1862,7 +1815,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
 {
        unsigned int generation = ne->generation;
 
-       barrier();
+       smp_rmb();
        return hpsb_write(ne->host, ne->nodeid, generation,
                          addr, buffer, length);
 }