From patchwork Fri Mar 19 08:39:33 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: christian pellegrin X-Patchwork-Id: 86900 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2J8g9nV004887 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 19 Mar 2010 08:42:47 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-1.v29.ch3.sourceforge.com) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NsXmS-0004b6-S9; Fri, 19 Mar 2010 08:42:08 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.124] helo=mx.sourceforge.net) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NsXmQ-0004ab-Hu for spi-devel-general@lists.sourceforge.net; Fri, 19 Mar 2010 08:42:06 +0000 Received-SPF: pass (sfi-mx-4.v28.ch3.sourceforge.com: domain of gmail.com designates 209.85.221.180 as permitted sender) client-ip=209.85.221.180; envelope-from=chripell@gmail.com; helo=mail-qy0-f180.google.com; Received: from mail-qy0-f180.google.com ([209.85.221.180]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NsXmO-0001sE-A4 for spi-devel-general@lists.sourceforge.net; Fri, 19 Mar 2010 08:42:06 +0000 Received: by qyk10 with SMTP id 10so1764154qyk.6 for ; Fri, 19 Mar 2010 01:41:58 -0700 (PDT) Received: by 10.224.140.132 with SMTP id i4mr1120415qau.375.1268988117797; Fri, 19 Mar 2010 01:41:57 -0700 (PDT) Received: from localhost (host126-57-dynamic.4-87-r.retail.telecomitalia.it [87.4.57.126]) by mx.google.com with ESMTPS id 22sm655945qyk.14.2010.03.19.01.41.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 19 Mar 2010 01:41:57 -0700 (PDT) From: Christian Pellegrin To: feng.tang@intel.com, akpm@linux-foundation.org, greg@kroah.com, david-b@pacbell.net, grant.likely@secretlab.ca, alan@lxorguk.ukuu.org.uk, spi-devel-general@lists.sourceforge.net, linux-serial@vger.kernel.org Date: Fri, 19 Mar 2010 09:39:33 +0100 Message-Id: <1268987973-22719-1-git-send-email-chripell@fsfe.org> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: References: X-Spam-Score: -1.0 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_PASS SPF: sender matches SPF record -0.0 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.0 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.5 AWL AWL: From: address is in the auto white-list X-Headers-End: 1NsXmO-0001sE-A4 Cc: Christian Pellegrin Subject: [spi-devel-general] [PATCH 2/3] max3100: moved to threaded interrupt X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: spi-devel-general-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 19 Mar 2010 08:42:47 +0000 (UTC) diff --git a/drivers/serial/max3100.c b/drivers/serial/max3100.c index 3c30c56..0c972c6 100644 --- a/drivers/serial/max3100.c +++ b/drivers/serial/max3100.c @@ -45,7 +45,9 @@ #include #include #include -#include +#include +#include +#include #include @@ -113,18 +115,15 @@ struct max3100_port { int irq; /* irq assigned to the max3100 */ + /* the workqueue is needed because we cannot schedule + a threaded interrupt during PM + */ + struct work_struct resume_work; + int minor; /* minor number */ int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */ int loopback; /* 1 if we are in loopback mode */ - /* for handling irqs: need workqueue since we do spi_sync */ - struct workqueue_struct *workqueue; - struct work_struct work; - /* set to 1 to make the workhandler exit as soon as possible */ - int force_end_work; - /* need to know we are suspending to avoid deadlock on workqueue */ - int suspending; - /* hook for suspending MAX3100 via dedicated pin */ void (*max3100_hw_suspend) (int suspend); @@ -171,13 +170,12 @@ static void max3100_calc_parity(struct max3100_port *s, u16 *c) *c |= max3100_do_parity(s, *c) << 8; } -static void max3100_work(struct work_struct *w); - -static void max3100_dowork(struct max3100_port *s) +static void max3100_resume_work(struct work_struct *w) { - if (!s->force_end_work && !work_pending(&s->work) && - !freezing(current) && !s->suspending) - queue_work(s->workqueue, &s->work); + struct max3100_port *s = container_of(w, struct max3100_port, + resume_work); + + raise_threaded_irq(s->irq); } static void max3100_timeout(unsigned long data) @@ -185,7 +183,7 @@ static void max3100_timeout(unsigned long data) struct max3100_port *s = (struct max3100_port *)data; if (s->port.state) { - max3100_dowork(s); + raise_threaded_irq(s->irq); mod_timer(&s->timer, jiffies + s->poll_time); } } @@ -255,9 +253,9 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx) return ret; } -static void max3100_work(struct work_struct *w) +static irqreturn_t max3100_ist(int irq, void *dev_id) { - struct max3100_port *s = container_of(w, struct max3100_port, work); + struct max3100_port *s = dev_id; int rxchars; u16 tx, rx; int conf, cconf, rts, crts; @@ -314,23 +312,14 @@ static void max3100_work(struct work_struct *w) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&s->port); - } while (!s->force_end_work && - !freezing(current) && + } while (!kthread_should_stop() && ((rx & MAX3100_R) || (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)))); if (rxchars > 0 && s->port.state->port.tty != NULL) tty_flip_buffer_push(s->port.state->port.tty); -} - -static irqreturn_t max3100_irq(int irqno, void *dev_id) -{ - struct max3100_port *s = dev_id; - - dev_dbg(&s->spi->dev, "%s\n", __func__); - max3100_dowork(s); return IRQ_HANDLED; } @@ -353,7 +342,7 @@ static void max3100_start_tx(struct uart_port *port) dev_dbg(&s->spi->dev, "%s\n", __func__); - max3100_dowork(s); + raise_threaded_irq(s->irq); } static void max3100_stop_rx(struct uart_port *port) @@ -369,7 +358,7 @@ static void max3100_stop_rx(struct uart_port *port) s->conf &= ~MAX3100_RM; s->conf_commit = 1; spin_unlock(&s->conf_lock); - max3100_dowork(s); + raise_threaded_irq(s->irq); } static unsigned int max3100_tx_empty(struct uart_port *port) @@ -381,7 +370,7 @@ static unsigned int max3100_tx_empty(struct uart_port *port) dev_dbg(&s->spi->dev, "%s\n", __func__); /* may not be truly up-to-date */ - max3100_dowork(s); + raise_threaded_irq(s->irq); return s->tx_empty; } @@ -394,7 +383,7 @@ static unsigned int max3100_get_mctrl(struct uart_port *port) dev_dbg(&s->spi->dev, "%s\n", __func__); /* may not be truly up-to-date */ - max3100_dowork(s); + raise_threaded_irq(s->irq); /* always assert DCD and DSR since these lines are not wired */ return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR; } @@ -414,7 +403,7 @@ static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl) if (s->rts != rts) { s->rts = rts; s->rts_commit = 1; - max3100_dowork(s); + raise_threaded_irq(s->irq); } spin_unlock(&s->conf_lock); } @@ -528,7 +517,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, MAX3100_STATUS_PE | MAX3100_STATUS_FE | MAX3100_STATUS_OE; - /* we are sending char from a workqueue so enable */ + /* we are sending char from a threded irq so enable */ s->port.state->port.tty->low_latency = 1; if (s->poll_time > 0) @@ -541,7 +530,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, s->conf_commit = 1; s->parity = parity; spin_unlock(&s->conf_lock); - max3100_dowork(s); + raise_threaded_irq(s->irq); if (UART_ENABLE_MS(&s->port, termios->c_cflag)) max3100_enable_ms(&s->port); @@ -555,19 +544,11 @@ static void max3100_shutdown(struct uart_port *port) dev_dbg(&s->spi->dev, "%s\n", __func__); - if (s->suspending) - return; - - s->force_end_work = 1; - if (s->poll_time > 0) del_timer_sync(&s->timer); - if (s->workqueue) { - flush_workqueue(s->workqueue); - destroy_workqueue(s->workqueue); - s->workqueue = NULL; - } + flush_work(&s->resume_work); + if (s->irq) free_irq(s->irq, s); @@ -587,7 +568,6 @@ static int max3100_startup(struct uart_port *port) struct max3100_port *s = container_of(port, struct max3100_port, port); - char b[12]; dev_dbg(&s->spi->dev, "%s\n", __func__); @@ -595,27 +575,15 @@ static int max3100_startup(struct uart_port *port) s->baud = s->crystal ? 230400 : 115200; s->rx_enabled = 1; - if (s->suspending) - return 0; - - s->force_end_work = 0; s->parity = 0; s->rts = 0; - sprintf(b, "max3100-%d", s->minor); - s->workqueue = create_freezeable_workqueue(b); - if (!s->workqueue) { - dev_warn(&s->spi->dev, "cannot create workqueue\n"); - return -EBUSY; - } - INIT_WORK(&s->work, max3100_work); + INIT_WORK(&s->resume_work, max3100_resume_work); - if (request_irq(s->irq, max3100_irq, + if (request_threaded_irq(s->irq, NULL, max3100_ist, IRQF_TRIGGER_FALLING, "max3100", s) < 0) { - dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq); + dev_err(&s->spi->dev, "cannot allocate irq %d\n", s->irq); s->irq = 0; - destroy_workqueue(s->workqueue); - s->workqueue = NULL; return -EBUSY; } @@ -628,7 +596,7 @@ static int max3100_startup(struct uart_port *port) if (s->max3100_hw_suspend) s->max3100_hw_suspend(0); s->conf_commit = 1; - max3100_dowork(s); + raise_threaded_irq(s->irq); /* wait for clock to settle */ msleep(50); @@ -857,9 +825,6 @@ static int max3100_suspend(struct spi_device *spi, pm_message_t state) disable_irq(s->irq); - s->suspending = 1; - uart_suspend_port(&max3100_uart_driver, &s->port); - if (s->max3100_hw_suspend) s->max3100_hw_suspend(1); else { @@ -880,14 +845,11 @@ static int max3100_resume(struct spi_device *spi) if (s->max3100_hw_suspend) s->max3100_hw_suspend(0); - uart_resume_port(&max3100_uart_driver, &s->port); - s->suspending = 0; enable_irq(s->irq); - + /* must reconfigure if power was cut-off the chip during suspend */ s->conf_commit = 1; - if (s->workqueue) - max3100_dowork(s); + schedule_work(&s->resume_work); return 0; }