diff options
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
| -rw-r--r-- | drivers/s390/net/qeth_main.c | 217 |
1 files changed, 93 insertions, 124 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 2bde4f1fb9c2..d2efa5ff125d 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
| @@ -471,7 +471,7 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
| 471 | channel->state == CH_STATE_UP) | 471 | channel->state == CH_STATE_UP) |
| 472 | qeth_issue_next_read(card); | 472 | qeth_issue_next_read(card); |
| 473 | 473 | ||
| 474 | tasklet_schedule(&channel->irq_tasklet); | 474 | qeth_irq_tasklet((unsigned long)channel); |
| 475 | return; | 475 | return; |
| 476 | out: | 476 | out: |
| 477 | wake_up(&card->wait_q); | 477 | wake_up(&card->wait_q); |
| @@ -951,40 +951,6 @@ qeth_do_run_thread(struct qeth_card *card, unsigned long thread) | |||
| 951 | } | 951 | } |
| 952 | 952 | ||
| 953 | static int | 953 | static int |
| 954 | qeth_register_ip_addresses(void *ptr) | ||
| 955 | { | ||
| 956 | struct qeth_card *card; | ||
| 957 | |||
| 958 | card = (struct qeth_card *) ptr; | ||
| 959 | daemonize("qeth_reg_ip"); | ||
| 960 | QETH_DBF_TEXT(trace,4,"regipth1"); | ||
| 961 | if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD)) | ||
| 962 | return 0; | ||
| 963 | QETH_DBF_TEXT(trace,4,"regipth2"); | ||
| 964 | qeth_set_ip_addr_list(card); | ||
| 965 | qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD); | ||
| 966 | return 0; | ||
| 967 | } | ||
| 968 | |||
| 969 | /* | ||
| 970 | * Drive the SET_PROMISC_MODE thread | ||
| 971 | */ | ||
| 972 | static int | ||
| 973 | qeth_set_promisc_mode(void *ptr) | ||
| 974 | { | ||
| 975 | struct qeth_card *card = (struct qeth_card *) ptr; | ||
| 976 | |||
| 977 | daemonize("qeth_setprm"); | ||
| 978 | QETH_DBF_TEXT(trace,4,"setprm1"); | ||
| 979 | if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD)) | ||
| 980 | return 0; | ||
| 981 | QETH_DBF_TEXT(trace,4,"setprm2"); | ||
| 982 | qeth_setadp_promisc_mode(card); | ||
| 983 | qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD); | ||
| 984 | return 0; | ||
| 985 | } | ||
| 986 | |||
| 987 | static int | ||
| 988 | qeth_recover(void *ptr) | 954 | qeth_recover(void *ptr) |
| 989 | { | 955 | { |
| 990 | struct qeth_card *card; | 956 | struct qeth_card *card; |
| @@ -1047,11 +1013,6 @@ qeth_start_kernel_thread(struct work_struct *work) | |||
| 1047 | if (card->read.state != CH_STATE_UP && | 1013 | if (card->read.state != CH_STATE_UP && |
| 1048 | card->write.state != CH_STATE_UP) | 1014 | card->write.state != CH_STATE_UP) |
| 1049 | return; | 1015 | return; |
| 1050 | |||
| 1051 | if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) | ||
| 1052 | kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); | ||
| 1053 | if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD)) | ||
| 1054 | kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD); | ||
| 1055 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) | 1016 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) |
| 1056 | kernel_thread(qeth_recover, (void *) card, SIGCHLD); | 1017 | kernel_thread(qeth_recover, (void *) card, SIGCHLD); |
| 1057 | } | 1018 | } |
| @@ -1074,7 +1035,7 @@ qeth_set_intial_options(struct qeth_card *card) | |||
| 1074 | card->options.layer2 = 1; | 1035 | card->options.layer2 = 1; |
| 1075 | else | 1036 | else |
| 1076 | card->options.layer2 = 0; | 1037 | card->options.layer2 = 0; |
| 1077 | card->options.performance_stats = 1; | 1038 | card->options.performance_stats = 0; |
| 1078 | } | 1039 | } |
| 1079 | 1040 | ||
| 1080 | /** | 1041 | /** |
| @@ -1613,8 +1574,6 @@ qeth_issue_next_read(struct qeth_card *card) | |||
| 1613 | return -ENOMEM; | 1574 | return -ENOMEM; |
| 1614 | } | 1575 | } |
| 1615 | qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE); | 1576 | qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE); |
| 1616 | wait_event(card->wait_q, | ||
| 1617 | atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0); | ||
| 1618 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); | 1577 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); |
| 1619 | rc = ccw_device_start(card->read.ccwdev, &card->read.ccw, | 1578 | rc = ccw_device_start(card->read.ccwdev, &card->read.ccw, |
| 1620 | (addr_t) iob, 0, 0); | 1579 | (addr_t) iob, 0, 0); |
| @@ -1635,6 +1594,7 @@ qeth_alloc_reply(struct qeth_card *card) | |||
| 1635 | reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC); | 1594 | reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC); |
| 1636 | if (reply){ | 1595 | if (reply){ |
| 1637 | atomic_set(&reply->refcnt, 1); | 1596 | atomic_set(&reply->refcnt, 1); |
| 1597 | atomic_set(&reply->received, 0); | ||
| 1638 | reply->card = card; | 1598 | reply->card = card; |
| 1639 | }; | 1599 | }; |
| 1640 | return reply; | 1600 | return reply; |
| @@ -1655,31 +1615,6 @@ qeth_put_reply(struct qeth_reply *reply) | |||
| 1655 | kfree(reply); | 1615 | kfree(reply); |
| 1656 | } | 1616 | } |
| 1657 | 1617 | ||
| 1658 | static void | ||
| 1659 | qeth_cmd_timeout(unsigned long data) | ||
| 1660 | { | ||
| 1661 | struct qeth_reply *reply, *list_reply, *r; | ||
| 1662 | unsigned long flags; | ||
| 1663 | |||
| 1664 | reply = (struct qeth_reply *) data; | ||
| 1665 | spin_lock_irqsave(&reply->card->lock, flags); | ||
| 1666 | list_for_each_entry_safe(list_reply, r, | ||
| 1667 | &reply->card->cmd_waiter_list, list) { | ||
| 1668 | if (reply == list_reply){ | ||
| 1669 | qeth_get_reply(reply); | ||
| 1670 | list_del_init(&reply->list); | ||
| 1671 | spin_unlock_irqrestore(&reply->card->lock, flags); | ||
| 1672 | reply->rc = -ETIME; | ||
| 1673 | reply->received = 1; | ||
| 1674 | wake_up(&reply->wait_q); | ||
| 1675 | qeth_put_reply(reply); | ||
| 1676 | return; | ||
| 1677 | } | ||
| 1678 | } | ||
| 1679 | spin_unlock_irqrestore(&reply->card->lock, flags); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | |||
| 1683 | static struct qeth_ipa_cmd * | 1618 | static struct qeth_ipa_cmd * |
| 1684 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | 1619 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) |
| 1685 | { | 1620 | { |
| @@ -1745,7 +1680,7 @@ qeth_clear_ipacmd_list(struct qeth_card *card) | |||
| 1745 | list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { | 1680 | list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { |
| 1746 | qeth_get_reply(reply); | 1681 | qeth_get_reply(reply); |
| 1747 | reply->rc = -EIO; | 1682 | reply->rc = -EIO; |
| 1748 | reply->received = 1; | 1683 | atomic_inc(&reply->received); |
| 1749 | list_del_init(&reply->list); | 1684 | list_del_init(&reply->list); |
| 1750 | wake_up(&reply->wait_q); | 1685 | wake_up(&reply->wait_q); |
| 1751 | qeth_put_reply(reply); | 1686 | qeth_put_reply(reply); |
| @@ -1814,7 +1749,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel, | |||
| 1814 | &card->cmd_waiter_list); | 1749 | &card->cmd_waiter_list); |
| 1815 | spin_unlock_irqrestore(&card->lock, flags); | 1750 | spin_unlock_irqrestore(&card->lock, flags); |
| 1816 | } else { | 1751 | } else { |
| 1817 | reply->received = 1; | 1752 | atomic_inc(&reply->received); |
| 1818 | wake_up(&reply->wait_q); | 1753 | wake_up(&reply->wait_q); |
| 1819 | } | 1754 | } |
| 1820 | qeth_put_reply(reply); | 1755 | qeth_put_reply(reply); |
| @@ -1858,7 +1793,7 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
| 1858 | int rc; | 1793 | int rc; |
| 1859 | unsigned long flags; | 1794 | unsigned long flags; |
| 1860 | struct qeth_reply *reply = NULL; | 1795 | struct qeth_reply *reply = NULL; |
| 1861 | struct timer_list timer; | 1796 | unsigned long timeout; |
| 1862 | 1797 | ||
| 1863 | QETH_DBF_TEXT(trace, 2, "sendctl"); | 1798 | QETH_DBF_TEXT(trace, 2, "sendctl"); |
| 1864 | 1799 | ||
| @@ -1873,21 +1808,20 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
| 1873 | reply->seqno = QETH_IDX_COMMAND_SEQNO; | 1808 | reply->seqno = QETH_IDX_COMMAND_SEQNO; |
| 1874 | else | 1809 | else |
| 1875 | reply->seqno = card->seqno.ipa++; | 1810 | reply->seqno = card->seqno.ipa++; |
| 1876 | init_timer(&timer); | ||
| 1877 | timer.function = qeth_cmd_timeout; | ||
| 1878 | timer.data = (unsigned long) reply; | ||
| 1879 | init_waitqueue_head(&reply->wait_q); | 1811 | init_waitqueue_head(&reply->wait_q); |
| 1880 | spin_lock_irqsave(&card->lock, flags); | 1812 | spin_lock_irqsave(&card->lock, flags); |
| 1881 | list_add_tail(&reply->list, &card->cmd_waiter_list); | 1813 | list_add_tail(&reply->list, &card->cmd_waiter_list); |
| 1882 | spin_unlock_irqrestore(&card->lock, flags); | 1814 | spin_unlock_irqrestore(&card->lock, flags); |
| 1883 | QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); | 1815 | QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); |
| 1884 | wait_event(card->wait_q, | 1816 | |
| 1885 | atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0); | 1817 | while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ; |
| 1886 | qeth_prepare_control_data(card, len, iob); | 1818 | qeth_prepare_control_data(card, len, iob); |
| 1819 | |||
| 1887 | if (IS_IPA(iob->data)) | 1820 | if (IS_IPA(iob->data)) |
| 1888 | timer.expires = jiffies + QETH_IPA_TIMEOUT; | 1821 | timeout = jiffies + QETH_IPA_TIMEOUT; |
| 1889 | else | 1822 | else |
| 1890 | timer.expires = jiffies + QETH_TIMEOUT; | 1823 | timeout = jiffies + QETH_TIMEOUT; |
| 1824 | |||
| 1891 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); | 1825 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); |
| 1892 | spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); | 1826 | spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); |
| 1893 | rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, | 1827 | rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, |
| @@ -1906,9 +1840,16 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
| 1906 | wake_up(&card->wait_q); | 1840 | wake_up(&card->wait_q); |
| 1907 | return rc; | 1841 | return rc; |
| 1908 | } | 1842 | } |
| 1909 | add_timer(&timer); | 1843 | while (!atomic_read(&reply->received)) { |
| 1910 | wait_event(reply->wait_q, reply->received); | 1844 | if (time_after(jiffies, timeout)) { |
| 1911 | del_timer_sync(&timer); | 1845 | spin_lock_irqsave(&reply->card->lock, flags); |
| 1846 | list_del_init(&reply->list); | ||
| 1847 | spin_unlock_irqrestore(&reply->card->lock, flags); | ||
| 1848 | reply->rc = -ETIME; | ||
| 1849 | atomic_inc(&reply->received); | ||
| 1850 | wake_up(&reply->wait_q); | ||
| 1851 | } | ||
| 1852 | }; | ||
| 1912 | rc = reply->rc; | 1853 | rc = reply->rc; |
| 1913 | qeth_put_reply(reply); | 1854 | qeth_put_reply(reply); |
| 1914 | return rc; | 1855 | return rc; |
| @@ -2466,32 +2407,17 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, | |||
| 2466 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); | 2407 | qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); |
| 2467 | } | 2408 | } |
| 2468 | 2409 | ||
| 2469 | static inline __u16 | 2410 | static inline void |
| 2470 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2411 | qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
| 2471 | struct qeth_hdr *hdr) | 2412 | struct qeth_hdr *hdr) |
| 2472 | { | 2413 | { |
| 2473 | unsigned short vlan_id = 0; | ||
| 2474 | #ifdef CONFIG_QETH_VLAN | ||
| 2475 | struct vlan_hdr *vhdr; | ||
| 2476 | #endif | ||
| 2477 | |||
| 2478 | skb->pkt_type = PACKET_HOST; | 2414 | skb->pkt_type = PACKET_HOST; |
| 2479 | skb->protocol = qeth_type_trans(skb, skb->dev); | 2415 | skb->protocol = qeth_type_trans(skb, skb->dev); |
| 2480 | if (card->options.checksum_type == NO_CHECKSUMMING) | 2416 | if (card->options.checksum_type == NO_CHECKSUMMING) |
| 2481 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 2417 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 2482 | else | 2418 | else |
| 2483 | skb->ip_summed = CHECKSUM_NONE; | 2419 | skb->ip_summed = CHECKSUM_NONE; |
| 2484 | #ifdef CONFIG_QETH_VLAN | ||
| 2485 | if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) { | ||
| 2486 | vhdr = (struct vlan_hdr *) skb->data; | ||
| 2487 | skb->protocol = | ||
| 2488 | __constant_htons(vhdr->h_vlan_encapsulated_proto); | ||
| 2489 | vlan_id = hdr->hdr.l2.vlan_id; | ||
| 2490 | skb_pull(skb, VLAN_HLEN); | ||
| 2491 | } | ||
| 2492 | #endif | ||
| 2493 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | 2420 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; |
| 2494 | return vlan_id; | ||
| 2495 | } | 2421 | } |
| 2496 | 2422 | ||
| 2497 | static inline __u16 | 2423 | static inline __u16 |
| @@ -2560,7 +2486,6 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
| 2560 | int offset; | 2486 | int offset; |
| 2561 | int rxrc; | 2487 | int rxrc; |
| 2562 | __u16 vlan_tag = 0; | 2488 | __u16 vlan_tag = 0; |
| 2563 | __u16 *vlan_addr; | ||
| 2564 | 2489 | ||
| 2565 | /* get first element of current buffer */ | 2490 | /* get first element of current buffer */ |
| 2566 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | 2491 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; |
| @@ -2571,7 +2496,7 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
| 2571 | &offset, &hdr))) { | 2496 | &offset, &hdr))) { |
| 2572 | skb->dev = card->dev; | 2497 | skb->dev = card->dev; |
| 2573 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) | 2498 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) |
| 2574 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); | 2499 | qeth_layer2_rebuild_skb(card, skb, hdr); |
| 2575 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) | 2500 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) |
| 2576 | vlan_tag = qeth_rebuild_skb(card, skb, hdr); | 2501 | vlan_tag = qeth_rebuild_skb(card, skb, hdr); |
| 2577 | else { /*in case of OSN*/ | 2502 | else { /*in case of OSN*/ |
| @@ -3968,13 +3893,22 @@ static inline struct sk_buff * | |||
| 3968 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, | 3893 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, |
| 3969 | struct qeth_hdr **hdr, int ipv) | 3894 | struct qeth_hdr **hdr, int ipv) |
| 3970 | { | 3895 | { |
| 3971 | struct sk_buff *new_skb; | 3896 | struct sk_buff *new_skb, *new_skb2; |
| 3972 | 3897 | ||
| 3973 | QETH_DBF_TEXT(trace, 6, "prepskb"); | 3898 | QETH_DBF_TEXT(trace, 6, "prepskb"); |
| 3974 | 3899 | new_skb = skb; | |
| 3975 | new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | 3900 | new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC); |
| 3976 | if (new_skb == NULL) | 3901 | if (!new_skb) |
| 3902 | return NULL; | ||
| 3903 | new_skb2 = qeth_realloc_headroom(card, new_skb, | ||
| 3904 | sizeof(struct qeth_hdr)); | ||
| 3905 | if (!new_skb2) { | ||
| 3906 | __qeth_free_new_skb(skb, new_skb); | ||
| 3977 | return NULL; | 3907 | return NULL; |
| 3908 | } | ||
| 3909 | if (new_skb != skb) | ||
| 3910 | __qeth_free_new_skb(new_skb2, new_skb); | ||
| 3911 | new_skb = new_skb2; | ||
| 3978 | *hdr = __qeth_prepare_skb(card, new_skb, ipv); | 3912 | *hdr = __qeth_prepare_skb(card, new_skb, ipv); |
| 3979 | if (*hdr == NULL) { | 3913 | if (*hdr == NULL) { |
| 3980 | __qeth_free_new_skb(skb, new_skb); | 3914 | __qeth_free_new_skb(skb, new_skb); |
| @@ -4844,9 +4778,11 @@ qeth_arp_query(struct qeth_card *card, char __user *udata) | |||
| 4844 | "(0x%x/%d)\n", | 4778 | "(0x%x/%d)\n", |
| 4845 | QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc), | 4779 | QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc), |
| 4846 | tmp, tmp); | 4780 | tmp, tmp); |
| 4847 | copy_to_user(udata, qinfo.udata, 4); | 4781 | if (copy_to_user(udata, qinfo.udata, 4)) |
| 4782 | rc = -EFAULT; | ||
| 4848 | } else { | 4783 | } else { |
| 4849 | copy_to_user(udata, qinfo.udata, qinfo.udata_len); | 4784 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) |
| 4785 | rc = -EFAULT; | ||
| 4850 | } | 4786 | } |
| 4851 | kfree(qinfo.udata); | 4787 | kfree(qinfo.udata); |
| 4852 | return rc; | 4788 | return rc; |
| @@ -4992,8 +4928,10 @@ qeth_snmp_command(struct qeth_card *card, char __user *udata) | |||
| 4992 | if (rc) | 4928 | if (rc) |
| 4993 | PRINT_WARN("SNMP command failed on %s: (0x%x)\n", | 4929 | PRINT_WARN("SNMP command failed on %s: (0x%x)\n", |
| 4994 | QETH_CARD_IFNAME(card), rc); | 4930 | QETH_CARD_IFNAME(card), rc); |
| 4995 | else | 4931 | else { |
| 4996 | copy_to_user(udata, qinfo.udata, qinfo.udata_len); | 4932 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) |
| 4933 | rc = -EFAULT; | ||
| 4934 | } | ||
| 4997 | 4935 | ||
| 4998 | kfree(ureq); | 4936 | kfree(ureq); |
| 4999 | kfree(qinfo.udata); | 4937 | kfree(qinfo.udata); |
| @@ -5544,12 +5482,10 @@ qeth_set_multicast_list(struct net_device *dev) | |||
| 5544 | qeth_add_multicast_ipv6(card); | 5482 | qeth_add_multicast_ipv6(card); |
| 5545 | #endif | 5483 | #endif |
| 5546 | out: | 5484 | out: |
| 5547 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 5485 | qeth_set_ip_addr_list(card); |
| 5548 | schedule_work(&card->kernel_thread_starter); | ||
| 5549 | if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) | 5486 | if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) |
| 5550 | return; | 5487 | return; |
| 5551 | if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) | 5488 | qeth_setadp_promisc_mode(card); |
| 5552 | schedule_work(&card->kernel_thread_starter); | ||
| 5553 | } | 5489 | } |
| 5554 | 5490 | ||
| 5555 | static int | 5491 | static int |
| @@ -6351,6 +6287,42 @@ static struct ethtool_ops qeth_ethtool_ops = { | |||
| 6351 | }; | 6287 | }; |
| 6352 | 6288 | ||
| 6353 | static int | 6289 | static int |
| 6290 | qeth_hard_header_parse(struct sk_buff *skb, unsigned char *haddr) | ||
| 6291 | { | ||
| 6292 | struct qeth_card *card; | ||
| 6293 | struct ethhdr *eth; | ||
| 6294 | |||
| 6295 | card = qeth_get_card_from_dev(skb->dev); | ||
| 6296 | if (card->options.layer2) | ||
| 6297 | goto haveheader; | ||
| 6298 | #ifdef CONFIG_QETH_IPV6 | ||
| 6299 | /* cause of the manipulated arp constructor and the ARP | ||
| 6300 | flag for OSAE devices we have some nasty exceptions */ | ||
| 6301 | if (card->info.type == QETH_CARD_TYPE_OSAE) { | ||
| 6302 | if (!card->options.fake_ll) { | ||
| 6303 | if ((skb->pkt_type==PACKET_OUTGOING) && | ||
| 6304 | (skb->protocol==ETH_P_IPV6)) | ||
| 6305 | goto haveheader; | ||
| 6306 | else | ||
| 6307 | return 0; | ||
| 6308 | } else { | ||
| 6309 | if ((skb->pkt_type==PACKET_OUTGOING) && | ||
| 6310 | (skb->protocol==ETH_P_IP)) | ||
| 6311 | return 0; | ||
| 6312 | else | ||
| 6313 | goto haveheader; | ||
| 6314 | } | ||
| 6315 | } | ||
| 6316 | #endif | ||
| 6317 | if (!card->options.fake_ll) | ||
| 6318 | return 0; | ||
| 6319 | haveheader: | ||
| 6320 | eth = eth_hdr(skb); | ||
| 6321 | memcpy(haddr, eth->h_source, ETH_ALEN); | ||
| 6322 | return ETH_ALEN; | ||
| 6323 | } | ||
| 6324 | |||
| 6325 | static int | ||
| 6354 | qeth_netdev_init(struct net_device *dev) | 6326 | qeth_netdev_init(struct net_device *dev) |
| 6355 | { | 6327 | { |
| 6356 | struct qeth_card *card; | 6328 | struct qeth_card *card; |
| @@ -6388,7 +6360,10 @@ qeth_netdev_init(struct net_device *dev) | |||
| 6388 | if (card->options.fake_ll && | 6360 | if (card->options.fake_ll && |
| 6389 | (qeth_get_netdev_flags(card) & IFF_NOARP)) | 6361 | (qeth_get_netdev_flags(card) & IFF_NOARP)) |
| 6390 | dev->hard_header = qeth_fake_header; | 6362 | dev->hard_header = qeth_fake_header; |
| 6391 | dev->hard_header_parse = NULL; | 6363 | if (dev->type == ARPHRD_IEEE802_TR) |
| 6364 | dev->hard_header_parse = NULL; | ||
| 6365 | else | ||
| 6366 | dev->hard_header_parse = qeth_hard_header_parse; | ||
| 6392 | dev->set_mac_address = qeth_layer2_set_mac_address; | 6367 | dev->set_mac_address = qeth_layer2_set_mac_address; |
| 6393 | dev->flags |= qeth_get_netdev_flags(card); | 6368 | dev->flags |= qeth_get_netdev_flags(card); |
| 6394 | if ((card->options.fake_broadcast) || | 6369 | if ((card->options.fake_broadcast) || |
| @@ -8235,8 +8210,7 @@ qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8235 | } | 8210 | } |
| 8236 | if (!qeth_add_ip(card, ipaddr)) | 8211 | if (!qeth_add_ip(card, ipaddr)) |
| 8237 | kfree(ipaddr); | 8212 | kfree(ipaddr); |
| 8238 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8213 | qeth_set_ip_addr_list(card); |
| 8239 | schedule_work(&card->kernel_thread_starter); | ||
| 8240 | return rc; | 8214 | return rc; |
| 8241 | } | 8215 | } |
| 8242 | 8216 | ||
| @@ -8264,8 +8238,7 @@ qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8264 | return; | 8238 | return; |
| 8265 | if (!qeth_delete_ip(card, ipaddr)) | 8239 | if (!qeth_delete_ip(card, ipaddr)) |
| 8266 | kfree(ipaddr); | 8240 | kfree(ipaddr); |
| 8267 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8241 | qeth_set_ip_addr_list(card); |
| 8268 | schedule_work(&card->kernel_thread_starter); | ||
| 8269 | } | 8242 | } |
| 8270 | 8243 | ||
| 8271 | /* | 8244 | /* |
| @@ -8308,8 +8281,7 @@ qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8308 | } | 8281 | } |
| 8309 | if (!qeth_add_ip(card, ipaddr)) | 8282 | if (!qeth_add_ip(card, ipaddr)) |
| 8310 | kfree(ipaddr); | 8283 | kfree(ipaddr); |
| 8311 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8284 | qeth_set_ip_addr_list(card); |
| 8312 | schedule_work(&card->kernel_thread_starter); | ||
| 8313 | return 0; | 8285 | return 0; |
| 8314 | } | 8286 | } |
| 8315 | 8287 | ||
| @@ -8337,8 +8309,7 @@ qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8337 | return; | 8309 | return; |
| 8338 | if (!qeth_delete_ip(card, ipaddr)) | 8310 | if (!qeth_delete_ip(card, ipaddr)) |
| 8339 | kfree(ipaddr); | 8311 | kfree(ipaddr); |
| 8340 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8312 | qeth_set_ip_addr_list(card); |
| 8341 | schedule_work(&card->kernel_thread_starter); | ||
| 8342 | } | 8313 | } |
| 8343 | 8314 | ||
| 8344 | /** | 8315 | /** |
| @@ -8380,8 +8351,7 @@ qeth_ip_event(struct notifier_block *this, | |||
| 8380 | default: | 8351 | default: |
| 8381 | break; | 8352 | break; |
| 8382 | } | 8353 | } |
| 8383 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8354 | qeth_set_ip_addr_list(card); |
| 8384 | schedule_work(&card->kernel_thread_starter); | ||
| 8385 | out: | 8355 | out: |
| 8386 | return NOTIFY_DONE; | 8356 | return NOTIFY_DONE; |
| 8387 | } | 8357 | } |
| @@ -8433,8 +8403,7 @@ qeth_ip6_event(struct notifier_block *this, | |||
| 8433 | default: | 8403 | default: |
| 8434 | break; | 8404 | break; |
| 8435 | } | 8405 | } |
| 8436 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8406 | qeth_set_ip_addr_list(card); |
| 8437 | schedule_work(&card->kernel_thread_starter); | ||
| 8438 | out: | 8407 | out: |
| 8439 | return NOTIFY_DONE; | 8408 | return NOTIFY_DONE; |
| 8440 | } | 8409 | } |
