Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: firewire: ohci: work around VIA and NEC PHY packet reception bug firewire: core: do not use del_timer_sync() in interrupt context firewire: net: fix unicast reception RCODE in failure paths firewire: sbp2: fix stall with "Unsolicited response" firewire: sbp2: fix memory leak in sbp2_cancel_orbs or at send error ieee1394: Adjust confusing if indentation
This commit is contained in:
@@ -81,6 +81,10 @@ static int close_transaction(struct fw_transaction *transaction,
|
|||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
list_for_each_entry(t, &card->transaction_list, link) {
|
list_for_each_entry(t, &card->transaction_list, link) {
|
||||||
if (t == transaction) {
|
if (t == transaction) {
|
||||||
|
if (!del_timer(&t->split_timeout_timer)) {
|
||||||
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
goto timed_out;
|
||||||
|
}
|
||||||
list_del_init(&t->link);
|
list_del_init(&t->link);
|
||||||
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
||||||
break;
|
break;
|
||||||
@@ -89,11 +93,11 @@ static int close_transaction(struct fw_transaction *transaction,
|
|||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
|
||||||
if (&t->link != &card->transaction_list) {
|
if (&t->link != &card->transaction_list) {
|
||||||
del_timer_sync(&t->split_timeout_timer);
|
|
||||||
t->callback(card, rcode, NULL, 0, t->callback_data);
|
t->callback(card, rcode, NULL, 0, t->callback_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timed_out:
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,6 +925,10 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
|
|||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
list_for_each_entry(t, &card->transaction_list, link) {
|
list_for_each_entry(t, &card->transaction_list, link) {
|
||||||
if (t->node_id == source && t->tlabel == tlabel) {
|
if (t->node_id == source && t->tlabel == tlabel) {
|
||||||
|
if (!del_timer(&t->split_timeout_timer)) {
|
||||||
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
goto timed_out;
|
||||||
|
}
|
||||||
list_del_init(&t->link);
|
list_del_init(&t->link);
|
||||||
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
||||||
break;
|
break;
|
||||||
@@ -929,6 +937,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
|
|||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
|
||||||
if (&t->link == &card->transaction_list) {
|
if (&t->link == &card->transaction_list) {
|
||||||
|
timed_out:
|
||||||
fw_notify("Unsolicited response (source %x, tlabel %x)\n",
|
fw_notify("Unsolicited response (source %x, tlabel %x)\n",
|
||||||
source, tlabel);
|
source, tlabel);
|
||||||
return;
|
return;
|
||||||
@@ -963,8 +972,6 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&t->split_timeout_timer);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The response handler may be executed while the request handler
|
* The response handler may be executed while the request handler
|
||||||
* is still pending. Cancel the request handler.
|
* is still pending. Cancel the request handler.
|
||||||
|
@@ -579,7 +579,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||||||
if (!peer) {
|
if (!peer) {
|
||||||
fw_notify("No peer for ARP packet from %016llx\n",
|
fw_notify("No peer for ARP packet from %016llx\n",
|
||||||
(unsigned long long)peer_guid);
|
(unsigned long long)peer_guid);
|
||||||
goto failed_proto;
|
goto no_peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -656,7 +656,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_proto:
|
no_peer:
|
||||||
net->stats.rx_errors++;
|
net->stats.rx_errors++;
|
||||||
net->stats.rx_dropped++;
|
net->stats.rx_dropped++;
|
||||||
|
|
||||||
@@ -664,7 +664,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||||||
if (netif_queue_stopped(net))
|
if (netif_queue_stopped(net))
|
||||||
netif_wake_queue(net);
|
netif_wake_queue(net);
|
||||||
|
|
||||||
return 0;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
||||||
@@ -701,7 +701,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
fw_error("out of memory\n");
|
fw_error("out of memory\n");
|
||||||
net->stats.rx_dropped++;
|
net->stats.rx_dropped++;
|
||||||
|
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
skb_reserve(skb, (net->hard_header_len + 15) & ~15);
|
skb_reserve(skb, (net->hard_header_len + 15) & ~15);
|
||||||
memcpy(skb_put(skb, len), buf, len);
|
memcpy(skb_put(skb, len), buf, len);
|
||||||
@@ -726,8 +726,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
|
|
||||||
peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
|
peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
|
||||||
if (!peer)
|
if (!peer) {
|
||||||
goto bad_proto;
|
retval = -ENOENT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
pd = fwnet_pd_find(peer, datagram_label);
|
pd = fwnet_pd_find(peer, datagram_label);
|
||||||
if (pd == NULL) {
|
if (pd == NULL) {
|
||||||
@@ -741,7 +743,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
dg_size, buf, fg_off, len);
|
dg_size, buf, fg_off, len);
|
||||||
if (pd == NULL) {
|
if (pd == NULL) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto bad_proto;
|
goto fail;
|
||||||
}
|
}
|
||||||
peer->pdg_size++;
|
peer->pdg_size++;
|
||||||
} else {
|
} else {
|
||||||
@@ -755,9 +757,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
pd = fwnet_pd_new(net, peer, datagram_label,
|
pd = fwnet_pd_new(net, peer, datagram_label,
|
||||||
dg_size, buf, fg_off, len);
|
dg_size, buf, fg_off, len);
|
||||||
if (pd == NULL) {
|
if (pd == NULL) {
|
||||||
retval = -ENOMEM;
|
|
||||||
peer->pdg_size--;
|
peer->pdg_size--;
|
||||||
goto bad_proto;
|
retval = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
|
if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
|
||||||
@@ -768,7 +770,8 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
*/
|
*/
|
||||||
fwnet_pd_delete(pd);
|
fwnet_pd_delete(pd);
|
||||||
peer->pdg_size--;
|
peer->pdg_size--;
|
||||||
goto bad_proto;
|
retval = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* new datagram or add to existing one */
|
} /* new datagram or add to existing one */
|
||||||
@@ -794,14 +797,13 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
fail:
|
||||||
bad_proto:
|
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
|
|
||||||
if (netif_queue_stopped(net))
|
if (netif_queue_stopped(net))
|
||||||
netif_wake_queue(net);
|
netif_wake_queue(net);
|
||||||
|
|
||||||
return 0;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
|
static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
|
||||||
|
@@ -694,7 +694,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
|||||||
log_ar_at_event('R', p.speed, p.header, evt);
|
log_ar_at_event('R', p.speed, p.header, evt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The OHCI bus reset handler synthesizes a phy packet with
|
* Several controllers, notably from NEC and VIA, forget to
|
||||||
|
* write ack_complete status at PHY packet reception.
|
||||||
|
*/
|
||||||
|
if (evt == OHCI1394_evt_no_status &&
|
||||||
|
(p.header[0] & 0xff) == (OHCI1394_phy_tcode << 4))
|
||||||
|
p.ack = ACK_COMPLETE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The OHCI bus reset handler synthesizes a PHY packet with
|
||||||
* the new generation number when a bus reset happens (see
|
* the new generation number when a bus reset happens (see
|
||||||
* section 8.4.2.3). This helps us determine when a request
|
* section 8.4.2.3). This helps us determine when a request
|
||||||
* was received and make sure we send the response in the same
|
* was received and make sure we send the response in the same
|
||||||
|
@@ -450,7 +450,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
|
|||||||
|
|
||||||
if (&orb->link != &lu->orb_list) {
|
if (&orb->link != &lu->orb_list) {
|
||||||
orb->callback(orb, &status);
|
orb->callback(orb, &status);
|
||||||
kref_put(&orb->kref, free_orb);
|
kref_put(&orb->kref, free_orb); /* orb callback reference */
|
||||||
} else {
|
} else {
|
||||||
fw_error("status write for unknown orb\n");
|
fw_error("status write for unknown orb\n");
|
||||||
}
|
}
|
||||||
@@ -472,20 +472,28 @@ static void complete_transaction(struct fw_card *card, int rcode,
|
|||||||
* So this callback only sets the rcode if it hasn't already
|
* So this callback only sets the rcode if it hasn't already
|
||||||
* been set and only does the cleanup if the transaction
|
* been set and only does the cleanup if the transaction
|
||||||
* failed and we didn't already get a status write.
|
* failed and we didn't already get a status write.
|
||||||
|
*
|
||||||
|
* Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
|
||||||
|
* OXUF936QSE firmwares occasionally respond after Split_Timeout and
|
||||||
|
* complete the ORB just fine. Note, we also get RCODE_CANCELLED
|
||||||
|
* from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
|
|
||||||
if (orb->rcode == -1)
|
if (orb->rcode == -1)
|
||||||
orb->rcode = rcode;
|
orb->rcode = rcode;
|
||||||
if (orb->rcode != RCODE_COMPLETE) {
|
|
||||||
|
if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
|
||||||
list_del(&orb->link);
|
list_del(&orb->link);
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
|
||||||
orb->callback(orb, NULL);
|
orb->callback(orb, NULL);
|
||||||
|
kref_put(&orb->kref, free_orb); /* orb callback reference */
|
||||||
} else {
|
} else {
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
kref_put(&orb->kref, free_orb);
|
kref_put(&orb->kref, free_orb); /* transaction callback reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
|
static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
|
||||||
@@ -501,9 +509,8 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
|
|||||||
list_add_tail(&orb->link, &lu->orb_list);
|
list_add_tail(&orb->link, &lu->orb_list);
|
||||||
spin_unlock_irqrestore(&device->card->lock, flags);
|
spin_unlock_irqrestore(&device->card->lock, flags);
|
||||||
|
|
||||||
/* Take a ref for the orb list and for the transaction callback. */
|
kref_get(&orb->kref); /* transaction callback reference */
|
||||||
kref_get(&orb->kref);
|
kref_get(&orb->kref); /* orb callback reference */
|
||||||
kref_get(&orb->kref);
|
|
||||||
|
|
||||||
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
|
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
|
||||||
node_id, generation, device->max_speed, offset,
|
node_id, generation, device->max_speed, offset,
|
||||||
@@ -525,11 +532,11 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
|
|||||||
|
|
||||||
list_for_each_entry_safe(orb, next, &list, link) {
|
list_for_each_entry_safe(orb, next, &list, link) {
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if (fw_cancel_transaction(device->card, &orb->t) == 0)
|
fw_cancel_transaction(device->card, &orb->t);
|
||||||
continue;
|
|
||||||
|
|
||||||
orb->rcode = RCODE_CANCELLED;
|
orb->rcode = RCODE_CANCELLED;
|
||||||
orb->callback(orb, NULL);
|
orb->callback(orb, NULL);
|
||||||
|
kref_put(&orb->kref, free_orb); /* orb callback reference */
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@@ -1106,7 +1106,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
|
|||||||
if (recv->block_irq_interval * 4 > iso->buf_packets)
|
if (recv->block_irq_interval * 4 > iso->buf_packets)
|
||||||
recv->block_irq_interval = iso->buf_packets / 4;
|
recv->block_irq_interval = iso->buf_packets / 4;
|
||||||
if (recv->block_irq_interval < 1)
|
if (recv->block_irq_interval < 1)
|
||||||
recv->block_irq_interval = 1;
|
recv->block_irq_interval = 1;
|
||||||
|
|
||||||
/* choose a buffer stride */
|
/* choose a buffer stride */
|
||||||
/* must be a power of 2, and <= PAGE_SIZE */
|
/* must be a power of 2, and <= PAGE_SIZE */
|
||||||
|
Reference in New Issue
Block a user