|
@@ -72,6 +72,15 @@
|
|
|
#define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23))
|
|
|
#define PHY_IDENTIFIER(id) ((id) << 30)
|
|
|
|
|
|
+/* returns 0 if the split timeout handler is already running */
|
|
|
+static int try_cancel_split_timeout(struct fw_transaction *t)
|
|
|
+{
|
|
|
+ if (t->is_split_transaction)
|
|
|
+ return del_timer(&t->split_timeout_timer);
|
|
|
+ else
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static int close_transaction(struct fw_transaction *transaction,
|
|
|
struct fw_card *card, int rcode)
|
|
|
{
|
|
@@ -81,7 +90,7 @@ 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) {
|
|
|
- if (!del_timer(&t->split_timeout_timer)) {
|
|
|
+ if (!try_cancel_split_timeout(t)) {
|
|
|
spin_unlock_irqrestore(&card->lock, flags);
|
|
|
goto timed_out;
|
|
|
}
|
|
@@ -141,16 +150,28 @@ static void split_transaction_timeout_callback(unsigned long data)
|
|
|
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 start_split_transaction_timeout(struct fw_transaction *t,
|
|
|
+ struct fw_card *card)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&card->lock, flags);
|
|
|
+
|
|
|
+ if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) {
|
|
|
+ spin_unlock_irqrestore(&card->lock, flags);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ t->is_split_transaction = true;
|
|
|
+ mod_timer(&t->split_timeout_timer,
|
|
|
+ jiffies + card->split_timeout_jiffies);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&card->lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
static void transmit_complete_callback(struct fw_packet *packet,
|
|
|
struct fw_card *card, int status)
|
|
|
{
|
|
@@ -162,7 +183,7 @@ static void transmit_complete_callback(struct fw_packet *packet,
|
|
|
close_transaction(t, card, RCODE_COMPLETE);
|
|
|
break;
|
|
|
case ACK_PENDING:
|
|
|
- t->timestamp = packet->timestamp;
|
|
|
+ start_split_transaction_timeout(t, card);
|
|
|
break;
|
|
|
case ACK_BUSY_X:
|
|
|
case ACK_BUSY_A:
|
|
@@ -250,7 +271,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
- WARN(1, "wrong tcode %d", tcode);
|
|
|
+ WARN(1, "wrong tcode %d\n", tcode);
|
|
|
}
|
|
|
common:
|
|
|
packet->speed = speed;
|
|
@@ -349,11 +370,9 @@ 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;
|
|
|
+ t->is_split_transaction = false;
|
|
|
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 + card->split_timeout_jiffies);
|
|
|
t->callback = callback;
|
|
|
t->callback_data = callback_data;
|
|
|
|
|
@@ -423,7 +442,8 @@ static void transmit_phy_packet_callback(struct fw_packet *packet,
|
|
|
}
|
|
|
|
|
|
static struct fw_packet phy_config_packet = {
|
|
|
- .header_length = 8,
|
|
|
+ .header_length = 12,
|
|
|
+ .header[0] = TCODE_LINK_INTERNAL << 4,
|
|
|
.payload_length = 0,
|
|
|
.speed = SCODE_100,
|
|
|
.callback = transmit_phy_packet_callback,
|
|
@@ -451,8 +471,8 @@ void fw_send_phy_config(struct fw_card *card,
|
|
|
|
|
|
mutex_lock(&phy_config_mutex);
|
|
|
|
|
|
- phy_config_packet.header[0] = data;
|
|
|
- phy_config_packet.header[1] = ~data;
|
|
|
+ phy_config_packet.header[1] = data;
|
|
|
+ phy_config_packet.header[2] = ~data;
|
|
|
phy_config_packet.generation = generation;
|
|
|
INIT_COMPLETION(phy_config_done);
|
|
|
|
|
@@ -638,7 +658,7 @@ int fw_get_response_length(struct fw_request *r)
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
- WARN(1, "wrong tcode %d", tcode);
|
|
|
+ WARN(1, "wrong tcode %d\n", tcode);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
@@ -694,7 +714,7 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
- WARN(1, "wrong tcode %d", tcode);
|
|
|
+ WARN(1, "wrong tcode %d\n", tcode);
|
|
|
}
|
|
|
|
|
|
response->payload_mapped = false;
|
|
@@ -925,7 +945,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) {
|
|
|
- if (!del_timer(&t->split_timeout_timer)) {
|
|
|
+ if (!try_cancel_split_timeout(t)) {
|
|
|
spin_unlock_irqrestore(&card->lock, flags);
|
|
|
goto timed_out;
|
|
|
}
|