| ======= | |
| 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; |