Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 198922
b: refs/heads/master
c: 5c40cbf
h: refs/heads/master
v: v3
  • Loading branch information
Clemens Ladisch authored and Stefan Richter committed May 18, 2010
1 parent 55a982c commit a90f549
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 47 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 753a8970f68594ea69c5fc13fbca18dbd9402996
refs/heads/master: 5c40cbfefa828208c671e2f58789e4dd04f79563
11 changes: 0 additions & 11 deletions trunk/drivers/firewire/core-card.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/workqueue.h>

#include <asm/atomic.h>
Expand Down Expand Up @@ -408,13 +407,6 @@ static void fw_card_bm_work(struct work_struct *work)
fw_card_put(card);
}

static void flush_timer_callback(unsigned long data)
{
struct fw_card *card = (struct fw_card *)data;

fw_flush_transactions(card);
}

void fw_card_initialize(struct fw_card *card,
const struct fw_card_driver *driver,
struct device *device)
Expand All @@ -433,8 +425,6 @@ void fw_card_initialize(struct fw_card *card,
init_completion(&card->done);
INIT_LIST_HEAD(&card->transaction_list);
spin_lock_init(&card->lock);
setup_timer(&card->flush_timer,
flush_timer_callback, (unsigned long)card);

card->local_node = NULL;

Expand Down Expand Up @@ -559,7 +549,6 @@ void fw_core_remove_card(struct fw_card *card)
wait_for_completion(&card->done);

WARN_ON(!list_empty(&card->transaction_list));
del_timer_sync(&card->flush_timer);
}
EXPORT_SYMBOL(fw_core_remove_card);

Expand Down
70 changes: 37 additions & 33 deletions trunk/drivers/firewire/core-transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,15 @@ static int close_transaction(struct fw_transaction *transaction,
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(t, &card->transaction_list, link) {
if (t == transaction) {
list_del(&t->link);
list_del_init(&t->link);
card->tlabel_mask &= ~(1ULL << t->tlabel);
break;
}
}
spin_unlock_irqrestore(&card->lock, flags);

if (&t->link != &card->transaction_list) {
del_timer_sync(&t->split_timeout_timer);
t->callback(card, rcode, NULL, 0, t->callback_data);
return 0;
}
Expand Down Expand Up @@ -121,6 +122,31 @@ int fw_cancel_transaction(struct fw_card *card,
}
EXPORT_SYMBOL(fw_cancel_transaction);

static void split_transaction_timeout_callback(unsigned long data)
{
struct fw_transaction *t = (struct fw_transaction *)data;
struct fw_card *card = t->card;
unsigned long flags;

spin_lock_irqsave(&card->lock, flags);
if (list_empty(&t->link)) {
spin_unlock_irqrestore(&card->lock, flags);
return;
}
list_del(&t->link);
card->tlabel_mask &= ~(1ULL << t->tlabel);
spin_unlock_irqrestore(&card->lock, flags);

card->driver->cancel_packet(card, &t->packet);

/*
* At this point cancel_packet will never call the transaction
* callback, since we just took the transaction out of the list.
* So do it here.
*/
t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
}

static void transmit_complete_callback(struct fw_packet *packet,
struct fw_card *card, int status)
{
Expand Down Expand Up @@ -293,13 +319,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
unsigned long flags;
int tlabel;

/*
* Bump the flush timer up 100ms first of all so we
* don't race with a flush timer callback.
*/

mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));

/*
* Allocate tlabel from the bitmap and put the transaction on
* the list while holding the card spinlock.
Expand All @@ -316,6 +335,11 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,

t->node_id = destination_id;
t->tlabel = tlabel;
t->card = card;
setup_timer(&t->split_timeout_timer,
split_transaction_timeout_callback, (unsigned long)t);
/* FIXME: start this timer later, relative to t->timestamp */
mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));
t->callback = callback;
t->callback_data = callback_data;

Expand Down Expand Up @@ -361,11 +385,13 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
struct transaction_callback_data d;
struct fw_transaction t;

init_timer_on_stack(&t.split_timeout_timer);
init_completion(&d.done);
d.payload = payload;
fw_send_request(card, &t, tcode, destination_id, generation, speed,
offset, payload, length, transaction_callback, &d);
wait_for_completion(&d.done);
destroy_timer_on_stack(&t.split_timeout_timer);

return d.rcode;
}
Expand Down Expand Up @@ -408,30 +434,6 @@ void fw_send_phy_config(struct fw_card *card,
mutex_unlock(&phy_config_mutex);
}

void fw_flush_transactions(struct fw_card *card)
{
struct fw_transaction *t, *next;
struct list_head list;
unsigned long flags;

INIT_LIST_HEAD(&list);
spin_lock_irqsave(&card->lock, flags);
list_splice_init(&card->transaction_list, &list);
card->tlabel_mask = 0;
spin_unlock_irqrestore(&card->lock, flags);

list_for_each_entry_safe(t, next, &list, link) {
card->driver->cancel_packet(card, &t->packet);

/*
* At this point cancel_packet will never call the
* transaction callback, since we just took all the
* transactions out of the list. So do it here.
*/
t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
}
}

static struct fw_address_handler *lookup_overlapping_address_handler(
struct list_head *list, unsigned long long offset, size_t length)
{
Expand Down Expand Up @@ -841,7 +843,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry(t, &card->transaction_list, link) {
if (t->node_id == source && t->tlabel == tlabel) {
list_del(&t->link);
list_del_init(&t->link);
card->tlabel_mask &= ~(1ULL << t->tlabel);
break;
}
Expand Down Expand Up @@ -883,6 +885,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
break;
}

del_timer_sync(&t->split_timeout_timer);

/*
* The response handler may be executed while the request handler
* is still pending. Cancel the request handler.
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/firewire/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
void fw_fill_response(struct fw_packet *response, u32 *request_header,
int rcode, void *payload, size_t length);
void fw_flush_transactions(struct fw_card *card);
void fw_send_phy_config(struct fw_card *card,
int node_id, int generation, int gap_count);

Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/firewire.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ struct fw_card {
int current_tlabel;
u64 tlabel_mask;
struct list_head transaction_list;
struct timer_list flush_timer;
unsigned long reset_jiffies;

unsigned long long guid;
Expand Down Expand Up @@ -288,6 +287,8 @@ struct fw_transaction {
int tlabel;
int timestamp;
struct list_head link;
struct fw_card *card;
struct timer_list split_timeout_timer;

struct fw_packet packet;

Expand Down

0 comments on commit a90f549

Please sign in to comment.