mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 08:26:29 +00:00 
			
		
		
		
	 31c00fc15e
			
		
	
	
		31c00fc15e
		
	
	
	
	
		
			
			Create Documentation/blockdev/ sub-directory and populate it. Populate the Documentation/serial/ sub-directory. Move MSI-HOWTO.txt to Documentation/PCI/. Move ioctl-number.txt to Documentation/ioctl/. Update all relevant 00-INDEX files. Update all relevant Kconfig files and source files. Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
		
			
				
	
	
		
			293 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
 | |
| 			The Lockronomicon
 | |
| 
 | |
| Your guide to the ancient and twisted locking policies of the tty layer and
 | |
| the warped logic behind them. Beware all ye who read on.
 | |
| 
 | |
| FIXME: still need to work out the full set of BKL assumptions and document
 | |
| them so they can eventually be killed off.
 | |
| 
 | |
| 
 | |
| Line Discipline
 | |
| ---------------
 | |
| 
 | |
| Line disciplines are registered with tty_register_ldisc() passing the
 | |
| discipline number and the ldisc structure. At the point of registration the 
 | |
| discipline must be ready to use and it is possible it will get used before
 | |
| the call returns success. If the call returns an error then it won't get
 | |
| called. Do not re-use ldisc numbers as they are part of the userspace ABI
 | |
| and writing over an existing ldisc will cause demons to eat your computer.
 | |
| After the return the ldisc data has been copied so you may free your own 
 | |
| copy of the structure. You must not re-register over the top of the line
 | |
| discipline even with the same data or your computer again will be eaten by
 | |
| demons.
 | |
| 
 | |
| In order to remove a line discipline call tty_unregister_ldisc().
 | |
| In ancient times this always worked. In modern times the function will
 | |
| return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
 | |
| code manages the module counts this should not usually be a concern.
 | |
| 
 | |
| Heed this warning: the reference count field of the registered copies of the
 | |
| tty_ldisc structure in the ldisc table counts the number of lines using this
 | |
| discipline. The reference count of the tty_ldisc structure within a tty 
 | |
| counts the number of active users of the ldisc at this instant. In effect it
 | |
| counts the number of threads of execution within an ldisc method (plus those
 | |
| about to enter and exit although this detail matters not).
 | |
| 
 | |
| Line Discipline Methods
 | |
| -----------------------
 | |
| 
 | |
| TTY side interfaces:
 | |
| 
 | |
| open()		-	Called when the line discipline is attached to
 | |
| 			the terminal. No other call into the line
 | |
| 			discipline for this tty will occur until it
 | |
| 			completes successfully. Can sleep.
 | |
| 
 | |
| close()		-	This is called on a terminal when the line
 | |
| 			discipline is being unplugged. At the point of
 | |
| 			execution no further users will enter the
 | |
| 			ldisc code for this tty. Can sleep.
 | |
| 
 | |
| hangup()	-	Called when the tty line is hung up.
 | |
| 			The line discipline should cease I/O to the tty.
 | |
| 			No further calls into the ldisc code will occur.
 | |
| 			Can sleep.
 | |
| 
 | |
| write()		-	A process is writing data through the line
 | |
| 			discipline.  Multiple write calls are serialized
 | |
| 			by the tty layer for the ldisc.  May sleep. 
 | |
| 
 | |
| flush_buffer()	-	(optional) May be called at any point between
 | |
| 			open and close, and instructs the line discipline
 | |
| 			to empty its input buffer.
 | |
| 
 | |
| chars_in_buffer() -	(optional) Report the number of bytes in the input
 | |
| 			buffer.
 | |
| 
 | |
| set_termios()	-	(optional) Called on termios structure changes.
 | |
| 			The caller passes the old termios data and the
 | |
| 			current data is in the tty. Called under the
 | |
| 			termios semaphore so allowed to sleep. Serialized
 | |
| 			against itself only.
 | |
| 
 | |
| read()		-	Move data from the line discipline to the user.
 | |
| 			Multiple read calls may occur in parallel and the
 | |
| 			ldisc must deal with serialization issues. May 
 | |
| 			sleep.
 | |
| 
 | |
| poll()		-	Check the status for the poll/select calls. Multiple
 | |
| 			poll calls may occur in parallel. May sleep.
 | |
| 
 | |
| ioctl()		-	Called when an ioctl is handed to the tty layer
 | |
| 			that might be for the ldisc. Multiple ioctl calls
 | |
| 			may occur in parallel. May sleep. 
 | |
| 
 | |
| Driver Side Interfaces:
 | |
| 
 | |
| receive_buf()	-	Hand buffers of bytes from the driver to the ldisc
 | |
| 			for processing. Semantics currently rather
 | |
| 			mysterious 8(
 | |
| 
 | |
| write_wakeup()	-	May be called at any point between open and close.
 | |
| 			The TTY_DO_WRITE_WAKEUP flag indicates if a call
 | |
| 			is needed but always races versus calls. Thus the
 | |
| 			ldisc must be careful about setting order and to
 | |
| 			handle unexpected calls. Must not sleep.
 | |
| 
 | |
| 			The driver is forbidden from calling this directly
 | |
| 			from the ->write call from the ldisc as the ldisc
 | |
| 			is permitted to call the driver write method from
 | |
| 			this function. In such a situation defer it.
 | |
| 
 | |
| 
 | |
| Driver Access
 | |
| 
 | |
| Line discipline methods can call the following methods of the underlying
 | |
| hardware driver through the function pointers within the tty->driver
 | |
| structure:
 | |
| 
 | |
| write()			Write a block of characters to the tty device.
 | |
| 			Returns the number of characters accepted. The
 | |
| 			character buffer passed to this method is already
 | |
| 			in kernel space.
 | |
| 
 | |
| put_char()		Queues a character for writing to the tty device.
 | |
| 			If there is no room in the queue, the character is
 | |
| 			ignored.
 | |
| 
 | |
| flush_chars()		(Optional) If defined, must be called after
 | |
| 			queueing characters with put_char() in order to
 | |
| 			start transmission.
 | |
| 
 | |
| write_room()		Returns the numbers of characters the tty driver
 | |
| 			will accept for queueing to be written.
 | |
| 
 | |
| ioctl()			Invoke device specific ioctl.
 | |
| 			Expects data pointers to refer to userspace.
 | |
| 			Returns ENOIOCTLCMD for unrecognized ioctl numbers.
 | |
| 
 | |
| set_termios()		Notify the tty driver that the device's termios
 | |
| 			settings have changed. New settings are in
 | |
| 			tty->termios. Previous settings should be passed in
 | |
| 			the "old" argument.
 | |
| 
 | |
| 			The API is defined such that the driver should return
 | |
| 			the actual modes selected. This means that the
 | |
| 			driver function is responsible for modifying any
 | |
| 			bits in the request it cannot fulfill to indicate
 | |
| 			the actual modes being used. A device with no
 | |
| 			hardware capability for change (eg a USB dongle or
 | |
| 			virtual port) can provide NULL for this method.
 | |
| 
 | |
| throttle()		Notify the tty driver that input buffers for the
 | |
| 			line discipline are close to full, and it should
 | |
| 			somehow signal that no more characters should be
 | |
| 			sent to the tty.
 | |
| 
 | |
| unthrottle()		Notify the tty driver that characters can now be
 | |
| 			sent to the tty without fear of overrunning the
 | |
| 			input buffers of the line disciplines.
 | |
| 
 | |
| stop()			Ask the tty driver to stop outputting characters
 | |
| 			to the tty device.
 | |
| 
 | |
| start()			Ask the tty driver to resume sending characters
 | |
| 			to the tty device.
 | |
| 
 | |
| hangup()		Ask the tty driver to hang up the tty device.
 | |
| 
 | |
| break_ctl()		(Optional) Ask the tty driver to turn on or off
 | |
| 			BREAK status on the RS-232 port.  If state is -1,
 | |
| 			then the BREAK status should be turned on; if
 | |
| 			state is 0, then BREAK should be turned off.
 | |
| 			If this routine is not implemented, use ioctls
 | |
| 			TIOCSBRK / TIOCCBRK instead.
 | |
| 
 | |
| wait_until_sent()	Waits until the device has written out all of the
 | |
| 			characters in its transmitter FIFO.
 | |
| 
 | |
| send_xchar()		Send a high-priority XON/XOFF character to the device.
 | |
| 
 | |
| 
 | |
| Flags
 | |
| 
 | |
| Line discipline methods have access to tty->flags field containing the
 | |
| following interesting flags:
 | |
| 
 | |
| TTY_THROTTLED		Driver input is throttled. The ldisc should call
 | |
| 			tty->driver->unthrottle() in order to resume
 | |
| 			reception when it is ready to process more data.
 | |
| 
 | |
| TTY_DO_WRITE_WAKEUP	If set, causes the driver to call the ldisc's
 | |
| 			write_wakeup() method in order to resume
 | |
| 			transmission when it can accept more data
 | |
| 			to transmit.
 | |
| 
 | |
| TTY_IO_ERROR		If set, causes all subsequent userspace read/write
 | |
| 			calls on the tty to fail, returning -EIO.
 | |
| 
 | |
| TTY_OTHER_CLOSED	Device is a pty and the other side has closed.
 | |
| 
 | |
| TTY_NO_WRITE_SPLIT	Prevent driver from splitting up writes into
 | |
| 			smaller chunks.
 | |
| 
 | |
| 
 | |
| Locking
 | |
| 
 | |
| Callers to the line discipline functions from the tty layer are required to
 | |
| take line discipline locks. The same is true of calls from the driver side
 | |
| but not yet enforced.
 | |
| 
 | |
| Three calls are now provided
 | |
| 
 | |
| 	ldisc = tty_ldisc_ref(tty);
 | |
| 
 | |
| takes a handle to the line discipline in the tty and returns it. If no ldisc
 | |
| is currently attached or the ldisc is being closed and re-opened at this
 | |
| point then NULL is returned. While this handle is held the ldisc will not
 | |
| change or go away.
 | |
| 
 | |
| 	tty_ldisc_deref(ldisc)
 | |
| 
 | |
| Returns the ldisc reference and allows the ldisc to be closed. Returning the
 | |
| reference takes away your right to call the ldisc functions until you take
 | |
| a new reference.
 | |
| 
 | |
| 	ldisc = tty_ldisc_ref_wait(tty);
 | |
| 
 | |
| Performs the same function as tty_ldisc_ref except that it will wait for an
 | |
| ldisc change to complete and then return a reference to the new ldisc. 
 | |
| 
 | |
| While these functions are slightly slower than the old code they should have
 | |
| minimal impact as most receive logic uses the flip buffers and they only
 | |
| need to take a reference when they push bits up through the driver.
 | |
| 
 | |
| A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc 
 | |
| functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
 | |
| fail in this situation if used within these functions. Ldisc and driver
 | |
| code calling its own functions must be careful in this case. 
 | |
| 
 | |
| 
 | |
| Driver Interface
 | |
| ----------------
 | |
| 
 | |
| open()		-	Called when a device is opened. May sleep
 | |
| 
 | |
| close()		-	Called when a device is closed. At the point of
 | |
| 			return from this call the driver must make no 
 | |
| 			further ldisc calls of any kind. May sleep
 | |
| 
 | |
| write()		-	Called to write bytes to the device. May not
 | |
| 			sleep. May occur in parallel in special cases. 
 | |
| 			Because this includes panic paths drivers generally
 | |
| 			shouldn't try and do clever locking here.
 | |
| 
 | |
| put_char()	-	Stuff a single character onto the queue. The
 | |
| 			driver is guaranteed following up calls to
 | |
| 			flush_chars.
 | |
| 
 | |
| flush_chars()	-	Ask the kernel to write put_char queue
 | |
| 
 | |
| write_room()	-	Return the number of characters tht can be stuffed
 | |
| 			into the port buffers without overflow (or less).
 | |
| 			The ldisc is responsible for being intelligent
 | |
|  			about multi-threading of write_room/write calls
 | |
| 
 | |
| ioctl()		-	Called when an ioctl may be for the driver
 | |
| 
 | |
| set_termios()	-	Called on termios change, serialized against
 | |
| 			itself by a semaphore. May sleep.
 | |
| 
 | |
| set_ldisc()	-	Notifier for discipline change. At the point this 
 | |
| 			is done the discipline is not yet usable. Can now
 | |
| 			sleep (I think)
 | |
| 
 | |
| throttle()	-	Called by the ldisc to ask the driver to do flow
 | |
| 			control.  Serialization including with unthrottle
 | |
| 			is the job of the ldisc layer.
 | |
| 
 | |
| unthrottle()	-	Called by the ldisc to ask the driver to stop flow
 | |
| 			control.
 | |
| 
 | |
| stop()		-	Ldisc notifier to the driver to stop output. As with
 | |
| 			throttle the serializations with start() are down
 | |
| 			to the ldisc layer.
 | |
| 
 | |
| start()		-	Ldisc notifier to the driver to start output.
 | |
| 
 | |
| hangup()	-	Ask the tty driver to cause a hangup initiated
 | |
| 			from the host side. [Can sleep ??]
 | |
| 
 | |
| break_ctl()	-	Send RS232 break. Can sleep. Can get called in
 | |
| 			parallel, driver must serialize (for now), and
 | |
| 			with write calls.
 | |
| 
 | |
| wait_until_sent() -	Wait for characters to exit the hardware queue
 | |
| 			of the driver. Can sleep
 | |
| 
 | |
| send_xchar()	  -	Send XON/XOFF and if possible jump the queue with
 | |
| 			it in order to get fast flow control responses.
 | |
| 			Cannot sleep ??
 | |
| 
 |