diff options
author | hayeswang <hayeswang@realtek.com> | 2013-08-14 08:54:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-15 04:34:25 -0400 |
commit | ebc2ec484db9c7c96b41f7d0d6d9d2e24f601116 (patch) | |
tree | 5c21c4100f89d0c50a97a081a7fcebd25bed74a2 /drivers/net/usb | |
parent | fce9b9be89cece975675142a3953bfb5299d195d (diff) |
net/usb/r8152: support aggregation
Enable the tx/rx aggregation which could contain one or more packets
for each bulk in/out. This could reduce the loading of the host
controller by sending less bulk transfer.
The rx packets in the bulk in buffer should be 8-byte aligned, and
the tx packets in the bulk out buffer should be 4-byte aligned.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/r8152.c | 647 |
1 files changed, 486 insertions, 161 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 11c51f275366..abb0b9f260e9 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -19,9 +19,10 @@ | |||
19 | #include <linux/crc32.h> | 19 | #include <linux/crc32.h> |
20 | #include <linux/if_vlan.h> | 20 | #include <linux/if_vlan.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/list.h> | ||
22 | 23 | ||
23 | /* Version Information */ | 24 | /* Version Information */ |
24 | #define DRIVER_VERSION "v1.0.0 (2013/05/03)" | 25 | #define DRIVER_VERSION "v1.01.0 (2013/08/12)" |
25 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" | 26 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
26 | #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" | 27 | #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" |
27 | #define MODULENAME "r8152" | 28 | #define MODULENAME "r8152" |
@@ -267,6 +268,9 @@ enum rtl_register_content { | |||
267 | FULL_DUP = 0x01, | 268 | FULL_DUP = 0x01, |
268 | }; | 269 | }; |
269 | 270 | ||
271 | #define RTL8152_MAX_TX 10 | ||
272 | #define RTL8152_MAX_RX 10 | ||
273 | |||
270 | #define RTL8152_REQT_READ 0xc0 | 274 | #define RTL8152_REQT_READ 0xc0 |
271 | #define RTL8152_REQT_WRITE 0x40 | 275 | #define RTL8152_REQT_WRITE 0x40 |
272 | #define RTL8152_REQ_GET_REGS 0x05 | 276 | #define RTL8152_REQ_GET_REGS 0x05 |
@@ -285,7 +289,6 @@ enum rtl_register_content { | |||
285 | /* rtl8152 flags */ | 289 | /* rtl8152 flags */ |
286 | enum rtl8152_flags { | 290 | enum rtl8152_flags { |
287 | RTL8152_UNPLUG = 0, | 291 | RTL8152_UNPLUG = 0, |
288 | RX_URB_FAIL, | ||
289 | RTL8152_SET_RX_MODE, | 292 | RTL8152_SET_RX_MODE, |
290 | WORK_ENABLE | 293 | WORK_ENABLE |
291 | }; | 294 | }; |
@@ -315,13 +318,34 @@ struct tx_desc { | |||
315 | u32 opts2; | 318 | u32 opts2; |
316 | }; | 319 | }; |
317 | 320 | ||
321 | struct rx_agg { | ||
322 | struct list_head list; | ||
323 | struct urb *urb; | ||
324 | void *context; | ||
325 | void *buffer; | ||
326 | void *head; | ||
327 | }; | ||
328 | |||
329 | struct tx_agg { | ||
330 | struct list_head list; | ||
331 | struct urb *urb; | ||
332 | void *context; | ||
333 | void *buffer; | ||
334 | void *head; | ||
335 | u32 skb_num; | ||
336 | u32 skb_len; | ||
337 | }; | ||
338 | |||
318 | struct r8152 { | 339 | struct r8152 { |
319 | unsigned long flags; | 340 | unsigned long flags; |
320 | struct usb_device *udev; | 341 | struct usb_device *udev; |
321 | struct tasklet_struct tl; | 342 | struct tasklet_struct tl; |
322 | struct net_device *netdev; | 343 | struct net_device *netdev; |
323 | struct urb *rx_urb, *tx_urb; | 344 | struct tx_agg tx_info[RTL8152_MAX_TX]; |
324 | struct sk_buff *tx_skb, *rx_skb; | 345 | struct rx_agg rx_info[RTL8152_MAX_RX]; |
346 | struct list_head rx_done, tx_free; | ||
347 | struct sk_buff_head tx_queue; | ||
348 | spinlock_t rx_lock, tx_lock; | ||
325 | struct delayed_work schedule; | 349 | struct delayed_work schedule; |
326 | struct mii_if_info mii; | 350 | struct mii_if_info mii; |
327 | u32 msg_enable; | 351 | u32 msg_enable; |
@@ -340,6 +364,7 @@ enum rtl_version { | |||
340 | * The RTL chips use a 64 element hash table based on the Ethernet CRC. | 364 | * The RTL chips use a 64 element hash table based on the Ethernet CRC. |
341 | */ | 365 | */ |
342 | static const int multicast_filter_limit = 32; | 366 | static const int multicast_filter_limit = 32; |
367 | static unsigned int rx_buf_sz = 16384; | ||
343 | 368 | ||
344 | static | 369 | static |
345 | int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) | 370 | int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) |
@@ -686,6 +711,9 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) | |||
686 | ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data); | 711 | ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data); |
687 | } | 712 | } |
688 | 713 | ||
714 | static | ||
715 | int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); | ||
716 | |||
689 | static inline void set_ethernet_addr(struct r8152 *tp) | 717 | static inline void set_ethernet_addr(struct r8152 *tp) |
690 | { | 718 | { |
691 | struct net_device *dev = tp->netdev; | 719 | struct net_device *dev = tp->netdev; |
@@ -716,26 +744,6 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p) | |||
716 | return 0; | 744 | return 0; |
717 | } | 745 | } |
718 | 746 | ||
719 | static int alloc_all_urbs(struct r8152 *tp) | ||
720 | { | ||
721 | tp->rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
722 | if (!tp->rx_urb) | ||
723 | return 0; | ||
724 | tp->tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
725 | if (!tp->tx_urb) { | ||
726 | usb_free_urb(tp->rx_urb); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | return 1; | ||
731 | } | ||
732 | |||
733 | static void free_all_urbs(struct r8152 *tp) | ||
734 | { | ||
735 | usb_free_urb(tp->rx_urb); | ||
736 | usb_free_urb(tp->tx_urb); | ||
737 | } | ||
738 | |||
739 | static struct net_device_stats *rtl8152_get_stats(struct net_device *dev) | 747 | static struct net_device_stats *rtl8152_get_stats(struct net_device *dev) |
740 | { | 748 | { |
741 | return &dev->stats; | 749 | return &dev->stats; |
@@ -743,129 +751,425 @@ static struct net_device_stats *rtl8152_get_stats(struct net_device *dev) | |||
743 | 751 | ||
744 | static void read_bulk_callback(struct urb *urb) | 752 | static void read_bulk_callback(struct urb *urb) |
745 | { | 753 | { |
746 | struct r8152 *tp; | ||
747 | unsigned pkt_len; | ||
748 | struct sk_buff *skb; | ||
749 | struct net_device *netdev; | 754 | struct net_device *netdev; |
750 | struct net_device_stats *stats; | 755 | unsigned long lockflags; |
751 | int status = urb->status; | 756 | int status = urb->status; |
757 | struct rx_agg *agg; | ||
758 | struct r8152 *tp; | ||
752 | int result; | 759 | int result; |
753 | struct rx_desc *rx_desc; | ||
754 | 760 | ||
755 | tp = urb->context; | 761 | agg = urb->context; |
762 | if (!agg) | ||
763 | return; | ||
764 | |||
765 | tp = agg->context; | ||
756 | if (!tp) | 766 | if (!tp) |
757 | return; | 767 | return; |
768 | |||
758 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) | 769 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) |
759 | return; | 770 | return; |
771 | |||
772 | if (!test_bit(WORK_ENABLE, &tp->flags)) | ||
773 | return; | ||
774 | |||
760 | netdev = tp->netdev; | 775 | netdev = tp->netdev; |
761 | if (!netif_device_present(netdev)) | 776 | if (!netif_carrier_ok(netdev)) |
762 | return; | 777 | return; |
763 | 778 | ||
764 | stats = rtl8152_get_stats(netdev); | ||
765 | switch (status) { | 779 | switch (status) { |
766 | case 0: | 780 | case 0: |
767 | break; | 781 | if (urb->actual_length < ETH_ZLEN) |
782 | break; | ||
783 | |||
784 | spin_lock_irqsave(&tp->rx_lock, lockflags); | ||
785 | list_add_tail(&agg->list, &tp->rx_done); | ||
786 | spin_unlock_irqrestore(&tp->rx_lock, lockflags); | ||
787 | tasklet_schedule(&tp->tl); | ||
788 | return; | ||
768 | case -ESHUTDOWN: | 789 | case -ESHUTDOWN: |
769 | set_bit(RTL8152_UNPLUG, &tp->flags); | 790 | set_bit(RTL8152_UNPLUG, &tp->flags); |
770 | netif_device_detach(tp->netdev); | 791 | netif_device_detach(tp->netdev); |
792 | return; | ||
771 | case -ENOENT: | 793 | case -ENOENT: |
772 | return; /* the urb is in unlink state */ | 794 | return; /* the urb is in unlink state */ |
773 | case -ETIME: | 795 | case -ETIME: |
774 | pr_warn_ratelimited("may be reset is needed?..\n"); | 796 | pr_warn_ratelimited("may be reset is needed?..\n"); |
775 | goto goon; | 797 | break; |
776 | default: | 798 | default: |
777 | pr_warn_ratelimited("Rx status %d\n", status); | 799 | pr_warn_ratelimited("Rx status %d\n", status); |
778 | goto goon; | 800 | break; |
779 | } | 801 | } |
780 | 802 | ||
781 | /* protect against short packets (tell me why we got some?!?) */ | 803 | result = r8152_submit_rx(tp, agg, GFP_ATOMIC); |
782 | if (urb->actual_length < sizeof(*rx_desc)) | ||
783 | goto goon; | ||
784 | |||
785 | |||
786 | rx_desc = (struct rx_desc *)urb->transfer_buffer; | ||
787 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | ||
788 | if (urb->actual_length < sizeof(struct rx_desc) + pkt_len) | ||
789 | goto goon; | ||
790 | |||
791 | skb = netdev_alloc_skb_ip_align(netdev, pkt_len); | ||
792 | if (!skb) | ||
793 | goto goon; | ||
794 | |||
795 | memcpy(skb->data, tp->rx_skb->data + sizeof(struct rx_desc), pkt_len); | ||
796 | skb_put(skb, pkt_len); | ||
797 | skb->protocol = eth_type_trans(skb, netdev); | ||
798 | netif_rx(skb); | ||
799 | stats->rx_packets++; | ||
800 | stats->rx_bytes += pkt_len; | ||
801 | goon: | ||
802 | usb_fill_bulk_urb(tp->rx_urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1), | ||
803 | tp->rx_skb->data, RTL8152_RMS + sizeof(struct rx_desc), | ||
804 | (usb_complete_t)read_bulk_callback, tp); | ||
805 | result = usb_submit_urb(tp->rx_urb, GFP_ATOMIC); | ||
806 | if (result == -ENODEV) { | 804 | if (result == -ENODEV) { |
807 | netif_device_detach(tp->netdev); | 805 | netif_device_detach(tp->netdev); |
808 | } else if (result) { | 806 | } else if (result) { |
809 | set_bit(RX_URB_FAIL, &tp->flags); | 807 | spin_lock_irqsave(&tp->rx_lock, lockflags); |
810 | goto resched; | 808 | list_add_tail(&agg->list, &tp->rx_done); |
811 | } else { | 809 | spin_unlock_irqrestore(&tp->rx_lock, lockflags); |
812 | clear_bit(RX_URB_FAIL, &tp->flags); | 810 | tasklet_schedule(&tp->tl); |
813 | } | 811 | } |
814 | |||
815 | return; | ||
816 | resched: | ||
817 | tasklet_schedule(&tp->tl); | ||
818 | } | 812 | } |
819 | 813 | ||
820 | static void rx_fixup(unsigned long data) | 814 | static void write_bulk_callback(struct urb *urb) |
821 | { | 815 | { |
816 | struct net_device_stats *stats; | ||
817 | unsigned long lockflags; | ||
818 | struct tx_agg *agg; | ||
822 | struct r8152 *tp; | 819 | struct r8152 *tp; |
823 | int status; | 820 | int status = urb->status; |
824 | 821 | ||
825 | tp = (struct r8152 *)data; | 822 | agg = urb->context; |
826 | if (!test_bit(WORK_ENABLE, &tp->flags)) | 823 | if (!agg) |
827 | return; | 824 | return; |
828 | 825 | ||
829 | status = usb_submit_urb(tp->rx_urb, GFP_ATOMIC); | 826 | tp = agg->context; |
830 | if (status == -ENODEV) { | 827 | if (!tp) |
831 | netif_device_detach(tp->netdev); | 828 | return; |
832 | } else if (status) { | 829 | |
833 | set_bit(RX_URB_FAIL, &tp->flags); | 830 | stats = rtl8152_get_stats(tp->netdev); |
834 | goto tlsched; | 831 | if (status) { |
832 | pr_warn_ratelimited("Tx status %d\n", status); | ||
833 | stats->tx_errors += agg->skb_num; | ||
835 | } else { | 834 | } else { |
836 | clear_bit(RX_URB_FAIL, &tp->flags); | 835 | stats->tx_packets += agg->skb_num; |
836 | stats->tx_bytes += agg->skb_len; | ||
837 | } | 837 | } |
838 | 838 | ||
839 | return; | 839 | spin_lock_irqsave(&tp->tx_lock, lockflags); |
840 | tlsched: | 840 | list_add_tail(&agg->list, &tp->tx_free); |
841 | tasklet_schedule(&tp->tl); | 841 | spin_unlock_irqrestore(&tp->tx_lock, lockflags); |
842 | |||
843 | if (!netif_carrier_ok(tp->netdev)) | ||
844 | return; | ||
845 | |||
846 | if (!test_bit(WORK_ENABLE, &tp->flags)) | ||
847 | return; | ||
848 | |||
849 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) | ||
850 | return; | ||
851 | |||
852 | if (!skb_queue_empty(&tp->tx_queue)) | ||
853 | tasklet_schedule(&tp->tl); | ||
842 | } | 854 | } |
843 | 855 | ||
844 | static void write_bulk_callback(struct urb *urb) | 856 | static inline void *rx_agg_align(void *data) |
857 | { | ||
858 | return (void *)ALIGN((uintptr_t)data, 8); | ||
859 | } | ||
860 | |||
861 | static inline void *tx_agg_align(void *data) | ||
862 | { | ||
863 | return (void *)ALIGN((uintptr_t)data, 4); | ||
864 | } | ||
865 | |||
866 | static void free_all_mem(struct r8152 *tp) | ||
867 | { | ||
868 | int i; | ||
869 | |||
870 | for (i = 0; i < RTL8152_MAX_RX; i++) { | ||
871 | if (tp->rx_info[i].urb) { | ||
872 | usb_free_urb(tp->rx_info[i].urb); | ||
873 | tp->rx_info[i].urb = NULL; | ||
874 | } | ||
875 | |||
876 | if (tp->rx_info[i].buffer) { | ||
877 | kfree(tp->rx_info[i].buffer); | ||
878 | tp->rx_info[i].buffer = NULL; | ||
879 | tp->rx_info[i].head = NULL; | ||
880 | } | ||
881 | } | ||
882 | |||
883 | for (i = 0; i < RTL8152_MAX_TX; i++) { | ||
884 | if (tp->tx_info[i].urb) { | ||
885 | usb_free_urb(tp->tx_info[i].urb); | ||
886 | tp->tx_info[i].urb = NULL; | ||
887 | } | ||
888 | |||
889 | if (tp->tx_info[i].buffer) { | ||
890 | kfree(tp->tx_info[i].buffer); | ||
891 | tp->tx_info[i].buffer = NULL; | ||
892 | tp->tx_info[i].head = NULL; | ||
893 | } | ||
894 | } | ||
895 | } | ||
896 | |||
897 | static int alloc_all_mem(struct r8152 *tp) | ||
898 | { | ||
899 | struct net_device *netdev = tp->netdev; | ||
900 | struct urb *urb; | ||
901 | int node, i; | ||
902 | u8 *buf; | ||
903 | |||
904 | node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1; | ||
905 | |||
906 | spin_lock_init(&tp->rx_lock); | ||
907 | spin_lock_init(&tp->tx_lock); | ||
908 | INIT_LIST_HEAD(&tp->rx_done); | ||
909 | INIT_LIST_HEAD(&tp->tx_free); | ||
910 | skb_queue_head_init(&tp->tx_queue); | ||
911 | |||
912 | for (i = 0; i < RTL8152_MAX_RX; i++) { | ||
913 | buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); | ||
914 | if (!buf) | ||
915 | goto err1; | ||
916 | |||
917 | if (buf != rx_agg_align(buf)) { | ||
918 | kfree(buf); | ||
919 | buf = kmalloc_node(rx_buf_sz + 8, GFP_KERNEL, node); | ||
920 | if (!buf) | ||
921 | goto err1; | ||
922 | } | ||
923 | |||
924 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
925 | if (!urb) { | ||
926 | kfree(buf); | ||
927 | goto err1; | ||
928 | } | ||
929 | |||
930 | INIT_LIST_HEAD(&tp->rx_info[i].list); | ||
931 | tp->rx_info[i].context = tp; | ||
932 | tp->rx_info[i].urb = urb; | ||
933 | tp->rx_info[i].buffer = buf; | ||
934 | tp->rx_info[i].head = rx_agg_align(buf); | ||
935 | } | ||
936 | |||
937 | for (i = 0; i < RTL8152_MAX_TX; i++) { | ||
938 | buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); | ||
939 | if (!buf) | ||
940 | goto err1; | ||
941 | |||
942 | if (buf != tx_agg_align(buf)) { | ||
943 | kfree(buf); | ||
944 | buf = kmalloc_node(rx_buf_sz + 4, GFP_KERNEL, node); | ||
945 | if (!buf) | ||
946 | goto err1; | ||
947 | } | ||
948 | |||
949 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
950 | if (!urb) { | ||
951 | kfree(buf); | ||
952 | goto err1; | ||
953 | } | ||
954 | |||
955 | INIT_LIST_HEAD(&tp->tx_info[i].list); | ||
956 | tp->tx_info[i].context = tp; | ||
957 | tp->tx_info[i].urb = urb; | ||
958 | tp->tx_info[i].buffer = buf; | ||
959 | tp->tx_info[i].head = tx_agg_align(buf); | ||
960 | |||
961 | list_add_tail(&tp->tx_info[i].list, &tp->tx_free); | ||
962 | } | ||
963 | |||
964 | return 0; | ||
965 | |||
966 | err1: | ||
967 | free_all_mem(tp); | ||
968 | return -ENOMEM; | ||
969 | } | ||
970 | |||
971 | static void rx_bottom(struct r8152 *tp) | ||
972 | { | ||
973 | struct net_device_stats *stats; | ||
974 | struct net_device *netdev; | ||
975 | struct rx_agg *agg; | ||
976 | struct rx_desc *rx_desc; | ||
977 | unsigned long lockflags; | ||
978 | struct list_head *cursor, *next; | ||
979 | struct sk_buff *skb; | ||
980 | struct urb *urb; | ||
981 | unsigned pkt_len; | ||
982 | int len_used; | ||
983 | u8 *rx_data; | ||
984 | int ret; | ||
985 | |||
986 | netdev = tp->netdev; | ||
987 | |||
988 | stats = rtl8152_get_stats(netdev); | ||
989 | |||
990 | spin_lock_irqsave(&tp->rx_lock, lockflags); | ||
991 | list_for_each_safe(cursor, next, &tp->rx_done) { | ||
992 | list_del_init(cursor); | ||
993 | spin_unlock_irqrestore(&tp->rx_lock, lockflags); | ||
994 | |||
995 | agg = list_entry(cursor, struct rx_agg, list); | ||
996 | urb = agg->urb; | ||
997 | if (urb->actual_length < ETH_ZLEN) { | ||
998 | ret = r8152_submit_rx(tp, agg, GFP_ATOMIC); | ||
999 | spin_lock_irqsave(&tp->rx_lock, lockflags); | ||
1000 | if (ret && ret != -ENODEV) { | ||
1001 | list_add_tail(&agg->list, next); | ||
1002 | tasklet_schedule(&tp->tl); | ||
1003 | } | ||
1004 | continue; | ||
1005 | } | ||
1006 | |||
1007 | len_used = 0; | ||
1008 | rx_desc = agg->head; | ||
1009 | rx_data = agg->head; | ||
1010 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | ||
1011 | len_used += sizeof(struct rx_desc) + pkt_len; | ||
1012 | |||
1013 | while (urb->actual_length >= len_used) { | ||
1014 | if (pkt_len < ETH_ZLEN) | ||
1015 | break; | ||
1016 | |||
1017 | pkt_len -= 4; /* CRC */ | ||
1018 | rx_data += sizeof(struct rx_desc); | ||
1019 | |||
1020 | skb = netdev_alloc_skb_ip_align(netdev, pkt_len); | ||
1021 | if (!skb) { | ||
1022 | stats->rx_dropped++; | ||
1023 | break; | ||
1024 | } | ||
1025 | memcpy(skb->data, rx_data, pkt_len); | ||
1026 | skb_put(skb, pkt_len); | ||
1027 | skb->protocol = eth_type_trans(skb, netdev); | ||
1028 | netif_rx(skb); | ||
1029 | stats->rx_packets++; | ||
1030 | stats->rx_bytes += pkt_len; | ||
1031 | |||
1032 | rx_data = rx_agg_align(rx_data + pkt_len + 4); | ||
1033 | rx_desc = (struct rx_desc *)rx_data; | ||
1034 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | ||
1035 | len_used = (int)(rx_data - (u8 *)agg->head); | ||
1036 | len_used += sizeof(struct rx_desc) + pkt_len; | ||
1037 | } | ||
1038 | |||
1039 | ret = r8152_submit_rx(tp, agg, GFP_ATOMIC); | ||
1040 | spin_lock_irqsave(&tp->rx_lock, lockflags); | ||
1041 | if (ret && ret != -ENODEV) { | ||
1042 | list_add_tail(&agg->list, next); | ||
1043 | tasklet_schedule(&tp->tl); | ||
1044 | } | ||
1045 | } | ||
1046 | spin_unlock_irqrestore(&tp->rx_lock, lockflags); | ||
1047 | } | ||
1048 | |||
1049 | static void tx_bottom(struct r8152 *tp) | ||
1050 | { | ||
1051 | struct net_device_stats *stats; | ||
1052 | struct net_device *netdev; | ||
1053 | struct tx_agg *agg; | ||
1054 | unsigned long lockflags; | ||
1055 | u32 remain, total; | ||
1056 | u8 *tx_data; | ||
1057 | int res; | ||
1058 | |||
1059 | netdev = tp->netdev; | ||
1060 | |||
1061 | next_agg: | ||
1062 | agg = NULL; | ||
1063 | spin_lock_irqsave(&tp->tx_lock, lockflags); | ||
1064 | if (!skb_queue_empty(&tp->tx_queue) && !list_empty(&tp->tx_free)) { | ||
1065 | struct list_head *cursor; | ||
1066 | |||
1067 | cursor = tp->tx_free.next; | ||
1068 | list_del_init(cursor); | ||
1069 | agg = list_entry(cursor, struct tx_agg, list); | ||
1070 | } | ||
1071 | spin_unlock_irqrestore(&tp->tx_lock, lockflags); | ||
1072 | |||
1073 | if (!agg) | ||
1074 | return; | ||
1075 | |||
1076 | tx_data = agg->head; | ||
1077 | agg->skb_num = agg->skb_len = 0; | ||
1078 | remain = rx_buf_sz - sizeof(struct tx_desc); | ||
1079 | total = 0; | ||
1080 | |||
1081 | while (remain >= ETH_ZLEN) { | ||
1082 | struct tx_desc *tx_desc; | ||
1083 | struct sk_buff *skb; | ||
1084 | unsigned int len; | ||
1085 | |||
1086 | skb = skb_dequeue(&tp->tx_queue); | ||
1087 | if (!skb) | ||
1088 | break; | ||
1089 | |||
1090 | len = skb->len; | ||
1091 | if (remain < len) { | ||
1092 | skb_queue_head(&tp->tx_queue, skb); | ||
1093 | break; | ||
1094 | } | ||
1095 | |||
1096 | tx_data = tx_agg_align(tx_data); | ||
1097 | tx_desc = (struct tx_desc *)tx_data; | ||
1098 | tx_data += sizeof(*tx_desc); | ||
1099 | |||
1100 | tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | | ||
1101 | TX_LS); | ||
1102 | memcpy(tx_data, skb->data, len); | ||
1103 | agg->skb_num++; | ||
1104 | agg->skb_len += len; | ||
1105 | dev_kfree_skb_any(skb); | ||
1106 | |||
1107 | tx_data += len; | ||
1108 | remain = rx_buf_sz - sizeof(*tx_desc) - | ||
1109 | (u32)(tx_agg_align(tx_data) - agg->head); | ||
1110 | } | ||
1111 | |||
1112 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | ||
1113 | agg->head, (int)(tx_data - (u8 *)agg->head), | ||
1114 | (usb_complete_t)write_bulk_callback, agg); | ||
1115 | res = usb_submit_urb(agg->urb, GFP_ATOMIC); | ||
1116 | |||
1117 | stats = rtl8152_get_stats(netdev); | ||
1118 | |||
1119 | if (res) { | ||
1120 | /* Can we get/handle EPIPE here? */ | ||
1121 | if (res == -ENODEV) { | ||
1122 | netif_device_detach(netdev); | ||
1123 | } else { | ||
1124 | netif_warn(tp, tx_err, netdev, | ||
1125 | "failed tx_urb %d\n", res); | ||
1126 | stats->tx_dropped += agg->skb_num; | ||
1127 | spin_lock_irqsave(&tp->tx_lock, lockflags); | ||
1128 | list_add_tail(&agg->list, &tp->tx_free); | ||
1129 | spin_unlock_irqrestore(&tp->tx_lock, lockflags); | ||
1130 | } | ||
1131 | return; | ||
1132 | } | ||
1133 | goto next_agg; | ||
1134 | } | ||
1135 | |||
1136 | static void bottom_half(unsigned long data) | ||
845 | { | 1137 | { |
846 | struct r8152 *tp; | 1138 | struct r8152 *tp; |
847 | int status = urb->status; | ||
848 | 1139 | ||
849 | tp = urb->context; | 1140 | tp = (struct r8152 *)data; |
850 | if (!tp) | 1141 | |
1142 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) | ||
1143 | return; | ||
1144 | |||
1145 | if (!test_bit(WORK_ENABLE, &tp->flags)) | ||
851 | return; | 1146 | return; |
852 | dev_kfree_skb_irq(tp->tx_skb); | 1147 | |
853 | if (!netif_device_present(tp->netdev)) | 1148 | if (!netif_carrier_ok(tp->netdev)) |
854 | return; | 1149 | return; |
855 | if (status) | 1150 | |
856 | dev_info(&urb->dev->dev, "%s: Tx status %d\n", | 1151 | rx_bottom(tp); |
857 | tp->netdev->name, status); | 1152 | tx_bottom(tp); |
858 | tp->netdev->trans_start = jiffies; | 1153 | } |
859 | netif_wake_queue(tp->netdev); | 1154 | |
1155 | static | ||
1156 | int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags) | ||
1157 | { | ||
1158 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1), | ||
1159 | agg->head, rx_buf_sz, | ||
1160 | (usb_complete_t)read_bulk_callback, agg); | ||
1161 | |||
1162 | return usb_submit_urb(agg->urb, mem_flags); | ||
860 | } | 1163 | } |
861 | 1164 | ||
862 | static void rtl8152_tx_timeout(struct net_device *netdev) | 1165 | static void rtl8152_tx_timeout(struct net_device *netdev) |
863 | { | 1166 | { |
864 | struct r8152 *tp = netdev_priv(netdev); | 1167 | struct r8152 *tp = netdev_priv(netdev); |
865 | struct net_device_stats *stats = rtl8152_get_stats(netdev); | 1168 | int i; |
1169 | |||
866 | netif_warn(tp, tx_err, netdev, "Tx timeout.\n"); | 1170 | netif_warn(tp, tx_err, netdev, "Tx timeout.\n"); |
867 | usb_unlink_urb(tp->tx_urb); | 1171 | for (i = 0; i < RTL8152_MAX_TX; i++) |
868 | stats->tx_errors++; | 1172 | usb_unlink_urb(tp->tx_info[i].urb); |
869 | } | 1173 | } |
870 | 1174 | ||
871 | static void rtl8152_set_rx_mode(struct net_device *netdev) | 1175 | static void rtl8152_set_rx_mode(struct net_device *netdev) |
@@ -923,33 +1227,44 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, | |||
923 | { | 1227 | { |
924 | struct r8152 *tp = netdev_priv(netdev); | 1228 | struct r8152 *tp = netdev_priv(netdev); |
925 | struct net_device_stats *stats = rtl8152_get_stats(netdev); | 1229 | struct net_device_stats *stats = rtl8152_get_stats(netdev); |
1230 | unsigned long lockflags; | ||
1231 | struct tx_agg *agg = NULL; | ||
926 | struct tx_desc *tx_desc; | 1232 | struct tx_desc *tx_desc; |
927 | unsigned int len; | 1233 | unsigned int len; |
1234 | u8 *tx_data; | ||
928 | int res; | 1235 | int res; |
929 | 1236 | ||
930 | netif_stop_queue(netdev); | 1237 | skb_tx_timestamp(skb); |
931 | len = skb->len; | ||
932 | if (skb_header_cloned(skb) || skb_headroom(skb) < sizeof(*tx_desc)) { | ||
933 | struct sk_buff *tx_skb; | ||
934 | 1238 | ||
935 | tx_skb = skb_copy_expand(skb, sizeof(*tx_desc), 0, GFP_ATOMIC); | 1239 | spin_lock_irqsave(&tp->tx_lock, lockflags); |
936 | dev_kfree_skb_any(skb); | 1240 | if (!list_empty(&tp->tx_free) && skb_queue_empty(&tp->tx_queue)) { |
937 | if (!tx_skb) { | 1241 | struct list_head *cursor; |
938 | stats->tx_dropped++; | 1242 | |
939 | netif_wake_queue(netdev); | 1243 | cursor = tp->tx_free.next; |
940 | return NETDEV_TX_OK; | 1244 | list_del_init(cursor); |
941 | } | 1245 | agg = list_entry(cursor, struct tx_agg, list); |
942 | skb = tx_skb; | ||
943 | } | 1246 | } |
944 | tx_desc = (struct tx_desc *)skb_push(skb, sizeof(*tx_desc)); | 1247 | spin_unlock_irqrestore(&tp->tx_lock, lockflags); |
945 | memset(tx_desc, 0, sizeof(*tx_desc)); | 1248 | |
946 | tx_desc->opts1 = cpu_to_le32((len & TX_LEN_MASK) | TX_FS | TX_LS); | 1249 | if (!agg) { |
947 | tp->tx_skb = skb; | 1250 | skb_queue_tail(&tp->tx_queue, skb); |
948 | skb_tx_timestamp(skb); | 1251 | return NETDEV_TX_OK; |
949 | usb_fill_bulk_urb(tp->tx_urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | 1252 | } |
950 | skb->data, skb->len, | 1253 | |
951 | (usb_complete_t)write_bulk_callback, tp); | 1254 | tx_desc = (struct tx_desc *)agg->head; |
952 | res = usb_submit_urb(tp->tx_urb, GFP_ATOMIC); | 1255 | tx_data = agg->head + sizeof(*tx_desc); |
1256 | agg->skb_num = agg->skb_len = 0; | ||
1257 | |||
1258 | len = skb->len; | ||
1259 | tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS); | ||
1260 | memcpy(tx_data, skb->data, len); | ||
1261 | dev_kfree_skb_any(skb); | ||
1262 | agg->skb_num++; | ||
1263 | agg->skb_len += len; | ||
1264 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | ||
1265 | agg->head, len + sizeof(*tx_desc), | ||
1266 | (usb_complete_t)write_bulk_callback, agg); | ||
1267 | res = usb_submit_urb(agg->urb, GFP_ATOMIC); | ||
953 | if (res) { | 1268 | if (res) { |
954 | /* Can we get/handle EPIPE here? */ | 1269 | /* Can we get/handle EPIPE here? */ |
955 | if (res == -ENODEV) { | 1270 | if (res == -ENODEV) { |
@@ -957,12 +1272,11 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, | |||
957 | } else { | 1272 | } else { |
958 | netif_warn(tp, tx_err, netdev, | 1273 | netif_warn(tp, tx_err, netdev, |
959 | "failed tx_urb %d\n", res); | 1274 | "failed tx_urb %d\n", res); |
960 | stats->tx_errors++; | 1275 | stats->tx_dropped++; |
961 | netif_start_queue(netdev); | 1276 | spin_lock_irqsave(&tp->tx_lock, lockflags); |
1277 | list_add_tail(&agg->list, &tp->tx_free); | ||
1278 | spin_unlock_irqrestore(&tp->tx_lock, lockflags); | ||
962 | } | 1279 | } |
963 | } else { | ||
964 | stats->tx_packets++; | ||
965 | stats->tx_bytes += skb->len; | ||
966 | } | 1280 | } |
967 | 1281 | ||
968 | return NETDEV_TX_OK; | 1282 | return NETDEV_TX_OK; |
@@ -999,17 +1313,18 @@ static inline u8 rtl8152_get_speed(struct r8152 *tp) | |||
999 | 1313 | ||
1000 | static int rtl8152_enable(struct r8152 *tp) | 1314 | static int rtl8152_enable(struct r8152 *tp) |
1001 | { | 1315 | { |
1002 | u32 ocp_data; | 1316 | u32 ocp_data; |
1317 | int i, ret; | ||
1003 | u8 speed; | 1318 | u8 speed; |
1004 | 1319 | ||
1005 | speed = rtl8152_get_speed(tp); | 1320 | speed = rtl8152_get_speed(tp); |
1006 | if (speed & _100bps) { | 1321 | if (speed & _10bps) { |
1007 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); | 1322 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); |
1008 | ocp_data &= ~EEEP_CR_EEEP_TX; | 1323 | ocp_data |= EEEP_CR_EEEP_TX; |
1009 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); | 1324 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); |
1010 | } else { | 1325 | } else { |
1011 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); | 1326 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); |
1012 | ocp_data |= EEEP_CR_EEEP_TX; | 1327 | ocp_data &= ~EEEP_CR_EEEP_TX; |
1013 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); | 1328 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); |
1014 | } | 1329 | } |
1015 | 1330 | ||
@@ -1023,23 +1338,34 @@ static int rtl8152_enable(struct r8152 *tp) | |||
1023 | ocp_data &= ~RXDY_GATED_EN; | 1338 | ocp_data &= ~RXDY_GATED_EN; |
1024 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data); | 1339 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data); |
1025 | 1340 | ||
1026 | usb_fill_bulk_urb(tp->rx_urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1), | 1341 | INIT_LIST_HEAD(&tp->rx_done); |
1027 | tp->rx_skb->data, RTL8152_RMS + sizeof(struct rx_desc), | 1342 | ret = 0; |
1028 | (usb_complete_t)read_bulk_callback, tp); | 1343 | for (i = 0; i < RTL8152_MAX_RX; i++) { |
1344 | INIT_LIST_HEAD(&tp->rx_info[i].list); | ||
1345 | ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); | ||
1346 | } | ||
1029 | 1347 | ||
1030 | return usb_submit_urb(tp->rx_urb, GFP_KERNEL); | 1348 | return ret; |
1031 | } | 1349 | } |
1032 | 1350 | ||
1033 | static void rtl8152_disable(struct r8152 *tp) | 1351 | static void rtl8152_disable(struct r8152 *tp) |
1034 | { | 1352 | { |
1035 | u32 ocp_data; | 1353 | struct net_device_stats *stats = rtl8152_get_stats(tp->netdev); |
1036 | int i; | 1354 | struct sk_buff *skb; |
1355 | u32 ocp_data; | ||
1356 | int i; | ||
1037 | 1357 | ||
1038 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | 1358 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); |
1039 | ocp_data &= ~RCR_ACPT_ALL; | 1359 | ocp_data &= ~RCR_ACPT_ALL; |
1040 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | 1360 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); |
1041 | 1361 | ||
1042 | usb_kill_urb(tp->tx_urb); | 1362 | while ((skb = skb_dequeue(&tp->tx_queue))) { |
1363 | dev_kfree_skb(skb); | ||
1364 | stats->tx_dropped++; | ||
1365 | } | ||
1366 | |||
1367 | for (i = 0; i < RTL8152_MAX_TX; i++) | ||
1368 | usb_kill_urb(tp->tx_info[i].urb); | ||
1043 | 1369 | ||
1044 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1); | 1370 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1); |
1045 | ocp_data |= RXDY_GATED_EN; | 1371 | ocp_data |= RXDY_GATED_EN; |
@@ -1058,7 +1384,8 @@ static void rtl8152_disable(struct r8152 *tp) | |||
1058 | mdelay(1); | 1384 | mdelay(1); |
1059 | } | 1385 | } |
1060 | 1386 | ||
1061 | usb_kill_urb(tp->rx_urb); | 1387 | for (i = 0; i < RTL8152_MAX_RX; i++) |
1388 | usb_kill_urb(tp->rx_info[i].urb); | ||
1062 | 1389 | ||
1063 | rtl8152_nic_reset(tp); | 1390 | rtl8152_nic_reset(tp); |
1064 | } | 1391 | } |
@@ -1303,7 +1630,9 @@ static void set_carrier(struct r8152 *tp) | |||
1303 | } else { | 1630 | } else { |
1304 | if (tp->speed & LINK_STATUS) { | 1631 | if (tp->speed & LINK_STATUS) { |
1305 | netif_carrier_off(netdev); | 1632 | netif_carrier_off(netdev); |
1633 | tasklet_disable(&tp->tl); | ||
1306 | rtl8152_disable(tp); | 1634 | rtl8152_disable(tp); |
1635 | tasklet_enable(&tp->tl); | ||
1307 | } | 1636 | } |
1308 | } | 1637 | } |
1309 | tp->speed = speed; | 1638 | tp->speed = speed; |
@@ -1369,7 +1698,9 @@ static int rtl8152_close(struct net_device *netdev) | |||
1369 | clear_bit(WORK_ENABLE, &tp->flags); | 1698 | clear_bit(WORK_ENABLE, &tp->flags); |
1370 | cancel_delayed_work_sync(&tp->schedule); | 1699 | cancel_delayed_work_sync(&tp->schedule); |
1371 | netif_stop_queue(netdev); | 1700 | netif_stop_queue(netdev); |
1701 | tasklet_disable(&tp->tl); | ||
1372 | rtl8152_disable(tp); | 1702 | rtl8152_disable(tp); |
1703 | tasklet_enable(&tp->tl); | ||
1373 | 1704 | ||
1374 | return res; | 1705 | return res; |
1375 | } | 1706 | } |
@@ -1429,8 +1760,8 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp) | |||
1429 | 1760 | ||
1430 | static void r8152b_init(struct r8152 *tp) | 1761 | static void r8152b_init(struct r8152 *tp) |
1431 | { | 1762 | { |
1432 | u32 ocp_data; | 1763 | u32 ocp_data; |
1433 | int i; | 1764 | int i; |
1434 | 1765 | ||
1435 | rtl_clear_bp(tp); | 1766 | rtl_clear_bp(tp); |
1436 | 1767 | ||
@@ -1475,9 +1806,9 @@ static void r8152b_init(struct r8152 *tp) | |||
1475 | break; | 1806 | break; |
1476 | } | 1807 | } |
1477 | 1808 | ||
1478 | /* disable rx aggregation */ | 1809 | /* enable rx aggregation */ |
1479 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); | 1810 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); |
1480 | ocp_data |= RX_AGG_DISABLE; | 1811 | ocp_data &= ~RX_AGG_DISABLE; |
1481 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); | 1812 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); |
1482 | } | 1813 | } |
1483 | 1814 | ||
@@ -1490,6 +1821,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) | |||
1490 | if (netif_running(tp->netdev)) { | 1821 | if (netif_running(tp->netdev)) { |
1491 | clear_bit(WORK_ENABLE, &tp->flags); | 1822 | clear_bit(WORK_ENABLE, &tp->flags); |
1492 | cancel_delayed_work_sync(&tp->schedule); | 1823 | cancel_delayed_work_sync(&tp->schedule); |
1824 | tasklet_disable(&tp->tl); | ||
1493 | } | 1825 | } |
1494 | 1826 | ||
1495 | rtl8152_down(tp); | 1827 | rtl8152_down(tp); |
@@ -1508,6 +1840,7 @@ static int rtl8152_resume(struct usb_interface *intf) | |||
1508 | set_bit(WORK_ENABLE, &tp->flags); | 1840 | set_bit(WORK_ENABLE, &tp->flags); |
1509 | set_bit(RTL8152_SET_RX_MODE, &tp->flags); | 1841 | set_bit(RTL8152_SET_RX_MODE, &tp->flags); |
1510 | schedule_delayed_work(&tp->schedule, 0); | 1842 | schedule_delayed_work(&tp->schedule, 0); |
1843 | tasklet_enable(&tp->tl); | ||
1511 | } | 1844 | } |
1512 | 1845 | ||
1513 | return 0; | 1846 | return 0; |
@@ -1619,6 +1952,7 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
1619 | struct usb_device *udev = interface_to_usbdev(intf); | 1952 | struct usb_device *udev = interface_to_usbdev(intf); |
1620 | struct r8152 *tp; | 1953 | struct r8152 *tp; |
1621 | struct net_device *netdev; | 1954 | struct net_device *netdev; |
1955 | int ret; | ||
1622 | 1956 | ||
1623 | if (udev->actconfig->desc.bConfigurationValue != 1) { | 1957 | if (udev->actconfig->desc.bConfigurationValue != 1) { |
1624 | usb_driver_set_configuration(udev, 1); | 1958 | usb_driver_set_configuration(udev, 1); |
@@ -1631,10 +1965,12 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
1631 | return -ENOMEM; | 1965 | return -ENOMEM; |
1632 | } | 1966 | } |
1633 | 1967 | ||
1968 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
1634 | tp = netdev_priv(netdev); | 1969 | tp = netdev_priv(netdev); |
1970 | memset(tp, 0, sizeof(*tp)); | ||
1635 | tp->msg_enable = 0x7FFF; | 1971 | tp->msg_enable = 0x7FFF; |
1636 | 1972 | ||
1637 | tasklet_init(&tp->tl, rx_fixup, (unsigned long)tp); | 1973 | tasklet_init(&tp->tl, bottom_half, (unsigned long)tp); |
1638 | INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); | 1974 | INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); |
1639 | 1975 | ||
1640 | tp->udev = udev; | 1976 | tp->udev = udev; |
@@ -1657,37 +1993,27 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
1657 | r8152b_init(tp); | 1993 | r8152b_init(tp); |
1658 | set_ethernet_addr(tp); | 1994 | set_ethernet_addr(tp); |
1659 | 1995 | ||
1660 | if (!alloc_all_urbs(tp)) { | 1996 | ret = alloc_all_mem(tp); |
1661 | netif_err(tp, probe, netdev, "out of memory"); | 1997 | if (ret) |
1662 | goto out; | 1998 | goto out; |
1663 | } | ||
1664 | |||
1665 | tp->rx_skb = netdev_alloc_skb(netdev, | ||
1666 | RTL8152_RMS + sizeof(struct rx_desc)); | ||
1667 | if (!tp->rx_skb) | ||
1668 | goto out1; | ||
1669 | 1999 | ||
1670 | usb_set_intfdata(intf, tp); | 2000 | usb_set_intfdata(intf, tp); |
1671 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
1672 | 2001 | ||
1673 | 2002 | ret = register_netdev(netdev); | |
1674 | if (register_netdev(netdev) != 0) { | 2003 | if (ret != 0) { |
1675 | netif_err(tp, probe, netdev, "couldn't register the device"); | 2004 | netif_err(tp, probe, netdev, "couldn't register the device"); |
1676 | goto out2; | 2005 | goto out1; |
1677 | } | 2006 | } |
1678 | 2007 | ||
1679 | netif_info(tp, probe, netdev, "%s", DRIVER_VERSION); | 2008 | netif_info(tp, probe, netdev, "%s", DRIVER_VERSION); |
1680 | 2009 | ||
1681 | return 0; | 2010 | return 0; |
1682 | 2011 | ||
1683 | out2: | ||
1684 | usb_set_intfdata(intf, NULL); | ||
1685 | dev_kfree_skb(tp->rx_skb); | ||
1686 | out1: | 2012 | out1: |
1687 | free_all_urbs(tp); | 2013 | usb_set_intfdata(intf, NULL); |
1688 | out: | 2014 | out: |
1689 | free_netdev(netdev); | 2015 | free_netdev(netdev); |
1690 | return -EIO; | 2016 | return ret; |
1691 | } | 2017 | } |
1692 | 2018 | ||
1693 | static void rtl8152_unload(struct r8152 *tp) | 2019 | static void rtl8152_unload(struct r8152 *tp) |
@@ -1715,9 +2041,7 @@ static void rtl8152_disconnect(struct usb_interface *intf) | |||
1715 | tasklet_kill(&tp->tl); | 2041 | tasklet_kill(&tp->tl); |
1716 | unregister_netdev(tp->netdev); | 2042 | unregister_netdev(tp->netdev); |
1717 | rtl8152_unload(tp); | 2043 | rtl8152_unload(tp); |
1718 | free_all_urbs(tp); | 2044 | free_all_mem(tp); |
1719 | if (tp->rx_skb) | ||
1720 | dev_kfree_skb(tp->rx_skb); | ||
1721 | free_netdev(tp->netdev); | 2045 | free_netdev(tp->netdev); |
1722 | } | 2046 | } |
1723 | } | 2047 | } |
@@ -1732,11 +2056,12 @@ MODULE_DEVICE_TABLE(usb, rtl8152_table); | |||
1732 | 2056 | ||
1733 | static struct usb_driver rtl8152_driver = { | 2057 | static struct usb_driver rtl8152_driver = { |
1734 | .name = MODULENAME, | 2058 | .name = MODULENAME, |
2059 | .id_table = rtl8152_table, | ||
1735 | .probe = rtl8152_probe, | 2060 | .probe = rtl8152_probe, |
1736 | .disconnect = rtl8152_disconnect, | 2061 | .disconnect = rtl8152_disconnect, |
1737 | .id_table = rtl8152_table, | ||
1738 | .suspend = rtl8152_suspend, | 2062 | .suspend = rtl8152_suspend, |
1739 | .resume = rtl8152_resume | 2063 | .resume = rtl8152_resume, |
2064 | .reset_resume = rtl8152_resume, | ||
1740 | }; | 2065 | }; |
1741 | 2066 | ||
1742 | module_usb_driver(rtl8152_driver); | 2067 | module_usb_driver(rtl8152_driver); |