#include "core.h"
 
+#define define_fw_printk_level(func, kern_level)               \
+void func(const struct fw_card *card, const char *fmt, ...)    \
+{                                                              \
+       struct va_format vaf;                                   \
+       va_list args;                                           \
+                                                               \
+       va_start(args, fmt);                                    \
+       vaf.fmt = fmt;                                          \
+       vaf.va = &args;                                         \
+       printk(kern_level KBUILD_MODNAME " %s: %pV",            \
+              dev_name(card->device), &vaf);                   \
+       va_end(args);                                           \
+}
+define_fw_printk_level(fw_err, KERN_ERR);
+define_fw_printk_level(fw_notice, KERN_NOTICE);
+
 int fw_compute_block_crc(__be32 *block)
 {
        int length;
                fw_iso_resource_manage(card, generation, 1ULL << 31,
                                       &channel, &bandwidth, true);
                if (channel != 31) {
-                       fw_notify("failed to allocate broadcast channel\n");
+                       fw_notice(card, "failed to allocate broadcast channel\n");
                        return;
                }
                card->broadcast_channel_allocated = true;
 
                if (!card->irm_node->link_on) {
                        new_root_id = local_id;
-                       fw_notify("%s, making local node (%02x) root.\n",
+                       fw_notice(card, "%s, making local node (%02x) root\n",
                                  "IRM has link off", new_root_id);
                        goto pick_me;
                }
 
                if (irm_is_1394_1995_only && !keep_this_irm) {
                        new_root_id = local_id;
-                       fw_notify("%s, making local node (%02x) root.\n",
+                       fw_notice(card, "%s, making local node (%02x) root\n",
                                  "IRM is not 1394a compliant", new_root_id);
                        goto pick_me;
                }
                         * root, and thus, IRM.
                         */
                        new_root_id = local_id;
-                       fw_notify("%s, making local node (%02x) root.\n",
+                       fw_notice(card, "%s, making local node (%02x) root\n",
                                  "BM lock failed", new_root_id);
                        goto pick_me;
                }
        spin_unlock_irq(&card->lock);
 
        if (do_reset) {
-               fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",
-                         card->index, new_root_id, gap_count);
+               fw_notice(card, "phy config: new root=%x, gap_count=%d\n",
+                         new_root_id, gap_count);
                fw_send_phy_config(card, new_root_id, generation, gap_count);
                reset_bus(card, true);
                /* Will allocate broadcast channel after the reset. */
 
 
        e = kzalloc(sizeof(*e), GFP_KERNEL);
        if (e == NULL) {
-               fw_notify("Out of memory when allocating event\n");
+               fw_notice(client->device->card, "out of memory when allocating event\n");
                return;
        }
 
        r = kmalloc(sizeof(*r), GFP_ATOMIC);
        e = kmalloc(sizeof(*e), GFP_ATOMIC);
        if (r == NULL || e == NULL) {
-               fw_notify("Out of memory when allocating event\n");
+               fw_notice(card, "out of memory when allocating event\n");
                goto failed;
        }
        r->card    = card;
 
        e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);
        if (e == NULL) {
-               fw_notify("Out of memory when allocating event\n");
+               fw_notice(context->card, "out of memory when allocating event\n");
                return;
        }
        e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
 
        e = kmalloc(sizeof(*e), GFP_ATOMIC);
        if (e == NULL) {
-               fw_notify("Out of memory when allocating event\n");
+               fw_notice(context->card, "out of memory when allocating event\n");
                return;
        }
        e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL;
        list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {
                e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);
                if (e == NULL) {
-                       fw_notify("Out of memory when allocating event\n");
+                       fw_notice(card, "out of memory when allocating event\n");
                        break;
                }
                e->phy_packet.closure   = client->phy_receiver_closure;
 
  */
 static int read_config_rom(struct fw_device *device, int generation)
 {
+       struct fw_card *card = device->card;
        const u32 *old_rom, *new_rom;
        u32 *rom, *stack;
        u32 sp, key;
         */
        if ((rom[2] & 0x7) < device->max_speed ||
            device->max_speed == SCODE_BETA ||
-           device->card->beta_repeaters_present) {
+           card->beta_repeaters_present) {
                u32 dummy;
 
                /* for S1600 and S3200 */
                if (device->max_speed == SCODE_BETA)
-                       device->max_speed = device->card->link_speed;
+                       device->max_speed = card->link_speed;
 
                while (device->max_speed > SCODE_100) {
                        if (read_rom(device, generation, 0, &dummy) ==
                         * a firmware bug.  Ignore this whole block, i.e.
                         * simply set a fake block length of 0.
                         */
-                       fw_error("skipped invalid ROM block %x at %llx\n",
-                                rom[i],
-                                i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
+                       fw_err(card, "skipped invalid ROM block %x at %llx\n",
+                              rom[i],
+                              i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
                        rom[i] = 0;
                        end = i;
                }
                         * the ROM don't have to check offsets all the time.
                         */
                        if (i + (rom[i] & 0xffffff) >= MAX_CONFIG_ROM_SIZE) {
-                               fw_error("skipped unsupported ROM entry %x at %llx\n",
-                                        rom[i],
-                                        i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
+                               fw_err(card,
+                                      "skipped unsupported ROM entry %x at %llx\n",
+                                      rom[i],
+                                      i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
                                rom[i] = 0;
                                continue;
                        }
                 */
                unit = kzalloc(sizeof(*unit), GFP_KERNEL);
                if (unit == NULL) {
-                       fw_error("failed to allocate memory for unit\n");
+                       fw_err(device->card, "out of memory for unit\n");
                        continue;
                }
 
                smp_wmb();  /* update node_id before generation */
                old->generation = card->generation;
                old->config_rom_retries = 0;
-               fw_notify("rediscovered device %s\n", dev_name(dev));
+               fw_notice(card, "rediscovered device %s\n", dev_name(dev));
 
                PREPARE_DELAYED_WORK(&old->work, fw_device_update);
                fw_schedule_device_work(old, 0);
 {
        struct fw_device *device =
                container_of(work, struct fw_device, work.work);
+       struct fw_card *card = device->card;
        struct device *revived_dev;
        int minor, ret;
 
                        fw_schedule_device_work(device, RETRY_DELAY);
                } else {
                        if (device->node->link_on)
-                               fw_notify("giving up on config rom for node id %x\n",
+                               fw_notice(card, "giving up on Config ROM for node id %x\n",
                                          device->node_id);
-                       if (device->node == device->card->root_node)
-                               fw_schedule_bm_work(device->card, 0);
+                       if (device->node == card->root_node)
+                               fw_schedule_bm_work(card, 0);
                        fw_device_release(&device->device);
                }
                return;
        }
 
-       revived_dev = device_find_child(device->card->device,
+       revived_dev = device_find_child(card->device,
                                        device, lookup_existing_device);
        if (revived_dev) {
                put_device(revived_dev);
 
        device->device.bus = &fw_bus_type;
        device->device.type = &fw_device_type;
-       device->device.parent = device->card->device;
+       device->device.parent = card->device;
        device->device.devt = MKDEV(fw_cdev_major, minor);
        dev_set_name(&device->device, "fw%d", minor);
 
                                &device->attribute_group);
 
        if (device_add(&device->device)) {
-               fw_error("Failed to add device.\n");
+               fw_err(card, "failed to add device\n");
                goto error_with_cdev;
        }
 
                PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
                fw_schedule_device_work(device, SHUTDOWN_DELAY);
        } else {
-               if (device->config_rom_retries)
-                       fw_notify("created device %s: GUID %08x%08x, S%d00, "
-                                 "%d config ROM retries\n",
-                                 dev_name(&device->device),
-                                 device->config_rom[3], device->config_rom[4],
-                                 1 << device->max_speed,
-                                 device->config_rom_retries);
-               else
-                       fw_notify("created device %s: GUID %08x%08x, S%d00\n",
-                                 dev_name(&device->device),
-                                 device->config_rom[3], device->config_rom[4],
-                                 1 << device->max_speed);
+               fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n",
+                         dev_name(&device->device),
+                         device->config_rom[3], device->config_rom[4],
+                         1 << device->max_speed);
                device->config_rom_retries = 0;
 
                set_broadcast_channel(device, device->generation);
         * just end up running the IRM work a couple of extra times -
         * pretty harmless.
         */
-       if (device->node == device->card->root_node)
-               fw_schedule_bm_work(device->card, 0);
+       if (device->node == card->root_node)
+               fw_schedule_bm_work(card, 0);
 
        return;
 
                           FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
                goto gone;
 
-       fw_notify("refreshed device %s\n", dev_name(&device->device));
+       fw_notice(card, "refreshed device %s\n", dev_name(&device->device));
        device->config_rom_retries = 0;
        goto out;
 
  give_up:
-       fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
+       fw_notice(card, "giving up on refresh of device %s\n",
+                 dev_name(&device->device));
  gone:
        atomic_set(&device->state, FW_DEVICE_GONE);
        PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
 
                next_sid = count_ports(sid, &port_count, &child_port_count);
 
                if (next_sid == NULL) {
-                       fw_error("Inconsistent extended self IDs.\n");
+                       fw_err(card, "inconsistent extended self IDs\n");
                        return NULL;
                }
 
                q = *sid;
                if (phy_id != SELF_ID_PHY_ID(q)) {
-                       fw_error("PHY ID mismatch in self ID: %d != %d.\n",
-                                phy_id, SELF_ID_PHY_ID(q));
+                       fw_err(card, "PHY ID mismatch in self ID: %d != %d\n",
+                              phy_id, SELF_ID_PHY_ID(q));
                        return NULL;
                }
 
                if (child_port_count > stack_depth) {
-                       fw_error("Topology stack underflow\n");
+                       fw_err(card, "topology stack underflow\n");
                        return NULL;
                }
 
 
                node = fw_node_create(q, port_count, card->color);
                if (node == NULL) {
-                       fw_error("Out of memory while building topology.\n");
+                       fw_err(card, "out of memory while building topology\n");
                        return NULL;
                }
 
                 */
                if ((next_sid == end && parent_count != 0) ||
                    (next_sid < end && parent_count != 1)) {
-                       fw_error("Parent port inconsistency for node %d: "
-                                "parent_count=%d\n", phy_id, parent_count);
+                       fw_err(card, "parent port inconsistency for node %d: "
+                              "parent_count=%d\n", phy_id, parent_count);
                        return NULL;
                }
 
         */
        if (!is_next_generation(generation, card->generation) &&
            card->local_node != NULL) {
-               fw_notify("skipped bus generations, destroying all nodes\n");
+               fw_notice(card, "skipped bus generations, destroying all nodes\n");
                fw_destroy_nodes(card);
                card->bm_retries = 0;
        }
        card->color++;
 
        if (local_node == NULL) {
-               fw_error("topology build failed\n");
+               fw_err(card, "topology build failed\n");
                /* FIXME: We need to issue a bus reset in this case. */
        } else if (card->local_node == NULL) {
                card->local_node = local_node;
 
                break;
 
        default:
-               fw_error("ERROR - corrupt request received - %08x %08x %08x\n",
+               fw_notice(card, "ERROR - corrupt request received - %08x %08x %08x\n",
                         p->header[0], p->header[1], p->header[2]);
                return NULL;
        }
 
        if (&t->link == &card->transaction_list) {
  timed_out:
-               fw_notify("Unsolicited response (source %x, tlabel %x)\n",
+               fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
                          source, tlabel);
                return;
        }
 
 #ifndef _FIREWIRE_CORE_H
 #define _FIREWIRE_CORE_H
 
+#include <linux/compiler.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/list.h>
 
 /* -card */
 
+extern __printf(2, 3)
+void fw_err(const struct fw_card *card, const char *fmt, ...);
+extern __printf(2, 3)
+void fw_notice(const struct fw_card *card, const char *fmt, ...);
+
 /* bitfields within the PHY registers */
 #define PHY_LINK_ACTIVE                0x80
 #define PHY_CONTENDER          0x40
 
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
 
-#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
-#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-
 #define CSR_REGISTER_BASE              0xfffff0000000ULL
 
 /* register offsets are relative to CSR_REGISTER_BASE */