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;