aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-07-08 10:09:06 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-07-13 03:58:27 -0400
commit02d37bed188c500ee7afb0a2dc6b65a80704c58e (patch)
treea019891672a1505e35eb15fa2621caffecff2c80
parent8b4f70ba4967cae90d128857af1382026a24230a (diff)
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 <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/core-card.c68
-rw-r--r--drivers/firewire/core-cdev.c3
-rw-r--r--drivers/firewire/core-transaction.c18
-rw-r--r--drivers/firewire/core.h6
-rw-r--r--drivers/firewire/ohci.c53
-rw-r--r--include/linux/firewire.h6
6 files changed, 116 insertions, 38 deletions
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)
204} 204}
205EXPORT_SYMBOL(fw_core_remove_descriptor); 205EXPORT_SYMBOL(fw_core_remove_descriptor);
206 206
207static int reset_bus(struct fw_card *card, bool short_reset)
208{
209 int reg = short_reset ? 5 : 1;
210 int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
211
212 return card->driver->update_phy_reg(card, reg, 0, bit);
213}
214
215void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)
216{
217 /* We don't try hard to sort out requests of long vs. short resets. */
218 card->br_short = short_reset;
219
220 /* Use an arbitrary short delay to combine multiple reset requests. */
221 fw_card_get(card);
222 if (!schedule_delayed_work(&card->br_work,
223 delayed ? DIV_ROUND_UP(HZ, 100) : 0))
224 fw_card_put(card);
225}
226EXPORT_SYMBOL(fw_schedule_bus_reset);
227
228static void br_work(struct work_struct *work)
229{
230 struct fw_card *card = container_of(work, struct fw_card, br_work.work);
231
232 /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
233 if (card->reset_jiffies != 0 &&
234 time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {
235 if (!schedule_delayed_work(&card->br_work, 2 * HZ))
236 fw_card_put(card);
237 return;
238 }
239
240 fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation,
241 FW_PHY_CONFIG_CURRENT_GAP_COUNT);
242 reset_bus(card, card->br_short);
243 fw_card_put(card);
244}
245
207static void allocate_broadcast_channel(struct fw_card *card, int generation) 246static void allocate_broadcast_channel(struct fw_card *card, int generation)
208{ 247{
209 int channel, bandwidth = 0; 248 int channel, bandwidth = 0;
@@ -230,13 +269,13 @@ static const char gap_count_table[] = {
230void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) 269void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
231{ 270{
232 fw_card_get(card); 271 fw_card_get(card);
233 if (!schedule_delayed_work(&card->work, delay)) 272 if (!schedule_delayed_work(&card->bm_work, delay))
234 fw_card_put(card); 273 fw_card_put(card);
235} 274}
236 275
237static void fw_card_bm_work(struct work_struct *work) 276static void bm_work(struct work_struct *work)
238{ 277{
239 struct fw_card *card = container_of(work, struct fw_card, work.work); 278 struct fw_card *card = container_of(work, struct fw_card, bm_work.work);
240 struct fw_device *root_device; 279 struct fw_device *root_device;
241 struct fw_node *root_node; 280 struct fw_node *root_node;
242 int root_id, new_root_id, irm_id, bm_id, local_id; 281 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)
413 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", 452 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",
414 card->index, new_root_id, gap_count); 453 card->index, new_root_id, gap_count);
415 fw_send_phy_config(card, new_root_id, generation, gap_count); 454 fw_send_phy_config(card, new_root_id, generation, gap_count);
416 fw_core_initiate_bus_reset(card, 1); 455 reset_bus(card, true);
417 /* Will allocate broadcast channel after the reset. */ 456 /* Will allocate broadcast channel after the reset. */
418 goto out; 457 goto out;
419 } 458 }
@@ -465,7 +504,8 @@ void fw_card_initialize(struct fw_card *card,
465 504
466 card->local_node = NULL; 505 card->local_node = NULL;
467 506
468 INIT_DELAYED_WORK(&card->work, fw_card_bm_work); 507 INIT_DELAYED_WORK(&card->br_work, br_work);
508 INIT_DELAYED_WORK(&card->bm_work, bm_work);
469} 509}
470EXPORT_SYMBOL(fw_card_initialize); 510EXPORT_SYMBOL(fw_card_initialize);
471 511
@@ -491,7 +531,6 @@ int fw_card_add(struct fw_card *card,
491} 531}
492EXPORT_SYMBOL(fw_card_add); 532EXPORT_SYMBOL(fw_card_add);
493 533
494
495/* 534/*
496 * The next few functions implement a dummy driver that is used once a card 535 * The next few functions implement a dummy driver that is used once a card
497 * driver shuts down an fw_card. This allows the driver to cleanly unload, 536 * 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,
507 return -1; 546 return -1;
508} 547}
509 548
549static int dummy_read_phy_reg(struct fw_card *card, int address)
550{
551 return -ENODEV;
552}
553
510static int dummy_update_phy_reg(struct fw_card *card, int address, 554static int dummy_update_phy_reg(struct fw_card *card, int address,
511 int clear_bits, int set_bits) 555 int clear_bits, int set_bits)
512{ 556{
@@ -547,6 +591,7 @@ static int dummy_enable_phys_dma(struct fw_card *card,
547 591
548static const struct fw_card_driver dummy_driver_template = { 592static const struct fw_card_driver dummy_driver_template = {
549 .enable = dummy_enable, 593 .enable = dummy_enable,
594 .read_phy_reg = dummy_read_phy_reg,
550 .update_phy_reg = dummy_update_phy_reg, 595 .update_phy_reg = dummy_update_phy_reg,
551 .set_config_rom = dummy_set_config_rom, 596 .set_config_rom = dummy_set_config_rom,
552 .send_request = dummy_send_request, 597 .send_request = dummy_send_request,
@@ -568,7 +613,7 @@ void fw_core_remove_card(struct fw_card *card)
568 613
569 card->driver->update_phy_reg(card, 4, 614 card->driver->update_phy_reg(card, 4,
570 PHY_LINK_ACTIVE | PHY_CONTENDER, 0); 615 PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
571 fw_core_initiate_bus_reset(card, 1); 616 fw_schedule_bus_reset(card, false, true);
572 617
573 mutex_lock(&card_mutex); 618 mutex_lock(&card_mutex);
574 list_del_init(&card->link); 619 list_del_init(&card->link);
@@ -588,12 +633,3 @@ void fw_core_remove_card(struct fw_card *card)
588 WARN_ON(!list_empty(&card->transaction_list)); 633 WARN_ON(!list_empty(&card->transaction_list));
589} 634}
590EXPORT_SYMBOL(fw_core_remove_card); 635EXPORT_SYMBOL(fw_core_remove_card);
591
592int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
593{
594 int reg = short_reset ? 5 : 1;
595 int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
596
597 return card->driver->update_phy_reg(card, reg, 0, bit);
598}
599EXPORT_SYMBOL(fw_core_initiate_bus_reset);
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 7a690c466ce9..ee2e87353102 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -820,8 +820,9 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
820 820
821static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg) 821static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)
822{ 822{
823 return fw_core_initiate_bus_reset(client->device->card, 823 fw_schedule_bus_reset(client->device->card, true,
824 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET); 824 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);
825 return 0;
825} 826}
826 827
827static void release_descriptor(struct client *client, 828static void release_descriptor(struct client *client,
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 7813da8a1293..5f5a7852f7ac 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -426,9 +426,21 @@ void fw_send_phy_config(struct fw_card *card,
426 int node_id, int generation, int gap_count) 426 int node_id, int generation, int gap_count)
427{ 427{
428 long timeout = DIV_ROUND_UP(HZ, 10); 428 long timeout = DIV_ROUND_UP(HZ, 10);
429 u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) | 429 u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG);
430 PHY_CONFIG_ROOT_ID(node_id) | 430
431 PHY_CONFIG_GAP_COUNT(gap_count); 431 if (node_id != FW_PHY_CONFIG_NO_NODE_ID)
432 data |= PHY_CONFIG_ROOT_ID(node_id);
433
434 if (gap_count == FW_PHY_CONFIG_CURRENT_GAP_COUNT) {
435 gap_count = card->driver->read_phy_reg(card, 1);
436 if (gap_count < 0)
437 return;
438
439 gap_count &= 63;
440 if (gap_count == 63)
441 return;
442 }
443 data |= PHY_CONFIG_GAP_COUNT(gap_count);
432 444
433 mutex_lock(&phy_config_mutex); 445 mutex_lock(&phy_config_mutex);
434 446
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 3000dd74acfd..ff6c90922001 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -51,6 +51,7 @@ struct fw_card_driver {
51 int (*enable)(struct fw_card *card, 51 int (*enable)(struct fw_card *card,
52 const __be32 *config_rom, size_t length); 52 const __be32 *config_rom, size_t length);
53 53
54 int (*read_phy_reg)(struct fw_card *card, int address);
54 int (*update_phy_reg)(struct fw_card *card, int address, 55 int (*update_phy_reg)(struct fw_card *card, int address,
55 int clear_bits, int set_bits); 56 int clear_bits, int set_bits);
56 57
@@ -102,8 +103,8 @@ void fw_card_initialize(struct fw_card *card,
102int fw_card_add(struct fw_card *card, 103int fw_card_add(struct fw_card *card,
103 u32 max_receive, u32 link_speed, u64 guid); 104 u32 max_receive, u32 link_speed, u64 guid);
104void fw_core_remove_card(struct fw_card *card); 105void fw_core_remove_card(struct fw_card *card);
105int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
106int fw_compute_block_crc(__be32 *block); 106int fw_compute_block_crc(__be32 *block);
107void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset);
107void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); 108void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
108 109
109static inline struct fw_card *fw_card_get(struct fw_card *card) 110static inline struct fw_card *fw_card_get(struct fw_card *card)
@@ -225,6 +226,9 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
225int fw_get_response_length(struct fw_request *request); 226int fw_get_response_length(struct fw_request *request);
226void fw_fill_response(struct fw_packet *response, u32 *request_header, 227void fw_fill_response(struct fw_packet *response, u32 *request_header,
227 int rcode, void *payload, size_t length); 228 int rcode, void *payload, size_t length);
229
230#define FW_PHY_CONFIG_NO_NODE_ID -1
231#define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1
228void fw_send_phy_config(struct fw_card *card, 232void fw_send_phy_config(struct fw_card *card,
229 int node_id, int generation, int gap_count); 233 int node_id, int generation, int gap_count);
230 234
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index a4bbf3dadf58..bb6a92bc9e6a 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -34,6 +34,7 @@
34#include <linux/mm.h> 34#include <linux/mm.h>
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/moduleparam.h> 36#include <linux/moduleparam.h>
37#include <linux/mutex.h>
37#include <linux/pci.h> 38#include <linux/pci.h>
38#include <linux/pci_ids.h> 39#include <linux/pci_ids.h>
39#include <linux/spinlock.h> 40#include <linux/spinlock.h>
@@ -182,6 +183,8 @@ struct fw_ohci {
182 */ 183 */
183 spinlock_t lock; 184 spinlock_t lock;
184 185
186 struct mutex phy_reg_mutex;
187
185 struct ar_context ar_request_ctx; 188 struct ar_context ar_request_ctx;
186 struct ar_context ar_response_ctx; 189 struct ar_context ar_response_ctx;
187 struct context at_request_ctx; 190 struct context at_request_ctx;
@@ -517,13 +520,10 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
517 return -EBUSY; 520 return -EBUSY;
518} 521}
519 522
520static int ohci_update_phy_reg(struct fw_card *card, int addr, 523static int update_phy_reg(struct fw_ohci *ohci, int addr,
521 int clear_bits, int set_bits) 524 int clear_bits, int set_bits)
522{ 525{
523 struct fw_ohci *ohci = fw_ohci(card); 526 int ret = read_phy_reg(ohci, addr);
524 int ret;
525
526 ret = read_phy_reg(ohci, addr);
527 if (ret < 0) 527 if (ret < 0)
528 return ret; 528 return ret;
529 529
@@ -541,13 +541,38 @@ static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr)
541{ 541{
542 int ret; 542 int ret;
543 543
544 ret = ohci_update_phy_reg(&ohci->card, 7, PHY_PAGE_SELECT, page << 5); 544 ret = update_phy_reg(ohci, 7, PHY_PAGE_SELECT, page << 5);
545 if (ret < 0) 545 if (ret < 0)
546 return ret; 546 return ret;
547 547
548 return read_phy_reg(ohci, addr); 548 return read_phy_reg(ohci, addr);
549} 549}
550 550
551static int ohci_read_phy_reg(struct fw_card *card, int addr)
552{
553 struct fw_ohci *ohci = fw_ohci(card);
554 int ret;
555
556 mutex_lock(&ohci->phy_reg_mutex);
557 ret = read_phy_reg(ohci, addr);
558 mutex_unlock(&ohci->phy_reg_mutex);
559
560 return ret;
561}
562
563static int ohci_update_phy_reg(struct fw_card *card, int addr,
564 int clear_bits, int set_bits)
565{
566 struct fw_ohci *ohci = fw_ohci(card);
567 int ret;
568
569 mutex_lock(&ohci->phy_reg_mutex);
570 ret = update_phy_reg(ohci, addr, clear_bits, set_bits);
571 mutex_unlock(&ohci->phy_reg_mutex);
572
573 return ret;
574}
575
551static int ar_context_add_page(struct ar_context *ctx) 576static int ar_context_add_page(struct ar_context *ctx)
552{ 577{
553 struct device *dev = ctx->ohci->card.device; 578 struct device *dev = ctx->ohci->card.device;
@@ -1676,7 +1701,7 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
1676 clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; 1701 clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
1677 set = 0; 1702 set = 0;
1678 } 1703 }
1679 ret = ohci_update_phy_reg(&ohci->card, 5, clear, set); 1704 ret = update_phy_reg(ohci, 5, clear, set);
1680 if (ret < 0) 1705 if (ret < 0)
1681 return ret; 1706 return ret;
1682 1707
@@ -1856,12 +1881,8 @@ static int ohci_enable(struct fw_card *card,
1856 OHCI1394_HCControl_BIBimageValid); 1881 OHCI1394_HCControl_BIBimageValid);
1857 flush_writes(ohci); 1882 flush_writes(ohci);
1858 1883
1859 /* 1884 /* We are ready to go, reset bus to finish initialization. */
1860 * We are ready to go, initiate bus reset to finish the 1885 fw_schedule_bus_reset(&ohci->card, false, true);
1861 * initialization.
1862 */
1863
1864 fw_core_initiate_bus_reset(&ohci->card, 1);
1865 1886
1866 return 0; 1887 return 0;
1867} 1888}
@@ -1936,7 +1957,7 @@ static int ohci_set_config_rom(struct fw_card *card,
1936 * takes effect. 1957 * takes effect.
1937 */ 1958 */
1938 if (ret == 0) 1959 if (ret == 0)
1939 fw_core_initiate_bus_reset(&ohci->card, 1); 1960 fw_schedule_bus_reset(&ohci->card, true, true);
1940 else 1961 else
1941 dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, 1962 dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
1942 next_config_rom, next_config_rom_bus); 1963 next_config_rom, next_config_rom_bus);
@@ -2570,6 +2591,7 @@ static int ohci_queue_iso(struct fw_iso_context *base,
2570 2591
2571static const struct fw_card_driver ohci_driver = { 2592static const struct fw_card_driver ohci_driver = {
2572 .enable = ohci_enable, 2593 .enable = ohci_enable,
2594 .read_phy_reg = ohci_read_phy_reg,
2573 .update_phy_reg = ohci_update_phy_reg, 2595 .update_phy_reg = ohci_update_phy_reg,
2574 .set_config_rom = ohci_set_config_rom, 2596 .set_config_rom = ohci_set_config_rom,
2575 .send_request = ohci_send_request, 2597 .send_request = ohci_send_request,
@@ -2645,6 +2667,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
2645 pci_set_drvdata(dev, ohci); 2667 pci_set_drvdata(dev, ohci);
2646 2668
2647 spin_lock_init(&ohci->lock); 2669 spin_lock_init(&ohci->lock);
2670 mutex_init(&ohci->phy_reg_mutex);
2648 2671
2649 tasklet_init(&ohci->bus_reset_tasklet, 2672 tasklet_init(&ohci->bus_reset_tasklet,
2650 bus_reset_tasklet, (unsigned long)ohci); 2673 bus_reset_tasklet, (unsigned long)ohci);
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index db30a752a87a..adc5b55e6e5f 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -114,8 +114,10 @@ struct fw_card {
114 114
115 struct list_head link; 115 struct list_head link;
116 116
117 /* Work struct for BM duties. */ 117 struct delayed_work br_work; /* bus reset job */
118 struct delayed_work work; 118 bool br_short;
119
120 struct delayed_work bm_work; /* bus manager job */
119 int bm_retries; 121 int bm_retries;
120 int bm_generation; 122 int bm_generation;
121 __be32 bm_transaction_data[2]; 123 __be32 bm_transaction_data[2];