aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2006-01-15 06:43:16 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-03-31 10:15:55 -0500
commit70294b468302fd7a0a99dad935c7ba5322989345 (patch)
treee54b0b7c85517ef717f3755e06ca08fbb0f5937e /drivers/char/pcmcia
parent4bbed5231468014b500b048d7370a1c6c349231a (diff)
[PATCH] pcmcia: remove unneeded Vcc pseudo setting
As we do not allow setting Vcc in the pcmcia core, and Vpp1 and Vpp2 can only be set to the same value, a lot of code can be streamlined. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/char/pcmcia')
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c7
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c7
-rw-r--r--drivers/char/pcmcia/synclink_cs.c7
3 files changed, 0 insertions, 21 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 870decbdf7ca..c996ae1375be 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1765,7 +1765,6 @@ static void cm4000_config(dev_link_t * link, int devno)
1765 struct cm4000_dev *dev; 1765 struct cm4000_dev *dev;
1766 tuple_t tuple; 1766 tuple_t tuple;
1767 cisparse_t parse; 1767 cisparse_t parse;
1768 config_info_t conf;
1769 u_char buf[64]; 1768 u_char buf[64];
1770 int fail_fn, fail_rc; 1769 int fail_fn, fail_rc;
1771 int rc; 1770 int rc;
@@ -1790,16 +1789,10 @@ static void cm4000_config(dev_link_t * link, int devno)
1790 fail_fn = ParseTuple; 1789 fail_fn = ParseTuple;
1791 goto cs_failed; 1790 goto cs_failed;
1792 } 1791 }
1793 if ((fail_rc =
1794 pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
1795 fail_fn = GetConfigurationInfo;
1796 goto cs_failed;
1797 }
1798 1792
1799 link->state |= DEV_CONFIG; 1793 link->state |= DEV_CONFIG;
1800 link->conf.ConfigBase = parse.config.base; 1794 link->conf.ConfigBase = parse.config.base;
1801 link->conf.Present = parse.config.rmask[0]; 1795 link->conf.Present = parse.config.rmask[0];
1802 link->conf.Vcc = conf.Vcc;
1803 1796
1804 link->io.BasePort2 = 0; 1797 link->io.BasePort2 = 0;
1805 link->io.NumPorts2 = 0; 1798 link->io.NumPorts2 = 0;
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 47f10c8b8886..94ecd0342b72 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -520,7 +520,6 @@ static void reader_config(dev_link_t *link, int devno)
520 struct reader_dev *dev; 520 struct reader_dev *dev;
521 tuple_t tuple; 521 tuple_t tuple;
522 cisparse_t parse; 522 cisparse_t parse;
523 config_info_t conf;
524 u_char buf[64]; 523 u_char buf[64];
525 int fail_fn, fail_rc; 524 int fail_fn, fail_rc;
526 int rc; 525 int rc;
@@ -546,16 +545,10 @@ static void reader_config(dev_link_t *link, int devno)
546 fail_fn = ParseTuple; 545 fail_fn = ParseTuple;
547 goto cs_failed; 546 goto cs_failed;
548 } 547 }
549 if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
550 != CS_SUCCESS) {
551 fail_fn = GetConfigurationInfo;
552 goto cs_failed;
553 }
554 548
555 link->state |= DEV_CONFIG; 549 link->state |= DEV_CONFIG;
556 link->conf.ConfigBase = parse.config.base; 550 link->conf.ConfigBase = parse.config.base;
557 link->conf.Present = parse.config.rmask[0]; 551 link->conf.Present = parse.config.rmask[0];
558 link->conf.Vcc = conf.Vcc;
559 552
560 link->io.BasePort2 = 0; 553 link->io.BasePort2 = 0;
561 link->io.NumPorts2 = 0; 554 link->io.NumPorts2 = 0;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index d3ea53a5a50f..a6cbd3239921 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -576,7 +576,6 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
576 link->irq.Handler = NULL; 576 link->irq.Handler = NULL;
577 577
578 link->conf.Attributes = 0; 578 link->conf.Attributes = 0;
579 link->conf.Vcc = 50;
580 link->conf.IntType = INT_MEMORY_AND_IO; 579 link->conf.IntType = INT_MEMORY_AND_IO;
581 580
582 link->handle = p_dev; 581 link->handle = p_dev;
@@ -604,7 +603,6 @@ static void mgslpc_config(dev_link_t *link)
604 cisparse_t parse; 603 cisparse_t parse;
605 int last_fn, last_ret; 604 int last_fn, last_ret;
606 u_char buf[64]; 605 u_char buf[64];
607 config_info_t conf;
608 cistpl_cftable_entry_t dflt = { 0 }; 606 cistpl_cftable_entry_t dflt = { 0 };
609 cistpl_cftable_entry_t *cfg; 607 cistpl_cftable_entry_t *cfg;
610 608
@@ -626,10 +624,6 @@ static void mgslpc_config(dev_link_t *link)
626 /* Configure card */ 624 /* Configure card */
627 link->state |= DEV_CONFIG; 625 link->state |= DEV_CONFIG;
628 626
629 /* Look up the current Vcc */
630 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
631 link->conf.Vcc = conf.Vcc;
632
633 /* get CIS configuration entry */ 627 /* get CIS configuration entry */
634 628
635 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 629 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -662,7 +656,6 @@ static void mgslpc_config(dev_link_t *link)
662 } 656 }
663 657
664 link->conf.Attributes = CONF_ENABLE_IRQ; 658 link->conf.Attributes = CONF_ENABLE_IRQ;
665 link->conf.Vcc = 50;
666 link->conf.IntType = INT_MEMORY_AND_IO; 659 link->conf.IntType = INT_MEMORY_AND_IO;
667 link->conf.ConfigIndex = 8; 660 link->conf.ConfigIndex = 8;
668 link->conf.Present = PRESENT_OPTION; 661 link->conf.Present = PRESENT_OPTION;
> 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852


































                                                                           









                                                                               








                                                           











                                                        
                                             


                                                                                         
                                                      






                                                     
                                              



                     



























                                                                          
                                             





                                                                            
                                                                     




















                                                                                  
                                               













                                                                        



































































































































                                                                                                      







































































































































































































































































































































                                                                                                 
                                              
                                                   


                              
                               




















                                                                                  








                                                                                          
                                          
 





























































                                                                               


                      























                                                                  
                                            












































































































                                                                               
/*
 *  generic_serial.c
 *
 *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
 *
 *  written for the SX serial driver.
 *     Contains the code that should be shared over all the serial drivers.
 *
 *  Credit for the idea to do it this way might go to Alan Cox. 
 *
 *
 *  Version 0.1 -- December, 1998. Initial version.
 *  Version 0.2 -- March, 1999.    Some more routines. Bugfixes. Etc.
 *  Version 0.5 -- August, 1999.   Some more fixes. Reformat for Linus.
 *
 *  BitWizard is actively maintaining this file. We sometimes find
 *  that someone submitted changes to this file. We really appreciate
 *  your help, but please submit changes through us. We're doing our
 *  best to be responsive.  -- REW
 * */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/mm.h>
#include <linux/generic_serial.h>
#include <linux/interrupt.h>
#include <linux/tty_flip.h>
#include <linux/delay.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>

#define DEBUG 

static int gs_debug;

#ifdef DEBUG
#define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
#else
#define gs_dprintk(f, str...) /* nothing */
#endif

#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __FUNCTION__)

#define RS_EVENT_WRITE_WAKEUP	1

module_param(gs_debug, int, 0644);


void gs_put_char(struct tty_struct * tty, unsigned char ch)
{
	struct gs_port *port;

	func_enter (); 

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	if (! (port->flags & ASYNC_INITIALIZED)) return;

	/* Take a lock on the serial tranmit buffer! */
	mutex_lock(& port->port_write_mutex);

	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
		mutex_unlock(&port->port_write_mutex);
		return;
	}

	port->xmit_buf[port->xmit_head++] = ch;
	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
	port->xmit_cnt++;  /* Characters in buffer */

	mutex_unlock(&port->port_write_mutex);
	func_exit ();
}


/*
> Problems to take into account are:
>       -1- Interrupts that empty part of the buffer.
>       -2- page faults on the access to userspace. 
>       -3- Other processes that are also trying to do a "write". 
*/

int gs_write(struct tty_struct * tty, 
                    const unsigned char *buf, int count)
{
	struct gs_port *port;
	int c, total = 0;
	int t;

	func_enter ();

	if (!tty) return 0;

	port = tty->driver_data;

	if (!port) return 0;

	if (! (port->flags & ASYNC_INITIALIZED))
		return 0;

	/* get exclusive "write" access to this port (problem 3) */
	/* This is not a spinlock because we can have a disk access (page 
		 fault) in copy_from_user */
	mutex_lock(& port->port_write_mutex);

	while (1) {

		c = count;
 
		/* This is safe because we "OWN" the "head". Noone else can 
		   change the "head": we own the port_write_mutex. */
		/* Don't overrun the end of the buffer */
		t = SERIAL_XMIT_SIZE - port->xmit_head;
		if (t < c) c = t;
 
		/* This is safe because the xmit_cnt can only decrease. This 
		   would increase "t", so we might copy too little chars. */
		/* Don't copy past the "head" of the buffer */
		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
		if (t < c) c = t;
 
		/* Can't copy more? break out! */
		if (c <= 0) break;

		memcpy (port->xmit_buf + port->xmit_head, buf, c);

		port -> xmit_cnt += c;
		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
		buf += c;
		count -= c;
		total += c;
	}
	mutex_unlock(& port->port_write_mutex);

	gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", 
	            (port->flags & GS_TX_INTEN)?"enabled": "disabled"); 

	if (port->xmit_cnt && 
	    !tty->stopped && 
	    !tty->hw_stopped &&
	    !(port->flags & GS_TX_INTEN)) {
		port->flags |= GS_TX_INTEN;
		port->rd->enable_tx_interrupts (port);
	}
	func_exit ();
	return total;
}



int gs_write_room(struct tty_struct * tty)
{
	struct gs_port *port = tty->driver_data;
	int ret;

	func_enter ();
	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
	if (ret < 0)
		ret = 0;
	func_exit ();
	return ret;
}


int gs_chars_in_buffer(struct tty_struct *tty)
{
	struct gs_port *port = tty->driver_data;
	func_enter ();

	func_exit ();
	return port->xmit_cnt;
}


static int gs_real_chars_in_buffer(struct tty_struct *tty)
{
	struct gs_port *port;
	func_enter ();

	if (!tty) return 0;
	port = tty->driver_data;

	if (!port->rd) return 0;
	if (!port->rd->chars_in_buffer) return 0;

	func_exit ();
	return port->xmit_cnt + port->rd->chars_in_buffer (port);
}


static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) 
{
	struct gs_port *port = ptr;
	unsigned long end_jiffies;
	int jiffies_to_transmit, charsleft = 0, rv = 0;
	int rcib;

	func_enter();

	gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port);
	if (port) {
		gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", 
		port->xmit_cnt, port->xmit_buf, port->tty);
	}

	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
		func_exit();
		return -EINVAL;  /* This is an error which we don't know how to handle. */
	}

	rcib = gs_real_chars_in_buffer(port->tty);

	if(rcib <= 0) {
		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
		func_exit();
		return rv;
	}
	/* stop trying: now + twice the time it would normally take +  seconds */
	if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;
	end_jiffies  = jiffies; 
	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
		end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0;
	end_jiffies += timeout;

	gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", 
		    jiffies, end_jiffies, end_jiffies-jiffies); 

	/* the expression is actually jiffies < end_jiffies, but that won't
	   work around the wraparound. Tricky eh? */
	while ((charsleft = gs_real_chars_in_buffer (port->tty)) &&
	        time_after (end_jiffies, jiffies)) {
		/* Units check: 
		   chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies!
		   check! */

		charsleft += 16; /* Allow 16 chars more to be transmitted ... */
		jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0;
		/*                                ^^^ Round up.... */
		if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1;

		gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies "
			    "(%d chars).\n", jiffies_to_transmit, charsleft); 

		msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit));
		if (signal_pending (current)) {
			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
			rv = -EINTR;
			break;
		}
	}

	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
	set_current_state (TASK_RUNNING);

	func_exit();
	return rv;
}



void gs_flush_buffer(struct tty_struct *tty)
{
	struct gs_port *port;
	unsigned long flags;

	func_enter ();

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	/* XXX Would the write semaphore do? */
	spin_lock_irqsave (&port->driver_lock, flags);
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	spin_unlock_irqrestore (&port->driver_lock, flags);

	tty_wakeup(tty);
	func_exit ();
}


void gs_flush_chars(struct tty_struct * tty)
{
	struct gs_port *port;

	func_enter ();

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
	    !port->xmit_buf) {
		func_exit ();
		return;
	}

	/* Beats me -- REW */
	port->flags |= GS_TX_INTEN;
	port->rd->enable_tx_interrupts (port);
	func_exit ();
}


void gs_stop(struct tty_struct * tty)
{
	struct gs_port *port;

	func_enter ();

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	if (port->xmit_cnt && 
	    port->xmit_buf && 
	    (port->flags & GS_TX_INTEN) ) {
		port->flags &= ~GS_TX_INTEN;
		port->rd->disable_tx_interrupts (port);
	}
	func_exit ();
}


void gs_start(struct tty_struct * tty)
{
	struct gs_port *port;

	if (!tty) return;

	port = tty->driver_data;

	if (!port) return;

	if (port->xmit_cnt && 
	    port->xmit_buf && 
	    !(port->flags & GS_TX_INTEN) ) {
		port->flags |= GS_TX_INTEN;
		port->rd->enable_tx_interrupts (port);
	}
	func_exit ();
}


static void gs_shutdown_port (struct gs_port *port)
{
	unsigned long flags;

	func_enter();
	
	if (!port) return;
	
	if (!(port->flags & ASYNC_INITIALIZED))
		return;

	spin_lock_irqsave(&port->driver_lock, flags);

	if (port->xmit_buf) {
		free_page((unsigned long) port->xmit_buf);
		port->xmit_buf = NULL;
	}

	if (port->tty)
		set_bit(TTY_IO_ERROR, &port->tty->flags);

	port->rd->shutdown_port (port);

	port->flags &= ~ASYNC_INITIALIZED;
	spin_unlock_irqrestore(&port->driver_lock, flags);

	func_exit();
}


void gs_hangup(struct tty_struct *tty)
{
	struct gs_port   *port;

	func_enter ();

	if (!tty) return;

	port = tty->driver_data;
	tty = port->tty;
	if (!tty) 
		return;

	gs_shutdown_port (port);
	port->flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
	port->tty = NULL;
	port->count = 0;

	wake_up_interruptible(&port->open_wait);
	func_exit ();
}


int gs_block_til_ready(void *port_, struct file * filp)
{
	struct gs_port *port = port_;
	DECLARE_WAITQUEUE(wait, current);
	int    retval;
	int    do_clocal = 0;
	int    CD;
	struct tty_struct *tty;
	unsigned long flags;

	func_enter ();

	if (!port) return 0;

	tty = port->tty;

	if (!tty) return 0;

	gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
	/*
	 * If the device is in the middle of being closed, then block
	 * until it's done, and then try again.
	 */
	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
		interruptible_sleep_on(&port->close_wait);
		if (port->flags & ASYNC_HUP_NOTIFY)
			return -EAGAIN;
		else
			return -ERESTARTSYS;
	}

	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 

	/*
	 * If non-blocking mode is set, or the port is not enabled,
	 * then make the check up front and then exit.
	 */
	if ((filp->f_flags & O_NONBLOCK) ||
	    (tty->flags & (1 << TTY_IO_ERROR))) {
		port->flags |= ASYNC_NORMAL_ACTIVE;
		return 0;
	}

	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
 
	if (C_CLOCAL(tty))
		do_clocal = 1;

	/*
	 * Block waiting for the carrier detect and the line to become
	 * free (i.e., not in use by the callout).  While we are in
	 * this loop, port->count is dropped by one, so that
	 * rs_close() knows when to free things.  We restore it upon
	 * exit, either normal or abnormal.
	 */
	retval = 0;

	add_wait_queue(&port->open_wait, &wait);

	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
	spin_lock_irqsave(&port->driver_lock, flags);
	if (!tty_hung_up_p(filp)) {
		port->count--;
	}
	spin_unlock_irqrestore(&port->driver_lock, flags);
	port->blocked_open++;
	while (1) {
		CD = port->rd->get_CD (port);
		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
		set_current_state (TASK_INTERRUPTIBLE);
		if (tty_hung_up_p(filp) ||
		    !(port->flags & ASYNC_INITIALIZED)) {
			if (port->flags & ASYNC_HUP_NOTIFY)
				retval = -EAGAIN;
			else
				retval = -ERESTARTSYS;
			break;
		}
		if (!(port->flags & ASYNC_CLOSING) &&
		    (do_clocal || CD))
			break;
		gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 
		(int)signal_pending (current), *(long*)(&current->blocked)); 
		if (signal_pending(current)) {
			retval = -ERESTARTSYS;
			break;
		}
		schedule();
	}
	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
		    port->blocked_open);
	set_current_state (TASK_RUNNING);
	remove_wait_queue(&port->open_wait, &wait);
	if (!tty_hung_up_p(filp)) {
		port->count++;
	}
	port->blocked_open--;
	if (retval)
		return retval;

	port->flags |= ASYNC_NORMAL_ACTIVE;
	func_exit ();
	return 0;
}			 


void gs_close(struct tty_struct * tty, struct file * filp)
{
	unsigned long flags;
	struct gs_port *port;
	
	func_enter ();

	if (!tty) return;

	port = (struct gs_port *) tty->driver_data;

	if (!port) return;

	if (!port->tty) {
		/* This seems to happen when this is called from vhangup. */
		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->tty is NULL\n");
		port->tty = tty;
	}

	spin_lock_irqsave(&port->driver_lock, flags);

	if (tty_hung_up_p(filp)) {
		spin_unlock_irqrestore(&port->driver_lock, flags);
		if (port->rd->hungup)
			port->rd->hungup (port);
		func_exit ();
		return;
	}

	if ((tty->count == 1) && (port->count != 1)) {
		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
		       " tty->count is 1, port count is %d\n", port, port->count);
		port->count = 1;
	}
	if (--port->count < 0) {
		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->count);
		port->count = 0;
	}

	if (port->count) {
		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->count);
		spin_unlock_irqrestore(&port->driver_lock, flags);
		func_exit ();
		return;
	}