diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-14 05:45:27 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-14 08:26:29 -0400 |
commit | 5a124d382ea5c97be43c779e4f481455e0287654 (patch) | |
tree | d77069fe1456932f4ce2872dc6b1f963cb8662c5 /drivers/firewire | |
parent | f91e3bd842ec6f5cea245993926ee8ff26250467 (diff) |
firewire: net: allow for unordered unit discovery
Decouple the creation and destruction of the net_device from the order
of discovery and removal of nodes with RFC 2734 unit directories since
there is no reliable order. The net_device is now created when the
first RFC 2734 unit on a card is discovered, and destroyed when the last
RFC 2734 unit on a card went away. This includes all remote units as
well as the local unit, which is therefore tracked as a peer now too.
Also, locking around the list of peers is slightly extended to guard
against peer removal. As a side effect, fwnet_peer.pdg_lock has become
superfluous and is deleted.
Peer data (max_rec, speed, node ID, generation) are updated more
carefully.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 2 | ||||
-rw-r--r-- | drivers/firewire/net.c | 454 |
2 files changed, 207 insertions, 249 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 8c45e43da7c5..667603ac14b1 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -429,8 +429,6 @@ void fw_card_initialize(struct fw_card *card, | |||
429 | card->local_node = NULL; | 429 | card->local_node = NULL; |
430 | 430 | ||
431 | INIT_DELAYED_WORK(&card->work, fw_card_bm_work); | 431 | INIT_DELAYED_WORK(&card->work, fw_card_bm_work); |
432 | card->netdev = NULL; | ||
433 | INIT_LIST_HEAD(&card->peer_list); | ||
434 | } | 432 | } |
435 | EXPORT_SYMBOL(fw_card_initialize); | 433 | EXPORT_SYMBOL(fw_card_initialize); |
436 | 434 | ||
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index ba6f924b1b13..d83c54587a63 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c | |||
@@ -18,8 +18,10 @@ | |||
18 | #include <linux/mod_devicetable.h> | 18 | #include <linux/mod_devicetable.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
21 | #include <linux/mutex.h> | ||
21 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
22 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/spinlock.h> | ||
23 | 25 | ||
24 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
25 | #include <net/arp.h> | 27 | #include <net/arp.h> |
@@ -135,40 +137,11 @@ struct fwnet_partial_datagram { | |||
135 | u16 datagram_size; | 137 | u16 datagram_size; |
136 | }; | 138 | }; |
137 | 139 | ||
138 | /* | 140 | static DEFINE_MUTEX(fwnet_device_mutex); |
139 | * We keep one of these for each IPv4 capable device attached to a fw_card. | 141 | static LIST_HEAD(fwnet_device_list); |
140 | * The list of them is stored in the fw_card structure rather than in the | ||
141 | * fwnet_device because the remote IPv4 nodes may be probed before the card is, | ||
142 | * so we need a place to store them before the fwnet_device structure is | ||
143 | * allocated. | ||
144 | */ | ||
145 | struct fwnet_peer { | ||
146 | struct list_head peer_link; | ||
147 | /* guid of the remote peer */ | ||
148 | u64 guid; | ||
149 | /* FIFO address to transmit datagrams to, or FWNET_NO_FIFO_ADDR */ | ||
150 | u64 fifo; | ||
151 | |||
152 | spinlock_t pdg_lock; /* partial datagram lock */ | ||
153 | /* List of partial datagrams received from this peer */ | ||
154 | struct list_head pd_list; | ||
155 | /* Number of entries in pd_list at the moment */ | ||
156 | unsigned pdg_size; | ||
157 | |||
158 | /* max payload to transmit to this remote peer */ | ||
159 | /* This already includes the RFC2374_FRAG_HDR_SIZE overhead */ | ||
160 | u16 max_payload; | ||
161 | /* outgoing datagram label */ | ||
162 | u16 datagram_label; | ||
163 | /* Current node_id of the remote peer */ | ||
164 | u16 node_id; | ||
165 | /* current generation of the remote peer */ | ||
166 | u8 generation; | ||
167 | /* max speed that this peer can receive at */ | ||
168 | u8 xmt_speed; | ||
169 | }; | ||
170 | 142 | ||
171 | struct fwnet_device { | 143 | struct fwnet_device { |
144 | struct list_head dev_link; | ||
172 | spinlock_t lock; | 145 | spinlock_t lock; |
173 | enum { | 146 | enum { |
174 | FWNET_BROADCAST_ERROR, | 147 | FWNET_BROADCAST_ERROR, |
@@ -206,7 +179,26 @@ struct fwnet_device { | |||
206 | /* List of packets that have been sent but not yet acked */ | 179 | /* List of packets that have been sent but not yet acked */ |
207 | struct list_head sent_list; | 180 | struct list_head sent_list; |
208 | 181 | ||
182 | struct list_head peer_list; | ||
209 | struct fw_card *card; | 183 | struct fw_card *card; |
184 | struct net_device *netdev; | ||
185 | }; | ||
186 | |||
187 | struct fwnet_peer { | ||
188 | struct list_head peer_link; | ||
189 | struct fwnet_device *dev; | ||
190 | u64 guid; | ||
191 | u64 fifo; | ||
192 | |||
193 | /* guarded by dev->lock */ | ||
194 | struct list_head pd_list; /* received partial datagrams */ | ||
195 | unsigned pdg_size; /* pd_list size */ | ||
196 | |||
197 | u16 datagram_label; /* outgoing datagram label */ | ||
198 | unsigned max_payload; /* includes RFC2374_FRAG_HDR_SIZE overhead */ | ||
199 | int node_id; | ||
200 | int generation; | ||
201 | unsigned speed; | ||
210 | }; | 202 | }; |
211 | 203 | ||
212 | /* This is our task struct. It's used for the packet complete callback. */ | 204 | /* This is our task struct. It's used for the packet complete callback. */ |
@@ -479,102 +471,47 @@ static bool fwnet_pd_is_complete(struct fwnet_partial_datagram *pd) | |||
479 | return fi->len == pd->datagram_size; | 471 | return fi->len == pd->datagram_size; |
480 | } | 472 | } |
481 | 473 | ||
482 | static int fwnet_peer_new(struct fw_card *card, struct fw_device *device) | 474 | /* caller must hold dev->lock */ |
483 | { | ||
484 | struct fwnet_peer *peer; | ||
485 | |||
486 | peer = kmalloc(sizeof(*peer), GFP_KERNEL); | ||
487 | if (!peer) { | ||
488 | fw_error("out of memory\n"); | ||
489 | |||
490 | return -ENOMEM; | ||
491 | } | ||
492 | peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; | ||
493 | peer->fifo = FWNET_NO_FIFO_ADDR; | ||
494 | INIT_LIST_HEAD(&peer->pd_list); | ||
495 | spin_lock_init(&peer->pdg_lock); | ||
496 | peer->pdg_size = 0; | ||
497 | peer->generation = device->generation; | ||
498 | rmb(); | ||
499 | peer->node_id = device->node_id; | ||
500 | /* FIXME what should it really be? */ | ||
501 | peer->max_payload = IEEE1394_MAX_PAYLOAD_S100 - RFC2374_UNFRAG_HDR_SIZE; | ||
502 | peer->datagram_label = 0U; | ||
503 | peer->xmt_speed = device->max_speed; | ||
504 | list_add_tail(&peer->peer_link, &card->peer_list); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | /* FIXME caller must take the lock, or peer needs to be reference-counted */ | ||
510 | static struct fwnet_peer *fwnet_peer_find_by_guid(struct fwnet_device *dev, | 475 | static struct fwnet_peer *fwnet_peer_find_by_guid(struct fwnet_device *dev, |
511 | u64 guid) | 476 | u64 guid) |
512 | { | 477 | { |
513 | struct fwnet_peer *p, *peer = NULL; | 478 | struct fwnet_peer *peer; |
514 | unsigned long flags; | ||
515 | 479 | ||
516 | spin_lock_irqsave(&dev->lock, flags); | 480 | list_for_each_entry(peer, &dev->peer_list, peer_link) |
517 | list_for_each_entry(p, &dev->card->peer_list, peer_link) | 481 | if (peer->guid == guid) |
518 | if (p->guid == guid) { | 482 | return peer; |
519 | peer = p; | ||
520 | break; | ||
521 | } | ||
522 | spin_unlock_irqrestore(&dev->lock, flags); | ||
523 | 483 | ||
524 | return peer; | 484 | return NULL; |
525 | } | 485 | } |
526 | 486 | ||
527 | /* FIXME caller must take the lock, or peer needs to be reference-counted */ | 487 | /* caller must hold dev->lock */ |
528 | /* FIXME node_id doesn't mean anything without generation */ | ||
529 | static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev, | 488 | static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev, |
530 | u16 node_id) | 489 | int node_id, int generation) |
531 | { | 490 | { |
532 | struct fwnet_peer *p, *peer = NULL; | 491 | struct fwnet_peer *peer; |
533 | unsigned long flags; | ||
534 | 492 | ||
535 | spin_lock_irqsave(&dev->lock, flags); | 493 | list_for_each_entry(peer, &dev->peer_list, peer_link) |
536 | list_for_each_entry(p, &dev->card->peer_list, peer_link) | 494 | if (peer->node_id == node_id && |
537 | if (p->node_id == node_id) { | 495 | peer->generation == generation) |
538 | peer = p; | 496 | return peer; |
539 | break; | ||
540 | } | ||
541 | spin_unlock_irqrestore(&dev->lock, flags); | ||
542 | 497 | ||
543 | return peer; | 498 | return NULL; |
544 | } | 499 | } |
545 | 500 | ||
546 | /* FIXME */ | 501 | /* See IEEE 1394-2008 table 6-4, table 8-8, table 16-18. */ |
547 | static void fwnet_peer_delete(struct fw_card *card, struct fw_device *device) | 502 | static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed) |
548 | { | 503 | { |
549 | struct net_device *net; | 504 | max_rec = min(max_rec, speed + 8); |
550 | struct fwnet_device *dev; | 505 | max_rec = min(max_rec, 0xbU); /* <= 4096 */ |
551 | struct fwnet_peer *peer; | 506 | if (max_rec < 8) { |
552 | u64 guid; | 507 | fw_notify("max_rec %x out of range\n", max_rec); |
553 | unsigned long flags; | 508 | max_rec = 8; |
554 | struct fwnet_partial_datagram *pd, *pd_next; | ||
555 | |||
556 | guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; | ||
557 | net = card->netdev; | ||
558 | if (net) | ||
559 | dev = netdev_priv(net); | ||
560 | else | ||
561 | dev = NULL; | ||
562 | if (dev) | ||
563 | spin_lock_irqsave(&dev->lock, flags); | ||
564 | |||
565 | list_for_each_entry(peer, &card->peer_list, peer_link) { | ||
566 | if (peer->guid == guid) { | ||
567 | list_del(&peer->peer_link); | ||
568 | list_for_each_entry_safe(pd, pd_next, &peer->pd_list, | ||
569 | pd_link) | ||
570 | fwnet_pd_delete(pd); | ||
571 | break; | ||
572 | } | ||
573 | } | 509 | } |
574 | if (dev) | 510 | |
575 | spin_unlock_irqrestore(&dev->lock, flags); | 511 | return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE; |
576 | } | 512 | } |
577 | 513 | ||
514 | |||
578 | static int fwnet_finish_incoming_packet(struct net_device *net, | 515 | static int fwnet_finish_incoming_packet(struct net_device *net, |
579 | struct sk_buff *skb, u16 source_node_id, | 516 | struct sk_buff *skb, u16 source_node_id, |
580 | bool is_broadcast, u16 ether_type) | 517 | bool is_broadcast, u16 ether_type) |
@@ -606,71 +543,44 @@ static int fwnet_finish_incoming_packet(struct net_device *net, | |||
606 | unsigned char *arp_ptr; | 543 | unsigned char *arp_ptr; |
607 | u64 fifo_addr; | 544 | u64 fifo_addr; |
608 | u64 peer_guid; | 545 | u64 peer_guid; |
609 | u8 max_rec; | 546 | unsigned sspd; |
610 | u8 sspd; | ||
611 | u16 max_payload; | 547 | u16 max_payload; |
612 | struct fwnet_peer *peer; | 548 | struct fwnet_peer *peer; |
613 | static const u16 fwnet_speed_to_max_payload[] = { | 549 | unsigned long flags; |
614 | /* S100, S200, S400, S800, S1600, S3200 */ | 550 | |
615 | 512, 1024, 2048, 4096, 4096, 4096 | 551 | arp1394 = (struct rfc2734_arp *)skb->data; |
616 | }; | 552 | arp = (struct arphdr *)skb->data; |
553 | arp_ptr = (unsigned char *)(arp + 1); | ||
554 | peer_guid = get_unaligned_be64(&arp1394->s_uniq_id); | ||
555 | fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32 | ||
556 | | get_unaligned_be32(&arp1394->fifo_lo); | ||
617 | 557 | ||
618 | arp1394 = (struct rfc2734_arp *)skb->data; | ||
619 | arp = (struct arphdr *)skb->data; | ||
620 | arp_ptr = (unsigned char *)(arp + 1); | ||
621 | fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 | ||
622 | | ntohl(arp1394->fifo_lo); | ||
623 | max_rec = dev->card->max_receive; | ||
624 | if (arp1394->max_rec < max_rec) | ||
625 | max_rec = arp1394->max_rec; | ||
626 | sspd = arp1394->sspd; | 558 | sspd = arp1394->sspd; |
627 | /* Sanity check. OS X 10.3 PPC reportedly sends 131. */ | 559 | /* Sanity check. OS X 10.3 PPC reportedly sends 131. */ |
628 | if (sspd > SCODE_3200) { | 560 | if (sspd > SCODE_3200) { |
629 | fw_notify("sspd %x out of range\n", sspd); | 561 | fw_notify("sspd %x out of range\n", sspd); |
630 | sspd = 0; | 562 | sspd = SCODE_3200; |
631 | } | 563 | } |
564 | max_payload = fwnet_max_payload(arp1394->max_rec, sspd); | ||
632 | 565 | ||
633 | max_payload = min(fwnet_speed_to_max_payload[sspd], | 566 | spin_lock_irqsave(&dev->lock, flags); |
634 | (u16)(1 << (max_rec + 1))) - RFC2374_UNFRAG_HDR_SIZE; | ||
635 | |||
636 | peer_guid = get_unaligned_be64(&arp1394->s_uniq_id); | ||
637 | peer = fwnet_peer_find_by_guid(dev, peer_guid); | 567 | peer = fwnet_peer_find_by_guid(dev, peer_guid); |
568 | if (peer) { | ||
569 | peer->fifo = fifo_addr; | ||
570 | |||
571 | if (peer->speed > sspd) | ||
572 | peer->speed = sspd; | ||
573 | if (peer->max_payload > max_payload) | ||
574 | peer->max_payload = max_payload; | ||
575 | } | ||
576 | spin_unlock_irqrestore(&dev->lock, flags); | ||
577 | |||
638 | if (!peer) { | 578 | if (!peer) { |
639 | fw_notify("No peer for ARP packet from %016llx\n", | 579 | fw_notify("No peer for ARP packet from %016llx\n", |
640 | (unsigned long long)peer_guid); | 580 | (unsigned long long)peer_guid); |
641 | goto failed_proto; | 581 | goto failed_proto; |
642 | } | 582 | } |
643 | 583 | ||
644 | /* FIXME don't use card->generation */ | ||
645 | if (peer->node_id != source_node_id || | ||
646 | peer->generation != dev->card->generation) { | ||
647 | fw_notify("Internal error: peer->node_id (%x) != " | ||
648 | "source_node_id (%x) or peer->generation (%x)" | ||
649 | " != dev->card->generation(%x)\n", | ||
650 | peer->node_id, source_node_id, | ||
651 | peer->generation, dev->card->generation); | ||
652 | peer->node_id = source_node_id; | ||
653 | peer->generation = dev->card->generation; | ||
654 | } | ||
655 | |||
656 | /* FIXME: for debugging */ | ||
657 | if (sspd > SCODE_400) | ||
658 | sspd = SCODE_400; | ||
659 | /* Update our speed/payload/fifo_offset table */ | ||
660 | /* | ||
661 | * FIXME: this does not handle cases where two high-speed endpoints must use a slower speed because of | ||
662 | * a lower speed hub between them. We need to look at the actual topology map here. | ||
663 | */ | ||
664 | peer->fifo = fifo_addr; | ||
665 | peer->max_payload = max_payload; | ||
666 | /* | ||
667 | * Only allow speeds to go down from their initial value. | ||
668 | * Otherwise a local peer that can only do S400 or slower may | ||
669 | * be told to transmit at S800 to a faster remote peer. | ||
670 | */ | ||
671 | if (peer->xmt_speed > sspd) | ||
672 | peer->xmt_speed = sspd; | ||
673 | |||
674 | /* | 584 | /* |
675 | * Now that we're done with the 1394 specific stuff, we'll | 585 | * Now that we're done with the 1394 specific stuff, we'll |
676 | * need to alter some of the data. Believe it or not, all | 586 | * need to alter some of the data. Believe it or not, all |
@@ -764,10 +674,11 @@ static int fwnet_finish_incoming_packet(struct net_device *net, | |||
764 | } | 674 | } |
765 | 675 | ||
766 | static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | 676 | static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, |
767 | u16 source_node_id, bool is_broadcast) | 677 | int source_node_id, int generation, |
678 | bool is_broadcast) | ||
768 | { | 679 | { |
769 | struct sk_buff *skb; | 680 | struct sk_buff *skb; |
770 | struct net_device *net; | 681 | struct net_device *net = dev->netdev; |
771 | struct rfc2734_header hdr; | 682 | struct rfc2734_header hdr; |
772 | unsigned lf; | 683 | unsigned lf; |
773 | unsigned long flags; | 684 | unsigned long flags; |
@@ -779,8 +690,6 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
779 | int retval; | 690 | int retval; |
780 | u16 ether_type; | 691 | u16 ether_type; |
781 | 692 | ||
782 | net = dev->card->netdev; | ||
783 | |||
784 | hdr.w0 = be32_to_cpu(buf[0]); | 693 | hdr.w0 = be32_to_cpu(buf[0]); |
785 | lf = fwnet_get_hdr_lf(&hdr); | 694 | lf = fwnet_get_hdr_lf(&hdr); |
786 | if (lf == RFC2374_HDR_UNFRAG) { | 695 | if (lf == RFC2374_HDR_UNFRAG) { |
@@ -819,9 +728,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
819 | } | 728 | } |
820 | datagram_label = fwnet_get_hdr_dgl(&hdr); | 729 | datagram_label = fwnet_get_hdr_dgl(&hdr); |
821 | dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ | 730 | dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ |
822 | peer = fwnet_peer_find_by_node_id(dev, source_node_id); | ||
823 | 731 | ||
824 | spin_lock_irqsave(&peer->pdg_lock, flags); | 732 | spin_lock_irqsave(&dev->lock, flags); |
733 | |||
734 | peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); | ||
735 | if (!peer) | ||
736 | goto bad_proto; | ||
825 | 737 | ||
826 | pd = fwnet_pd_find(peer, datagram_label); | 738 | pd = fwnet_pd_find(peer, datagram_label); |
827 | if (pd == NULL) { | 739 | if (pd == NULL) { |
@@ -876,7 +788,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
876 | skb = skb_get(pd->skb); | 788 | skb = skb_get(pd->skb); |
877 | fwnet_pd_delete(pd); | 789 | fwnet_pd_delete(pd); |
878 | 790 | ||
879 | spin_unlock_irqrestore(&peer->pdg_lock, flags); | 791 | spin_unlock_irqrestore(&dev->lock, flags); |
880 | 792 | ||
881 | return fwnet_finish_incoming_packet(net, skb, source_node_id, | 793 | return fwnet_finish_incoming_packet(net, skb, source_node_id, |
882 | false, ether_type); | 794 | false, ether_type); |
@@ -885,12 +797,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
885 | * Datagram is not complete, we're done for the | 797 | * Datagram is not complete, we're done for the |
886 | * moment. | 798 | * moment. |
887 | */ | 799 | */ |
888 | spin_unlock_irqrestore(&peer->pdg_lock, flags); | 800 | spin_unlock_irqrestore(&dev->lock, flags); |
889 | 801 | ||
890 | return 0; | 802 | return 0; |
891 | 803 | ||
892 | bad_proto: | 804 | bad_proto: |
893 | spin_unlock_irqrestore(&peer->pdg_lock, flags); | 805 | spin_unlock_irqrestore(&dev->lock, flags); |
894 | 806 | ||
895 | if (netif_queue_stopped(net)) | 807 | if (netif_queue_stopped(net)) |
896 | netif_wake_queue(net); | 808 | netif_wake_queue(net); |
@@ -916,7 +828,8 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, | |||
916 | return; | 828 | return; |
917 | } | 829 | } |
918 | 830 | ||
919 | status = fwnet_incoming_packet(dev, payload, length, source, false); | 831 | status = fwnet_incoming_packet(dev, payload, length, |
832 | source, generation, false); | ||
920 | if (status != 0) { | 833 | if (status != 0) { |
921 | fw_error("Incoming packet failure\n"); | 834 | fw_error("Incoming packet failure\n"); |
922 | fw_send_response(card, r, RCODE_CONFLICT_ERROR); | 835 | fw_send_response(card, r, RCODE_CONFLICT_ERROR); |
@@ -966,7 +879,7 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, | |||
966 | buf_ptr += 2; | 879 | buf_ptr += 2; |
967 | length -= IEEE1394_GASP_HDR_SIZE; | 880 | length -= IEEE1394_GASP_HDR_SIZE; |
968 | fwnet_incoming_packet(dev, buf_ptr, length, | 881 | fwnet_incoming_packet(dev, buf_ptr, length, |
969 | source_node_id, true); | 882 | source_node_id, -1, true); |
970 | } | 883 | } |
971 | 884 | ||
972 | packet.payload_length = dev->rcv_buffer_size; | 885 | packet.payload_length = dev->rcv_buffer_size; |
@@ -1073,7 +986,6 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) | |||
1073 | unsigned tx_len; | 986 | unsigned tx_len; |
1074 | struct rfc2734_header *bufhdr; | 987 | struct rfc2734_header *bufhdr; |
1075 | unsigned long flags; | 988 | unsigned long flags; |
1076 | struct net_device *net; | ||
1077 | 989 | ||
1078 | dev = ptask->dev; | 990 | dev = ptask->dev; |
1079 | tx_len = ptask->max_payload; | 991 | tx_len = ptask->max_payload; |
@@ -1137,8 +1049,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) | |||
1137 | list_add_tail(&ptask->pt_link, &dev->sent_list); | 1049 | list_add_tail(&ptask->pt_link, &dev->sent_list); |
1138 | spin_unlock_irqrestore(&dev->lock, flags); | 1050 | spin_unlock_irqrestore(&dev->lock, flags); |
1139 | 1051 | ||
1140 | net = dev->card->netdev; | 1052 | dev->netdev->trans_start = jiffies; |
1141 | net->trans_start = jiffies; | ||
1142 | 1053 | ||
1143 | return 0; | 1054 | return 0; |
1144 | } | 1055 | } |
@@ -1294,7 +1205,8 @@ static int fwnet_tx(struct sk_buff *skb, struct net_device *net) | |||
1294 | u16 dg_size; | 1205 | u16 dg_size; |
1295 | u16 *datagram_label_ptr; | 1206 | u16 *datagram_label_ptr; |
1296 | struct fwnet_packet_task *ptask; | 1207 | struct fwnet_packet_task *ptask; |
1297 | struct fwnet_peer *peer = NULL; | 1208 | struct fwnet_peer *peer; |
1209 | unsigned long flags; | ||
1298 | 1210 | ||
1299 | ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC); | 1211 | ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC); |
1300 | if (ptask == NULL) | 1212 | if (ptask == NULL) |
@@ -1314,6 +1226,9 @@ static int fwnet_tx(struct sk_buff *skb, struct net_device *net) | |||
1314 | proto = hdr_buf.h_proto; | 1226 | proto = hdr_buf.h_proto; |
1315 | dg_size = skb->len; | 1227 | dg_size = skb->len; |
1316 | 1228 | ||
1229 | /* serialize access to peer, including peer->datagram_label */ | ||
1230 | spin_lock_irqsave(&dev->lock, flags); | ||
1231 | |||
1317 | /* | 1232 | /* |
1318 | * Set the transmission type for the packet. ARP packets and IP | 1233 | * Set the transmission type for the packet. ARP packets and IP |
1319 | * broadcast packets are sent via GASP. | 1234 | * broadcast packets are sent via GASP. |
@@ -1322,35 +1237,30 @@ static int fwnet_tx(struct sk_buff *skb, struct net_device *net) | |||
1322 | || proto == htons(ETH_P_ARP) | 1237 | || proto == htons(ETH_P_ARP) |
1323 | || (proto == htons(ETH_P_IP) | 1238 | || (proto == htons(ETH_P_IP) |
1324 | && IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) { | 1239 | && IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) { |
1325 | max_payload = dev->broadcast_xmt_max_payload; | 1240 | max_payload = dev->broadcast_xmt_max_payload; |
1326 | datagram_label_ptr = &dev->broadcast_xmt_datagramlabel; | 1241 | datagram_label_ptr = &dev->broadcast_xmt_datagramlabel; |
1327 | 1242 | ||
1328 | ptask->fifo_addr = FWNET_NO_FIFO_ADDR; | 1243 | ptask->fifo_addr = FWNET_NO_FIFO_ADDR; |
1329 | ptask->generation = 0; | 1244 | ptask->generation = 0; |
1330 | ptask->dest_node = IEEE1394_ALL_NODES; | 1245 | ptask->dest_node = IEEE1394_ALL_NODES; |
1331 | ptask->speed = SCODE_100; | 1246 | ptask->speed = SCODE_100; |
1332 | } else { | 1247 | } else { |
1333 | __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); | 1248 | __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); |
1334 | u8 generation; | 1249 | u8 generation; |
1335 | 1250 | ||
1336 | peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid)); | 1251 | peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid)); |
1337 | if (!peer) | 1252 | if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR) |
1338 | goto fail; | 1253 | goto fail_unlock; |
1339 | |||
1340 | if (peer->fifo == FWNET_NO_FIFO_ADDR) | ||
1341 | goto fail; | ||
1342 | 1254 | ||
1343 | generation = peer->generation; | 1255 | generation = peer->generation; |
1344 | smp_rmb(); | 1256 | dest_node = peer->node_id; |
1345 | dest_node = peer->node_id; | 1257 | max_payload = peer->max_payload; |
1346 | |||
1347 | max_payload = peer->max_payload; | ||
1348 | datagram_label_ptr = &peer->datagram_label; | 1258 | datagram_label_ptr = &peer->datagram_label; |
1349 | 1259 | ||
1350 | ptask->fifo_addr = peer->fifo; | 1260 | ptask->fifo_addr = peer->fifo; |
1351 | ptask->generation = generation; | 1261 | ptask->generation = generation; |
1352 | ptask->dest_node = dest_node; | 1262 | ptask->dest_node = dest_node; |
1353 | ptask->speed = peer->xmt_speed; | 1263 | ptask->speed = peer->speed; |
1354 | } | 1264 | } |
1355 | 1265 | ||
1356 | /* If this is an ARP packet, convert it */ | 1266 | /* If this is an ARP packet, convert it */ |
@@ -1393,11 +1303,16 @@ static int fwnet_tx(struct sk_buff *skb, struct net_device *net) | |||
1393 | ptask->outstanding_pkts = DIV_ROUND_UP(dg_size, max_payload); | 1303 | ptask->outstanding_pkts = DIV_ROUND_UP(dg_size, max_payload); |
1394 | max_payload += RFC2374_FRAG_HDR_SIZE; | 1304 | max_payload += RFC2374_FRAG_HDR_SIZE; |
1395 | } | 1305 | } |
1306 | |||
1307 | spin_unlock_irqrestore(&dev->lock, flags); | ||
1308 | |||
1396 | ptask->max_payload = max_payload; | 1309 | ptask->max_payload = max_payload; |
1397 | fwnet_send_packet(ptask); | 1310 | fwnet_send_packet(ptask); |
1398 | 1311 | ||
1399 | return NETDEV_TX_OK; | 1312 | return NETDEV_TX_OK; |
1400 | 1313 | ||
1314 | fail_unlock: | ||
1315 | spin_unlock_irqrestore(&dev->lock, flags); | ||
1401 | fail: | 1316 | fail: |
1402 | if (ptask) | 1317 | if (ptask) |
1403 | kmem_cache_free(fwnet_packet_task_cache, ptask); | 1318 | kmem_cache_free(fwnet_packet_task_cache, ptask); |
@@ -1467,7 +1382,48 @@ static void fwnet_init_dev(struct net_device *net) | |||
1467 | SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops); | 1382 | SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops); |
1468 | } | 1383 | } |
1469 | 1384 | ||
1470 | /* FIXME create netdev upon first fw_unit of a card, not upon local fw_unit */ | 1385 | /* caller must hold fwnet_device_mutex */ |
1386 | static struct fwnet_device *fwnet_dev_find(struct fw_card *card) | ||
1387 | { | ||
1388 | struct fwnet_device *dev; | ||
1389 | |||
1390 | list_for_each_entry(dev, &fwnet_device_list, dev_link) | ||
1391 | if (dev->card == card) | ||
1392 | return dev; | ||
1393 | |||
1394 | return NULL; | ||
1395 | } | ||
1396 | |||
1397 | static int fwnet_add_peer(struct fwnet_device *dev, | ||
1398 | struct fw_unit *unit, struct fw_device *device) | ||
1399 | { | ||
1400 | struct fwnet_peer *peer; | ||
1401 | |||
1402 | peer = kmalloc(sizeof(*peer), GFP_KERNEL); | ||
1403 | if (!peer) | ||
1404 | return -ENOMEM; | ||
1405 | |||
1406 | unit->device.driver_data = peer; | ||
1407 | peer->dev = dev; | ||
1408 | peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; | ||
1409 | peer->fifo = FWNET_NO_FIFO_ADDR; | ||
1410 | INIT_LIST_HEAD(&peer->pd_list); | ||
1411 | peer->pdg_size = 0; | ||
1412 | peer->datagram_label = 0; | ||
1413 | peer->speed = device->max_speed; | ||
1414 | peer->max_payload = fwnet_max_payload(device->max_rec, peer->speed); | ||
1415 | |||
1416 | peer->generation = device->generation; | ||
1417 | smp_rmb(); | ||
1418 | peer->node_id = device->node_id; | ||
1419 | |||
1420 | spin_lock_irq(&dev->lock); | ||
1421 | list_add_tail(&peer->peer_link, &dev->peer_list); | ||
1422 | spin_unlock_irq(&dev->lock); | ||
1423 | |||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1471 | static int fwnet_probe(struct device *_dev) | 1427 | static int fwnet_probe(struct device *_dev) |
1472 | { | 1428 | { |
1473 | struct fw_unit *unit = fw_unit(_dev); | 1429 | struct fw_unit *unit = fw_unit(_dev); |
@@ -1476,16 +1432,22 @@ static int fwnet_probe(struct device *_dev) | |||
1476 | struct net_device *net; | 1432 | struct net_device *net; |
1477 | struct fwnet_device *dev; | 1433 | struct fwnet_device *dev; |
1478 | unsigned max_mtu; | 1434 | unsigned max_mtu; |
1435 | bool new_netdev; | ||
1436 | int ret; | ||
1479 | 1437 | ||
1480 | if (!device->is_local) { | 1438 | mutex_lock(&fwnet_device_mutex); |
1481 | int added; | ||
1482 | 1439 | ||
1483 | added = fwnet_peer_new(card, device); | 1440 | dev = fwnet_dev_find(card); |
1484 | return added; | 1441 | if (dev) { |
1442 | new_netdev = false; | ||
1443 | net = dev->netdev; | ||
1444 | goto have_dev; | ||
1485 | } | 1445 | } |
1446 | |||
1447 | new_netdev = true; | ||
1486 | net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev); | 1448 | net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev); |
1487 | if (net == NULL) { | 1449 | if (net == NULL) { |
1488 | fw_error("out of memory\n"); | 1450 | ret = -ENOMEM; |
1489 | goto out; | 1451 | goto out; |
1490 | } | 1452 | } |
1491 | 1453 | ||
@@ -1500,12 +1462,13 @@ static int fwnet_probe(struct device *_dev) | |||
1500 | 1462 | ||
1501 | dev->local_fifo = FWNET_NO_FIFO_ADDR; | 1463 | dev->local_fifo = FWNET_NO_FIFO_ADDR; |
1502 | 1464 | ||
1503 | /* INIT_WORK(&dev->wake, fwnet_handle_queue);*/ | ||
1504 | INIT_LIST_HEAD(&dev->packet_list); | 1465 | INIT_LIST_HEAD(&dev->packet_list); |
1505 | INIT_LIST_HEAD(&dev->broadcasted_list); | 1466 | INIT_LIST_HEAD(&dev->broadcasted_list); |
1506 | INIT_LIST_HEAD(&dev->sent_list); | 1467 | INIT_LIST_HEAD(&dev->sent_list); |
1468 | INIT_LIST_HEAD(&dev->peer_list); | ||
1507 | 1469 | ||
1508 | dev->card = card; | 1470 | dev->card = card; |
1471 | dev->netdev = net; | ||
1509 | 1472 | ||
1510 | /* | 1473 | /* |
1511 | * Use the RFC 2734 default 1500 octets or the maximum payload | 1474 | * Use the RFC 2734 default 1500 octets or the maximum payload |
@@ -1518,43 +1481,57 @@ static int fwnet_probe(struct device *_dev) | |||
1518 | /* Set our hardware address while we're at it */ | 1481 | /* Set our hardware address while we're at it */ |
1519 | put_unaligned_be64(card->guid, net->dev_addr); | 1482 | put_unaligned_be64(card->guid, net->dev_addr); |
1520 | put_unaligned_be64(~0ULL, net->broadcast); | 1483 | put_unaligned_be64(~0ULL, net->broadcast); |
1521 | if (register_netdev(net)) { | 1484 | ret = register_netdev(net); |
1485 | if (ret) { | ||
1522 | fw_error("Cannot register the driver\n"); | 1486 | fw_error("Cannot register the driver\n"); |
1523 | goto out; | 1487 | goto out; |
1524 | } | 1488 | } |
1525 | 1489 | ||
1490 | list_add_tail(&dev->dev_link, &fwnet_device_list); | ||
1526 | fw_notify("%s: IPv4 over FireWire on device %016llx\n", | 1491 | fw_notify("%s: IPv4 over FireWire on device %016llx\n", |
1527 | net->name, (unsigned long long)card->guid); | 1492 | net->name, (unsigned long long)card->guid); |
1528 | card->netdev = net; | 1493 | have_dev: |
1529 | 1494 | ret = fwnet_add_peer(dev, unit, device); | |
1530 | return 0; | 1495 | if (ret && new_netdev) { |
1496 | unregister_netdev(net); | ||
1497 | list_del(&dev->dev_link); | ||
1498 | } | ||
1531 | out: | 1499 | out: |
1532 | if (net) | 1500 | if (ret && new_netdev) |
1533 | free_netdev(net); | 1501 | free_netdev(net); |
1534 | 1502 | ||
1535 | return -ENOENT; | 1503 | mutex_unlock(&fwnet_device_mutex); |
1504 | |||
1505 | return ret; | ||
1506 | } | ||
1507 | |||
1508 | static void fwnet_remove_peer(struct fwnet_peer *peer) | ||
1509 | { | ||
1510 | struct fwnet_partial_datagram *pd, *pd_next; | ||
1511 | |||
1512 | spin_lock_irq(&peer->dev->lock); | ||
1513 | list_del(&peer->peer_link); | ||
1514 | spin_unlock_irq(&peer->dev->lock); | ||
1515 | |||
1516 | list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link) | ||
1517 | fwnet_pd_delete(pd); | ||
1518 | |||
1519 | kfree(peer); | ||
1536 | } | 1520 | } |
1537 | 1521 | ||
1538 | static int fwnet_remove(struct device *_dev) | 1522 | static int fwnet_remove(struct device *_dev) |
1539 | { | 1523 | { |
1540 | struct fw_unit *unit = fw_unit(_dev); | 1524 | struct fwnet_peer *peer = _dev->driver_data; |
1541 | struct fw_device *device = fw_parent_device(unit); | 1525 | struct fwnet_device *dev = peer->dev; |
1542 | struct fw_card *card = device->card; | ||
1543 | struct net_device *net; | 1526 | struct net_device *net; |
1544 | struct fwnet_device *dev; | ||
1545 | struct fwnet_peer *peer; | ||
1546 | struct fwnet_partial_datagram *pd, *pd_next; | ||
1547 | struct fwnet_packet_task *ptask, *pt_next; | 1527 | struct fwnet_packet_task *ptask, *pt_next; |
1548 | 1528 | ||
1549 | if (!device->is_local) { | 1529 | mutex_lock(&fwnet_device_mutex); |
1550 | fwnet_peer_delete(card, device); | ||
1551 | 1530 | ||
1552 | return 0; | 1531 | fwnet_remove_peer(peer); |
1553 | } | ||
1554 | 1532 | ||
1555 | net = card->netdev; | 1533 | if (list_empty(&dev->peer_list)) { |
1556 | if (net) { | 1534 | net = dev->netdev; |
1557 | dev = netdev_priv(net); | ||
1558 | unregister_netdev(net); | 1535 | unregister_netdev(net); |
1559 | 1536 | ||
1560 | if (dev->local_fifo != FWNET_NO_FIFO_ADDR) | 1537 | if (dev->local_fifo != FWNET_NO_FIFO_ADDR) |
@@ -1580,19 +1557,11 @@ static int fwnet_remove(struct device *_dev) | |||
1580 | dev_kfree_skb_any(ptask->skb); | 1557 | dev_kfree_skb_any(ptask->skb); |
1581 | kmem_cache_free(fwnet_packet_task_cache, ptask); | 1558 | kmem_cache_free(fwnet_packet_task_cache, ptask); |
1582 | } | 1559 | } |
1583 | list_for_each_entry(peer, &card->peer_list, peer_link) { | ||
1584 | if (peer->pdg_size) { | ||
1585 | list_for_each_entry_safe(pd, pd_next, | ||
1586 | &peer->pd_list, pd_link) | ||
1587 | fwnet_pd_delete(pd); | ||
1588 | peer->pdg_size = 0; | ||
1589 | } | ||
1590 | peer->fifo = FWNET_NO_FIFO_ADDR; | ||
1591 | } | ||
1592 | free_netdev(net); | 1560 | free_netdev(net); |
1593 | card->netdev = NULL; | ||
1594 | } | 1561 | } |
1595 | 1562 | ||
1563 | mutex_unlock(&fwnet_device_mutex); | ||
1564 | |||
1596 | return 0; | 1565 | return 0; |
1597 | } | 1566 | } |
1598 | 1567 | ||
@@ -1603,24 +1572,15 @@ static int fwnet_remove(struct device *_dev) | |||
1603 | static void fwnet_update(struct fw_unit *unit) | 1572 | static void fwnet_update(struct fw_unit *unit) |
1604 | { | 1573 | { |
1605 | struct fw_device *device = fw_parent_device(unit); | 1574 | struct fw_device *device = fw_parent_device(unit); |
1606 | struct net_device *net = device->card->netdev; | 1575 | struct fwnet_peer *peer = unit->device.driver_data; |
1607 | struct fwnet_device *dev; | 1576 | int generation; |
1608 | struct fwnet_peer *peer; | ||
1609 | u64 guid; | ||
1610 | 1577 | ||
1611 | if (net && !device->is_local) { | 1578 | generation = device->generation; |
1612 | dev = netdev_priv(net); | 1579 | |
1613 | guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; | 1580 | spin_lock_irq(&peer->dev->lock); |
1614 | peer = fwnet_peer_find_by_guid(dev, guid); | 1581 | peer->node_id = device->node_id; |
1615 | if (!peer) { | 1582 | peer->generation = generation; |
1616 | fw_error("fwnet_update: no peer for device %016llx\n", | 1583 | spin_unlock_irq(&peer->dev->lock); |
1617 | (unsigned long long)guid); | ||
1618 | return; | ||
1619 | } | ||
1620 | peer->generation = device->generation; | ||
1621 | rmb(); | ||
1622 | peer->node_id = device->node_id; | ||
1623 | } | ||
1624 | } | 1584 | } |
1625 | 1585 | ||
1626 | static const struct ieee1394_device_id fwnet_id_table[] = { | 1586 | static const struct ieee1394_device_id fwnet_id_table[] = { |