|  | ======= | 
|  | Locking | 
|  | ======= | 
|  |  | 
|  | This file explains the locking and exclusion scheme used in the PCCARD | 
|  | and PCMCIA subsystems. | 
|  |  | 
|  |  | 
|  | A) Overview, Locking Hierarchy: | 
|  | =============================== | 
|  |  | 
|  | pcmcia_socket_list_rwsem | 
|  | - protects only the list of sockets | 
|  |  | 
|  | - skt_mutex | 
|  | - serializes card insert / ejection | 
|  |  | 
|  | - ops_mutex | 
|  | - serializes socket operation | 
|  |  | 
|  |  | 
|  | B) Exclusion | 
|  | ============ | 
|  |  | 
|  | The following functions and callbacks to struct pcmcia_socket must | 
|  | be called with "skt_mutex" held:: | 
|  |  | 
|  | socket_detect_change() | 
|  | send_event() | 
|  | socket_reset() | 
|  | socket_shutdown() | 
|  | socket_setup() | 
|  | socket_remove() | 
|  | socket_insert() | 
|  | socket_early_resume() | 
|  | socket_late_resume() | 
|  | socket_resume() | 
|  | socket_suspend() | 
|  |  | 
|  | struct pcmcia_callback	*callback | 
|  |  | 
|  | The following functions and callbacks to struct pcmcia_socket must | 
|  | be called with "ops_mutex" held:: | 
|  |  | 
|  | socket_reset() | 
|  | socket_setup() | 
|  |  | 
|  | struct pccard_operations	*ops | 
|  | struct pccard_resource_ops	*resource_ops; | 
|  |  | 
|  | Note that send_event() and `struct pcmcia_callback *callback` must not be | 
|  | called with "ops_mutex" held. | 
|  |  | 
|  |  | 
|  | C) Protection | 
|  | ============= | 
|  |  | 
|  | 1. Global Data: | 
|  | --------------- | 
|  | struct list_head	pcmcia_socket_list; | 
|  |  | 
|  | protected by pcmcia_socket_list_rwsem; | 
|  |  | 
|  |  | 
|  | 2. Per-Socket Data: | 
|  | ------------------- | 
|  | The resource_ops and their data are protected by ops_mutex. | 
|  |  | 
|  | The "main" struct pcmcia_socket is protected as follows (read-only fields | 
|  | or single-use fields not mentioned): | 
|  |  | 
|  | - by pcmcia_socket_list_rwsem:: | 
|  |  | 
|  | struct list_head	socket_list; | 
|  |  | 
|  | - by thread_lock:: | 
|  |  | 
|  | unsigned int		thread_events; | 
|  |  | 
|  | - by skt_mutex:: | 
|  |  | 
|  | u_int			suspended_state; | 
|  | void			(*tune_bridge); | 
|  | struct pcmcia_callback	*callback; | 
|  | int			resume_status; | 
|  |  | 
|  | - by ops_mutex:: | 
|  |  | 
|  | socket_state_t		socket; | 
|  | u_int			state; | 
|  | u_short			lock_count; | 
|  | pccard_mem_map		cis_mem; | 
|  | void __iomem 		*cis_virt; | 
|  | struct { }		irq; | 
|  | io_window_t		io[]; | 
|  | pccard_mem_map		win[]; | 
|  | struct list_head	cis_cache; | 
|  | size_t			fake_cis_len; | 
|  | u8			*fake_cis; | 
|  | u_int			irq_mask; | 
|  | void 			(*zoom_video); | 
|  | int 			(*power_hook); | 
|  | u8			resource...; | 
|  | struct list_head	devices_list; | 
|  | u8			device_count; | 
|  | struct 			pcmcia_state; | 
|  |  | 
|  |  | 
|  | 3. Per PCMCIA-device Data: | 
|  | -------------------------- | 
|  |  | 
|  | The "main" struct pcmcia_device is protected as follows (read-only fields | 
|  | or single-use fields not mentioned): | 
|  |  | 
|  |  | 
|  | - by pcmcia_socket->ops_mutex:: | 
|  |  | 
|  | struct list_head	socket_device_list; | 
|  | struct config_t		*function_config; | 
|  | u16			_irq:1; | 
|  | u16			_io:1; | 
|  | u16			_win:4; | 
|  | u16			_locked:1; | 
|  | u16			allow_func_id_match:1; | 
|  | u16			suspended:1; | 
|  | u16			_removed:1; | 
|  |  | 
|  | - by the PCMCIA driver:: | 
|  |  | 
|  | io_req_t		io; | 
|  | irq_req_t		irq; | 
|  | config_req_t		conf; | 
|  | window_handle_t		win; |