Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ee2db684b4b92d138ee3b7326e69f4297cf4beca
Commit:     ee2db684b4b92d138ee3b7326e69f4297cf4beca
Parent:     2d36c16eb032239cb038ad875ecf83c545002461
Author:     Frank Blaschka <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 8 17:30:11 2007 +0100
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Tue Jan 9 02:18:32 2007 -0500

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/s390/net/qeth.h      |    2 +-
 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 53c358c..e95c281 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -710,7 +710,7 @@ struct qeth_reply {
        int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
        u32 seqno;
        unsigned long offset;
-       int received;
+       atomic_t received;
        int rc;
        void *param;
        struct qeth_card *card;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index bfc37ba..d2efa5f 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)
            channel->state == CH_STATE_UP)
                qeth_issue_next_read(card);
 
-       tasklet_schedule(&channel->irq_tasklet);
+       qeth_irq_tasklet((unsigned long)channel);
        return;
 out:
        wake_up(&card->wait_q);
@@ -951,40 +951,6 @@ qeth_do_run_thread(struct qeth_card *card, unsigned long 
thread)
 }
 
 static int
-qeth_register_ip_addresses(void *ptr)
-{
-       struct qeth_card *card;
-
-       card = (struct qeth_card *) ptr;
-       daemonize("qeth_reg_ip");
-       QETH_DBF_TEXT(trace,4,"regipth1");
-       if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))
-               return 0;
-       QETH_DBF_TEXT(trace,4,"regipth2");
-       qeth_set_ip_addr_list(card);
-       qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD);
-       return 0;
-}
-
-/*
- * Drive the SET_PROMISC_MODE thread
- */
-static int
-qeth_set_promisc_mode(void *ptr)
-{
-       struct qeth_card *card = (struct qeth_card *) ptr;
-
-       daemonize("qeth_setprm");
-       QETH_DBF_TEXT(trace,4,"setprm1");
-       if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
-               return 0;
-       QETH_DBF_TEXT(trace,4,"setprm2");
-       qeth_setadp_promisc_mode(card);
-       qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
-       return 0;
-}
-
-static int
 qeth_recover(void *ptr)
 {
        struct qeth_card *card;
@@ -1047,11 +1013,6 @@ qeth_start_kernel_thread(struct work_struct *work)
        if (card->read.state != CH_STATE_UP &&
            card->write.state != CH_STATE_UP)
                return;
-
-       if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
-               kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
-       if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
-               kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
        if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
                kernel_thread(qeth_recover, (void *) card, SIGCHLD);
 }
@@ -1613,8 +1574,6 @@ qeth_issue_next_read(struct qeth_card *card)
                return -ENOMEM;
        }
        qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
-       wait_event(card->wait_q,
-                  atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
        QETH_DBF_TEXT(trace, 6, "noirqpnd");
        rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
                              (addr_t) iob, 0, 0);
@@ -1635,6 +1594,7 @@ qeth_alloc_reply(struct qeth_card *card)
        reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
        if (reply){
                atomic_set(&reply->refcnt, 1);
+               atomic_set(&reply->received, 0);
                reply->card = card;
        };
        return reply;
@@ -1655,31 +1615,6 @@ qeth_put_reply(struct qeth_reply *reply)
                kfree(reply);
 }
 
-static void
-qeth_cmd_timeout(unsigned long data)
-{
-       struct qeth_reply *reply, *list_reply, *r;
-       unsigned long flags;
-
-       reply = (struct qeth_reply *) data;
-       spin_lock_irqsave(&reply->card->lock, flags);
-       list_for_each_entry_safe(list_reply, r,
-                                &reply->card->cmd_waiter_list, list) {
-               if (reply == list_reply){
-                       qeth_get_reply(reply);
-                       list_del_init(&reply->list);
-                       spin_unlock_irqrestore(&reply->card->lock, flags);
-                       reply->rc = -ETIME;
-                       reply->received = 1;
-                       wake_up(&reply->wait_q);
-                       qeth_put_reply(reply);
-                       return;
-               }
-       }
-       spin_unlock_irqrestore(&reply->card->lock, flags);
-}
-
-
 static struct qeth_ipa_cmd *
 qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
 {
@@ -1745,7 +1680,7 @@ qeth_clear_ipacmd_list(struct qeth_card *card)
        list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
                qeth_get_reply(reply);
                reply->rc = -EIO;
-               reply->received = 1;
+               atomic_inc(&reply->received);
                list_del_init(&reply->list);
                wake_up(&reply->wait_q);
                qeth_put_reply(reply);
@@ -1814,7 +1749,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
                                              &card->cmd_waiter_list);
                                spin_unlock_irqrestore(&card->lock, flags);
                        } else {
-                               reply->received = 1;
+                               atomic_inc(&reply->received);
                                wake_up(&reply->wait_q);
                        }
                        qeth_put_reply(reply);
@@ -1858,7 +1793,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
        int rc;
        unsigned long flags;
        struct qeth_reply *reply = NULL;
-       struct timer_list timer;
+       unsigned long timeout;
 
        QETH_DBF_TEXT(trace, 2, "sendctl");
 
@@ -1873,21 +1808,20 @@ qeth_send_control_data(struct qeth_card *card, int len,
                reply->seqno = QETH_IDX_COMMAND_SEQNO;
        else
                reply->seqno = card->seqno.ipa++;
-       init_timer(&timer);
-       timer.function = qeth_cmd_timeout;
-       timer.data = (unsigned long) reply;
        init_waitqueue_head(&reply->wait_q);
        spin_lock_irqsave(&card->lock, flags);
        list_add_tail(&reply->list, &card->cmd_waiter_list);
        spin_unlock_irqrestore(&card->lock, flags);
        QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
-       wait_event(card->wait_q,
-                  atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+
+       while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
        qeth_prepare_control_data(card, len, iob);
+
        if (IS_IPA(iob->data))
-               timer.expires = jiffies + QETH_IPA_TIMEOUT;
+               timeout = jiffies + QETH_IPA_TIMEOUT;
        else
-               timer.expires = jiffies + QETH_TIMEOUT;
+               timeout = jiffies + QETH_TIMEOUT;
+
        QETH_DBF_TEXT(trace, 6, "noirqpnd");
        spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
        rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1906,9 +1840,16 @@ qeth_send_control_data(struct qeth_card *card, int len,
                wake_up(&card->wait_q);
                return rc;
        }
-       add_timer(&timer);
-       wait_event(reply->wait_q, reply->received);
-       del_timer_sync(&timer);
+       while (!atomic_read(&reply->received)) {
+               if (time_after(jiffies, timeout)) {
+                       spin_lock_irqsave(&reply->card->lock, flags);
+                       list_del_init(&reply->list);
+                       spin_unlock_irqrestore(&reply->card->lock, flags);
+                       reply->rc = -ETIME;
+                       atomic_inc(&reply->received);
+                       wake_up(&reply->wait_q);
+               }
+       };
        rc = reply->rc;
        qeth_put_reply(reply);
        return rc;
@@ -5541,12 +5482,10 @@ qeth_set_multicast_list(struct net_device *dev)
        qeth_add_multicast_ipv6(card);
 #endif
 out:
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
        if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
                return;
-       if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_setadp_promisc_mode(card);
 }
 
 static int
@@ -8271,8 +8210,7 @@ qeth_add_vipa(struct qeth_card *card, enum 
qeth_prot_versions proto,
        }
        if (!qeth_add_ip(card, ipaddr))
                kfree(ipaddr);
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
        return rc;
 }
 
@@ -8300,8 +8238,7 @@ qeth_del_vipa(struct qeth_card *card, enum 
qeth_prot_versions proto,
                return;
        if (!qeth_delete_ip(card, ipaddr))
                kfree(ipaddr);
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
 }
 
 /*
@@ -8344,8 +8281,7 @@ qeth_add_rxip(struct qeth_card *card, enum 
qeth_prot_versions proto,
        }
        if (!qeth_add_ip(card, ipaddr))
                kfree(ipaddr);
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
        return 0;
 }
 
@@ -8373,8 +8309,7 @@ qeth_del_rxip(struct qeth_card *card, enum 
qeth_prot_versions proto,
                return;
        if (!qeth_delete_ip(card, ipaddr))
                kfree(ipaddr);
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
 }
 
 /**
@@ -8416,8 +8351,7 @@ qeth_ip_event(struct notifier_block *this,
        default:
                break;
        }
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
 out:
        return NOTIFY_DONE;
 }
@@ -8469,8 +8403,7 @@ qeth_ip6_event(struct notifier_block *this,
        default:
                break;
        }
-       if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
-               schedule_work(&card->kernel_thread_starter);
+       qeth_set_ip_addr_list(card);
 out:
        return NOTIFY_DONE;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to