From bda3b8a1faf209a98063ccd77d6833a2bb0fc77e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:23:28 +0200 Subject: firewire: core: retry on local errors in bus manager election When the candidate bus manager fails to do the lock request with which it tries to become bus manager, it assumes that the current IRM is not actually IRM capable and forces itself to become root. However, if that lock request failed because the local node itself was not able to send it, then we cannot blame the current IRM and should not steal its rootness. In this case, RCODE_SEND_ERROR is likely to indicate a temporary error condition such as exhausted tlabels or low memory, so we better try again later. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 9dcb30466ec0..901435cdd5c2 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -306,6 +306,16 @@ static void fw_card_bm_work(struct work_struct *work) goto out; } + if (rcode == RCODE_SEND_ERROR) { + /* + * We have been unable to send the lock request due to + * some local problem. Let's try again later and hope + * that the problem has gone away by then. + */ + fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); + goto out; + } + spin_lock_irqsave(&card->lock, flags); if (rcode != RCODE_COMPLETE) { -- cgit v1.2.3 From 8e4b50f94e8c1435a3e0ece42b7f97bc857d0145 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:26:28 +0200 Subject: firewire: core: add CSR SPLIT_TIMEOUT support Implement the SPLIT_TIMEOUT registers. Besides being required by the spec, this is desirable for some IIDC devices and necessary for many audio devices to be able to increase the timeout from userspace. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 901435cdd5c2..d0f15c2f1e1d 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -428,6 +428,10 @@ void fw_card_initialize(struct fw_card *card, card->device = device; card->current_tlabel = 0; card->tlabel_mask = 0; + card->split_timeout_hi = 0; + card->split_timeout_lo = 800 << 19; + card->split_timeout_cycles = 800; + card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10); card->color = 0; card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; -- cgit v1.2.3 From 7e0e314f198d5048b74c8f0ef9f4c1c02e5ecfc9 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:37:15 +0200 Subject: firewire: core: add CSR abdicate support Implement the abdicate bit, which is required for bus manager capable nodes and tested by the Base 1394 Test Suite. Finally, something to do at a command reset! :-) Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index d0f15c2f1e1d..7c4cf6cfa746 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -260,7 +260,8 @@ static void fw_card_bm_work(struct work_struct *work) grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); - if (is_next_generation(generation, card->bm_generation) || + if ((is_next_generation(generation, card->bm_generation) && + !card->bm_abdicate) || (card->bm_generation != generation && grace)) { /* * This first step is to figure out who is IRM and -- cgit v1.2.3 From e91b2787d0a2e4719b016e8dec0afd2d5ab6c30f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:40:49 +0200 Subject: firewire: allocate broadcast channel in hardware On OHCI 1.1 controllers, let the hardware allocate the broadcast channel automatically. This removes a theoretical race condition directly after a bus reset where it could be possible to read the channel allocation register with channel 31 still being unallocated. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 7c4cf6cfa746..faf2eee473b9 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -208,13 +208,19 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) { int channel, bandwidth = 0; - fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, - &bandwidth, true, card->bm_transaction_data); - if (channel == 31) { + if (!card->broadcast_channel_allocated) { + fw_iso_resource_manage(card, generation, 1ULL << 31, + &channel, &bandwidth, true, + card->bm_transaction_data); + if (channel != 31) { + fw_notify("failed to allocate broadcast channel\n"); + return; + } card->broadcast_channel_allocated = true; - device_for_each_child(card->device, (void *)(long)generation, - fw_device_set_broadcast_channel); } + + device_for_each_child(card->device, (void *)(long)generation, + fw_device_set_broadcast_channel); } static const char gap_count_table[] = { -- cgit v1.2.3 From c374ab424249b6ab91b1aee7460419d3f2c321df Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 10 Jun 2010 08:41:51 +0200 Subject: firewire: core: always enable cycle master packets As part of the bus manager responsibilities, make sure that the cycle master sends cycle start packets. This is needed when the old bus manager disabled the cycle master's cmstr bit and there are iso-capable nodes on the new bus. Signed-off-by: Clemens Ladisch --- drivers/firewire/core-card.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index faf2eee473b9..ef6f2616cac7 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -369,10 +369,8 @@ static void fw_card_bm_work(struct work_struct *work) goto out; } else if (root_device_is_cmc) { /* - * FIXME: I suppose we should set the cmstr bit in the - * STATE_CLEAR register of this node, as described in - * 1394-1995, 8.4.2.6. Also, send out a force root - * packet for this node. + * We will send out a force root packet for this + * node as part of the gap count optimization. */ new_root_id = root_id; } else { @@ -413,11 +411,25 @@ static void fw_card_bm_work(struct work_struct *work) fw_send_phy_config(card, new_root_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); /* Will allocate broadcast channel after the reset. */ - } else { - if (local_id == irm_id) - allocate_broadcast_channel(card, generation); + goto out; } + if (root_device_is_cmc) { + /* + * Make sure that the cycle master sends cycle start packets. + */ + card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); + rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, + root_id, generation, SCODE_100, + CSR_REGISTER_BASE + CSR_STATE_SET, + card->bm_transaction_data, sizeof(u32)); + if (rcode == RCODE_GENERATION) + goto out; + } + + if (local_id == irm_id) + allocate_broadcast_channel(card, generation); + out: fw_node_put(root_node); out_put_card: -- cgit v1.2.3 From e847cc832bab50aad939a0c30414cd986637564d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 12 Jun 2010 20:29:07 +0200 Subject: firewire: drop sizeof expressions from some request size arguments In case of fw_card_bm_work()'s lock request, the present sizeof expression is going to be wrong if somebody changes the fw_card's DMA scratch buffer's size in the future. In case of quadlet write requests, sizeof(u32) is just silly; it's 4. In case of SBP-2 ORB pointer write requests, 8 is arguably quicker to understand as the correct and only possible value than sizeof(some_datum). Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index ef6f2616cac7..156b098b0ada 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -296,8 +296,7 @@ static void fw_card_bm_work(struct work_struct *work) rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - card->bm_transaction_data, - sizeof(card->bm_transaction_data)); + card->bm_transaction_data, 8); if (rcode == RCODE_GENERATION) /* Another bus reset, BM work has been rescheduled. */ @@ -422,7 +421,7 @@ static void fw_card_bm_work(struct work_struct *work) rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, root_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_STATE_SET, - card->bm_transaction_data, sizeof(u32)); + card->bm_transaction_data, 4); if (rcode == RCODE_GENERATION) goto out; } -- cgit v1.2.3 From ae948011071c12ff6a328348859c717ea885ed40 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 21 Jun 2010 23:23:52 +0200 Subject: firewire: core: no need to track irq flags in bm_work This is a workqueue job and always entered with IRQs enabled. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 156b098b0ada..11fc81500f82 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -239,17 +239,16 @@ static void fw_card_bm_work(struct work_struct *work) struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root_device; struct fw_node *root_node; - unsigned long flags; int root_id, new_root_id, irm_id, local_id; int gap_count, generation, grace, rcode; bool do_reset = false; bool root_device_is_running; bool root_device_is_cmc; - spin_lock_irqsave(&card->lock, flags); + spin_lock_irq(&card->lock); if (card->local_node == NULL) { - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); goto out_put_card; } @@ -291,7 +290,7 @@ static void fw_card_bm_work(struct work_struct *work) card->bm_transaction_data[0] = cpu_to_be32(0x3f); card->bm_transaction_data[1] = cpu_to_be32(local_id); - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, @@ -322,7 +321,7 @@ static void fw_card_bm_work(struct work_struct *work) goto out; } - spin_lock_irqsave(&card->lock, flags); + spin_lock_irq(&card->lock); if (rcode != RCODE_COMPLETE) { /* @@ -341,7 +340,7 @@ static void fw_card_bm_work(struct work_struct *work) * We weren't BM in the last generation, and the last * bus reset is less than 125ms ago. Reschedule this job. */ - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); goto out; } @@ -364,7 +363,7 @@ static void fw_card_bm_work(struct work_struct *work) * If we haven't probed this device yet, bail out now * and let's try again once that's done. */ - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); goto out; } else if (root_device_is_cmc) { /* @@ -402,7 +401,7 @@ static void fw_card_bm_work(struct work_struct *work) (card->gap_count != gap_count || new_root_id != root_id)) do_reset = true; - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); if (do_reset) { fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", -- cgit v1.2.3 From 250b2b6dd421c9f8844a867d2ac06e0661e0ad93 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 21 Jun 2010 23:24:35 +0200 Subject: firewire: cdev: fix fw_cdev_event_bus_reset.bm_node_id Fix an obscure ABI feature that is a bit of a hassle to implement. However, somebody put it into the ABI, so let's fill in a sensible value there. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 11fc81500f82..6c316cfe70c4 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -239,7 +239,7 @@ static void fw_card_bm_work(struct work_struct *work) struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root_device; struct fw_node *root_node; - int root_id, new_root_id, irm_id, local_id; + int root_id, new_root_id, irm_id, bm_id, local_id; int gap_count, generation, grace, rcode; bool do_reset = false; bool root_device_is_running; @@ -301,9 +301,15 @@ static void fw_card_bm_work(struct work_struct *work) /* Another bus reset, BM work has been rescheduled. */ goto out; - if (rcode == RCODE_COMPLETE && - card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { + bm_id = be32_to_cpu(card->bm_transaction_data[0]); + spin_lock_irq(&card->lock); + if (rcode == RCODE_COMPLETE && generation == card->generation) + card->bm_node_id = + bm_id == 0x3f ? local_id : 0xffc0 | bm_id; + spin_unlock_irq(&card->lock); + + if (rcode == RCODE_COMPLETE && bm_id != 0x3f) { /* Somebody else is BM. Only act as IRM. */ if (local_id == irm_id) allocate_broadcast_channel(card, generation); -- cgit v1.2.3 From 02d37bed188c500ee7afb0a2dc6b65a80704c58e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 8 Jul 2010 16:09:06 +0200 Subject: firewire: core: integrate software-forced bus resets with bus management Bus resets which are triggered - by the kernel drivers after updates of the local nodes' config ROM, - by userspace software via ioctl shall be deferred until after >=2 seconds after the last bus reset. If multiple modifications of the local nodes' config ROM happen in a row, only a single bus reset should happen after them. When the local node's link goes from inactive to active or vice versa, and at the two occasions of bus resets mentioned above --- and if the current gap count differs from 63 --- the bus reset should be preceded by a PHY configuration packet that reaffirms the gap count. Otherwise a bus manager would have to reset the bus again right after that. This is necessary to promote bus stability, e.g. leave grace periods for allocations and reallocations of isochronous channels and bandwidth, SBP-2 reconnections etc.; see IEEE 1394 clause 8.2.1. This change implements all of the above by moving bus reset initiation into a delayed work (except for bus resets which are triggered by the bus manager workqueue job and are performed there immediately). It comes with a necessary addition to the card driver methods that allows to get the current gap count from PHY registers. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 68 +++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 16 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 6c316cfe70c4..2bb5c036e806 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -204,6 +204,45 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) } EXPORT_SYMBOL(fw_core_remove_descriptor); +static int reset_bus(struct fw_card *card, bool short_reset) +{ + int reg = short_reset ? 5 : 1; + int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; + + return card->driver->update_phy_reg(card, reg, 0, bit); +} + +void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset) +{ + /* We don't try hard to sort out requests of long vs. short resets. */ + card->br_short = short_reset; + + /* Use an arbitrary short delay to combine multiple reset requests. */ + fw_card_get(card); + if (!schedule_delayed_work(&card->br_work, + delayed ? DIV_ROUND_UP(HZ, 100) : 0)) + fw_card_put(card); +} +EXPORT_SYMBOL(fw_schedule_bus_reset); + +static void br_work(struct work_struct *work) +{ + struct fw_card *card = container_of(work, struct fw_card, br_work.work); + + /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ + if (card->reset_jiffies != 0 && + time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) { + if (!schedule_delayed_work(&card->br_work, 2 * HZ)) + fw_card_put(card); + return; + } + + fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation, + FW_PHY_CONFIG_CURRENT_GAP_COUNT); + reset_bus(card, card->br_short); + fw_card_put(card); +} + static void allocate_broadcast_channel(struct fw_card *card, int generation) { int channel, bandwidth = 0; @@ -230,13 +269,13 @@ static const char gap_count_table[] = { void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) { fw_card_get(card); - if (!schedule_delayed_work(&card->work, delay)) + if (!schedule_delayed_work(&card->bm_work, delay)) fw_card_put(card); } -static void fw_card_bm_work(struct work_struct *work) +static void bm_work(struct work_struct *work) { - struct fw_card *card = container_of(work, struct fw_card, work.work); + struct fw_card *card = container_of(work, struct fw_card, bm_work.work); struct fw_device *root_device; struct fw_node *root_node; int root_id, new_root_id, irm_id, bm_id, local_id; @@ -413,7 +452,7 @@ static void fw_card_bm_work(struct work_struct *work) fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", card->index, new_root_id, gap_count); fw_send_phy_config(card, new_root_id, generation, gap_count); - fw_core_initiate_bus_reset(card, 1); + reset_bus(card, true); /* Will allocate broadcast channel after the reset. */ goto out; } @@ -465,7 +504,8 @@ void fw_card_initialize(struct fw_card *card, card->local_node = NULL; - INIT_DELAYED_WORK(&card->work, fw_card_bm_work); + INIT_DELAYED_WORK(&card->br_work, br_work); + INIT_DELAYED_WORK(&card->bm_work, bm_work); } EXPORT_SYMBOL(fw_card_initialize); @@ -491,7 +531,6 @@ int fw_card_add(struct fw_card *card, } EXPORT_SYMBOL(fw_card_add); - /* * The next few functions implement a dummy driver that is used once a card * driver shuts down an fw_card. This allows the driver to cleanly unload, @@ -507,6 +546,11 @@ static int dummy_enable(struct fw_card *card, return -1; } +static int dummy_read_phy_reg(struct fw_card *card, int address) +{ + return -ENODEV; +} + static int dummy_update_phy_reg(struct fw_card *card, int address, int clear_bits, int set_bits) { @@ -547,6 +591,7 @@ static int dummy_enable_phys_dma(struct fw_card *card, static const struct fw_card_driver dummy_driver_template = { .enable = dummy_enable, + .read_phy_reg = dummy_read_phy_reg, .update_phy_reg = dummy_update_phy_reg, .set_config_rom = dummy_set_config_rom, .send_request = dummy_send_request, @@ -568,7 +613,7 @@ void fw_core_remove_card(struct fw_card *card) card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); - fw_core_initiate_bus_reset(card, 1); + fw_schedule_bus_reset(card, false, true); mutex_lock(&card_mutex); list_del_init(&card->link); @@ -588,12 +633,3 @@ void fw_core_remove_card(struct fw_card *card) WARN_ON(!list_empty(&card->transaction_list)); } EXPORT_SYMBOL(fw_core_remove_card); - -int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) -{ - int reg = short_reset ? 5 : 1; - int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; - - return card->driver->update_phy_reg(card, reg, 0, bit); -} -EXPORT_SYMBOL(fw_core_initiate_bus_reset); -- cgit v1.2.3 From 18d0cdfd1a4cc9028c0ef80f94538b31541f8fe5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 18 Jul 2010 12:44:01 +0200 Subject: firewire: normalize status values in packet callbacks core-transaction.c transmit_complete_callback() and close_transaction() expect packet callback status to be an ACK or RCODE, and ACKs get translated to RCODEs for transaction callbacks. An old comment on the packet callback API (been there from the initial submission of the stack) and the dummy_driver implementation of send_request/send_response deviated from this as they also included -ERRNO in the range of status values. Let's narrow status values down to ACK and RCODE to prevent surprises. RCODE_CANCELLED is chosen as the dummy_driver's RCODE as its meaning of "transaction timed out" comes closest to what happens when a transaction coincides with card removal. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 2bb5c036e806..0c312c4bb4bd 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -570,12 +570,12 @@ static int dummy_set_config_rom(struct fw_card *card, static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) { - packet->callback(packet, card, -ENODEV); + packet->callback(packet, card, RCODE_CANCELLED); } static void dummy_send_response(struct fw_card *card, struct fw_packet *packet) { - packet->callback(packet, card, -ENODEV); + packet->callback(packet, card, RCODE_CANCELLED); } static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) -- cgit v1.2.3 From bf54e1462b9192fdef7ea9e2bc44fdc16a4b87bc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 16 Jul 2010 22:25:51 +0200 Subject: firewire: cdev: add PHY packet reception Add an FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl() and FW_CDEV_EVENT_PHY_PACKET_RECEIVED poll()/read() event for /dev/fw*. This can be used to get information from remote PHYs by remote access PHY packets. This is also the 2nd half of the functionality (the receive part) to support a userspace implementation of a VersaPHY transaction layer. Safety considerations: - PHY packets are generally broadcasts, hence some kind of elevated privileges should be required of a process to be able to listen in on PHY packets. This implementation assumes that a process that is allowed to open the /dev/fw* of a local node does have this privilege. There was an inconclusive discussion about introducing POSIX capabilities as a means to check for user privileges for these kinds of operations. Other limitations: - PHY packet reception may be switched on by ioctl() but cannot be switched off again. It would be trivial to provide an off switch, but this is not worth the code. The client should simply close() the fd then, or just ignore further events. - For sake of simplicity of API and kernel-side implementation, no filter per packet content is provided. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 0c312c4bb4bd..6d1cfae6aad4 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -500,6 +500,7 @@ void fw_card_initialize(struct fw_card *card, kref_init(&card->kref); init_completion(&card->done); INIT_LIST_HEAD(&card->transaction_list); + INIT_LIST_HEAD(&card->phy_receiver_list); spin_lock_init(&card->lock); card->local_node = NULL; -- cgit v1.2.3 From 20802224298ce9dfd99a7e26b675fc0c8ae26cac Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 1 Aug 2010 12:23:14 +0200 Subject: firewire: core: add forgotten dummy driver methods, remove unused ones There is an at least theoretic race condition in which .start_iso etc. could still be called between when the dummy driver is bound to the card and when the children devices are being shut down. Add dummy_start_iso and friends. On the other hand, .enable, .set_config_rom, .read_csr, write_csr do not need to be implemented by the dummy driver, as commented. Signed-off-by: Stefan Richter --- drivers/firewire/core-card.c | 64 ++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'drivers/firewire/core-card.c') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 6d1cfae6aad4..417b8a4b1af1 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -538,15 +538,13 @@ EXPORT_SYMBOL(fw_card_add); * as all IO to the card will be handled (and failed) by the dummy driver * instead of calling into the module. Only functions for iso context * shutdown still need to be provided by the card driver. + * + * .read/write_csr() should never be called anymore after the dummy driver + * was bound since they are only used within request handler context. + * .set_config_rom() is never called since the card is taken out of card_list + * before switching to the dummy driver. */ -static int dummy_enable(struct fw_card *card, - const __be32 *config_rom, size_t length) -{ - BUG(); - return -1; -} - static int dummy_read_phy_reg(struct fw_card *card, int address) { return -ENODEV; @@ -558,17 +556,6 @@ static int dummy_update_phy_reg(struct fw_card *card, int address, return -ENODEV; } -static int dummy_set_config_rom(struct fw_card *card, - const __be32 *config_rom, size_t length) -{ - /* - * We take the card out of card_list before setting the dummy - * driver, so this should never get called. - */ - BUG(); - return -1; -} - static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) { packet->callback(packet, card, RCODE_CANCELLED); @@ -590,15 +577,40 @@ static int dummy_enable_phys_dma(struct fw_card *card, return -ENODEV; } +static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card, + int type, int channel, size_t header_size) +{ + return ERR_PTR(-ENODEV); +} + +static int dummy_start_iso(struct fw_iso_context *ctx, + s32 cycle, u32 sync, u32 tags) +{ + return -ENODEV; +} + +static int dummy_set_iso_channels(struct fw_iso_context *ctx, u64 *channels) +{ + return -ENODEV; +} + +static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p, + struct fw_iso_buffer *buffer, unsigned long payload) +{ + return -ENODEV; +} + static const struct fw_card_driver dummy_driver_template = { - .enable = dummy_enable, - .read_phy_reg = dummy_read_phy_reg, - .update_phy_reg = dummy_update_phy_reg, - .set_config_rom = dummy_set_config_rom, - .send_request = dummy_send_request, - .cancel_packet = dummy_cancel_packet, - .send_response = dummy_send_response, - .enable_phys_dma = dummy_enable_phys_dma, + .read_phy_reg = dummy_read_phy_reg, + .update_phy_reg = dummy_update_phy_reg, + .send_request = dummy_send_request, + .send_response = dummy_send_response, + .cancel_packet = dummy_cancel_packet, + .enable_phys_dma = dummy_enable_phys_dma, + .allocate_iso_context = dummy_allocate_iso_context, + .start_iso = dummy_start_iso, + .set_iso_channels = dummy_set_iso_channels, + .queue_iso = dummy_queue_iso, }; void fw_card_release(struct kref *kref) -- cgit v1.2.3