diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 68 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 3 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 18 | ||||
-rw-r--r-- | drivers/firewire/core.h | 6 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 53 |
5 files changed, 112 insertions, 36 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 | } |
205 | EXPORT_SYMBOL(fw_core_remove_descriptor); | 205 | EXPORT_SYMBOL(fw_core_remove_descriptor); |
206 | 206 | ||
207 | static 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 | |||
215 | void 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 | } | ||
226 | EXPORT_SYMBOL(fw_schedule_bus_reset); | ||
227 | |||
228 | static 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 | |||
207 | static void allocate_broadcast_channel(struct fw_card *card, int generation) | 246 | static 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[] = { | |||
230 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | 269 | void 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 | ||
237 | static void fw_card_bm_work(struct work_struct *work) | 276 | static 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 | } |
470 | EXPORT_SYMBOL(fw_card_initialize); | 510 | EXPORT_SYMBOL(fw_card_initialize); |
471 | 511 | ||
@@ -491,7 +531,6 @@ int fw_card_add(struct fw_card *card, | |||
491 | } | 531 | } |
492 | EXPORT_SYMBOL(fw_card_add); | 532 | EXPORT_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 | ||
549 | static int dummy_read_phy_reg(struct fw_card *card, int address) | ||
550 | { | ||
551 | return -ENODEV; | ||
552 | } | ||
553 | |||
510 | static int dummy_update_phy_reg(struct fw_card *card, int address, | 554 | static 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 | ||
548 | static const struct fw_card_driver dummy_driver_template = { | 592 | static 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 | } |
590 | EXPORT_SYMBOL(fw_core_remove_card); | 635 | EXPORT_SYMBOL(fw_core_remove_card); |
591 | |||
592 | int 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 | } | ||
599 | EXPORT_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 | ||
821 | static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg) | 821 | static 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 | ||
827 | static void release_descriptor(struct client *client, | 828 | static 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, | |||
102 | int fw_card_add(struct fw_card *card, | 103 | int 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); |
104 | void fw_core_remove_card(struct fw_card *card); | 105 | void fw_core_remove_card(struct fw_card *card); |
105 | int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); | ||
106 | int fw_compute_block_crc(__be32 *block); | 106 | int fw_compute_block_crc(__be32 *block); |
107 | void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset); | ||
107 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); | 108 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); |
108 | 109 | ||
109 | static inline struct fw_card *fw_card_get(struct fw_card *card) | 110 | static 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); | |||
225 | int fw_get_response_length(struct fw_request *request); | 226 | int fw_get_response_length(struct fw_request *request); |
226 | void fw_fill_response(struct fw_packet *response, u32 *request_header, | 227 | void 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 | ||
228 | void fw_send_phy_config(struct fw_card *card, | 232 | void 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 | ||
520 | static int ohci_update_phy_reg(struct fw_card *card, int addr, | 523 | static 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 | ||
551 | static 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 | |||
563 | static 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 | |||
551 | static int ar_context_add_page(struct ar_context *ctx) | 576 | static 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 | ||
2571 | static const struct fw_card_driver ohci_driver = { | 2592 | static 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); |