diff options
| author | Frank Blaschka <Frank.Blaschka@de.ibm.com> | 2007-01-08 11:30:11 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-01-09 02:18:32 -0500 |
| commit | ee2db684b4b92d138ee3b7326e69f4297cf4beca (patch) | |
| tree | 3fa3a0c3067f6d6f3534b9c6af17bea230bbdc8f | |
| parent | 2d36c16eb032239cb038ad875ecf83c545002461 (diff) | |
s390: qeth driver fixes: atomic context fixups
- qeth device functions were not callable
in atomic context due to usage of wait_event_xxx operations in qeth.
"schedule while atomic" message appeared and kernel dumped when
removing slave from bond device.
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/s390/net/qeth.h | 2 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_main.c | 125 |
2 files changed, 30 insertions, 97 deletions
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 53c358c7d368..e95c281f1e36 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
| @@ -710,7 +710,7 @@ struct qeth_reply { | |||
| 710 | int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long); | 710 | int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long); |
| 711 | u32 seqno; | 711 | u32 seqno; |
| 712 | unsigned long offset; | 712 | unsigned long offset; |
| 713 | int received; | 713 | atomic_t received; |
| 714 | int rc; | 714 | int rc; |
| 715 | void *param; | 715 | void *param; |
| 716 | struct qeth_card *card; | 716 | struct qeth_card *card; |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index bfc37bae19bc..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 | } |
| @@ -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; |
| @@ -5541,12 +5482,10 @@ qeth_set_multicast_list(struct net_device *dev) | |||
| 5541 | qeth_add_multicast_ipv6(card); | 5482 | qeth_add_multicast_ipv6(card); |
| 5542 | #endif | 5483 | #endif |
| 5543 | out: | 5484 | out: |
| 5544 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 5485 | qeth_set_ip_addr_list(card); |
| 5545 | schedule_work(&card->kernel_thread_starter); | ||
| 5546 | if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) | 5486 | if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) |
| 5547 | return; | 5487 | return; |
| 5548 | if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) | 5488 | qeth_setadp_promisc_mode(card); |
| 5549 | schedule_work(&card->kernel_thread_starter); | ||
| 5550 | } | 5489 | } |
| 5551 | 5490 | ||
| 5552 | static int | 5491 | static int |
| @@ -8271,8 +8210,7 @@ qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8271 | } | 8210 | } |
| 8272 | if (!qeth_add_ip(card, ipaddr)) | 8211 | if (!qeth_add_ip(card, ipaddr)) |
| 8273 | kfree(ipaddr); | 8212 | kfree(ipaddr); |
| 8274 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8213 | qeth_set_ip_addr_list(card); |
| 8275 | schedule_work(&card->kernel_thread_starter); | ||
| 8276 | return rc; | 8214 | return rc; |
| 8277 | } | 8215 | } |
| 8278 | 8216 | ||
| @@ -8300,8 +8238,7 @@ qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8300 | return; | 8238 | return; |
| 8301 | if (!qeth_delete_ip(card, ipaddr)) | 8239 | if (!qeth_delete_ip(card, ipaddr)) |
| 8302 | kfree(ipaddr); | 8240 | kfree(ipaddr); |
| 8303 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8241 | qeth_set_ip_addr_list(card); |
| 8304 | schedule_work(&card->kernel_thread_starter); | ||
| 8305 | } | 8242 | } |
| 8306 | 8243 | ||
| 8307 | /* | 8244 | /* |
| @@ -8344,8 +8281,7 @@ qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8344 | } | 8281 | } |
| 8345 | if (!qeth_add_ip(card, ipaddr)) | 8282 | if (!qeth_add_ip(card, ipaddr)) |
| 8346 | kfree(ipaddr); | 8283 | kfree(ipaddr); |
| 8347 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8284 | qeth_set_ip_addr_list(card); |
| 8348 | schedule_work(&card->kernel_thread_starter); | ||
| 8349 | return 0; | 8285 | return 0; |
| 8350 | } | 8286 | } |
| 8351 | 8287 | ||
| @@ -8373,8 +8309,7 @@ qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
| 8373 | return; | 8309 | return; |
| 8374 | if (!qeth_delete_ip(card, ipaddr)) | 8310 | if (!qeth_delete_ip(card, ipaddr)) |
| 8375 | kfree(ipaddr); | 8311 | kfree(ipaddr); |
| 8376 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8312 | qeth_set_ip_addr_list(card); |
| 8377 | schedule_work(&card->kernel_thread_starter); | ||
| 8378 | } | 8313 | } |
| 8379 | 8314 | ||
| 8380 | /** | 8315 | /** |
| @@ -8416,8 +8351,7 @@ qeth_ip_event(struct notifier_block *this, | |||
| 8416 | default: | 8351 | default: |
| 8417 | break; | 8352 | break; |
| 8418 | } | 8353 | } |
| 8419 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8354 | qeth_set_ip_addr_list(card); |
| 8420 | schedule_work(&card->kernel_thread_starter); | ||
| 8421 | out: | 8355 | out: |
| 8422 | return NOTIFY_DONE; | 8356 | return NOTIFY_DONE; |
| 8423 | } | 8357 | } |
| @@ -8469,8 +8403,7 @@ qeth_ip6_event(struct notifier_block *this, | |||
| 8469 | default: | 8403 | default: |
| 8470 | break; | 8404 | break; |
| 8471 | } | 8405 | } |
| 8472 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 8406 | qeth_set_ip_addr_list(card); |
| 8473 | schedule_work(&card->kernel_thread_starter); | ||
| 8474 | out: | 8407 | out: |
| 8475 | return NOTIFY_DONE; | 8408 | return NOTIFY_DONE; |
| 8476 | } | 8409 | } |
