2 * Thunderbolt Cactus Ridge driver - bus logic (NHI independent)
4 * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
7 #include <linux/slab.h>
8 #include <linux/errno.h>
9 #include <linux/delay.h>
14 /* hotplug handling */
16 struct tb_hotplug_event
{
17 struct work_struct work
;
25 * tb_handle_hotplug() - handle hotplug event
29 static void tb_handle_hotplug(struct work_struct
*work
)
31 struct tb_hotplug_event
*ev
= container_of(work
, typeof(*ev
), work
);
32 struct tb
*tb
= ev
->tb
;
33 mutex_lock(&tb
->lock
);
34 if (!tb
->hotplug_active
)
35 goto out
; /* during init, suspend or shutdown */
37 /* do nothing for now */
39 mutex_unlock(&tb
->lock
);
44 * tb_schedule_hotplug_handler() - callback function for the control channel
46 * Delegates to tb_handle_hotplug.
48 static void tb_schedule_hotplug_handler(void *data
, u64 route
, u8 port
,
52 struct tb_hotplug_event
*ev
= kmalloc(sizeof(*ev
), GFP_KERNEL
);
55 INIT_WORK(&ev
->work
, tb_handle_hotplug
);
60 queue_work(tb
->wq
, &ev
->work
);
64 * thunderbolt_shutdown_and_free() - shutdown everything
66 * Free all switches and the config channel.
68 * Used in the error path of thunderbolt_alloc_and_start.
70 void thunderbolt_shutdown_and_free(struct tb
*tb
)
72 mutex_lock(&tb
->lock
);
79 tb
->hotplug_active
= false; /* signal tb_handle_hotplug to quit */
81 /* allow tb_handle_hotplug to acquire the lock */
82 mutex_unlock(&tb
->lock
);
84 flush_workqueue(tb
->wq
);
85 destroy_workqueue(tb
->wq
);
88 mutex_destroy(&tb
->lock
);
93 * thunderbolt_alloc_and_start() - setup the thunderbolt bus
95 * Allocates a tb_cfg control channel, initializes the root switch, enables
96 * plug events and activates pci devices.
98 * Return: Returns NULL on error.
100 struct tb
*thunderbolt_alloc_and_start(struct tb_nhi
*nhi
)
104 BUILD_BUG_ON(sizeof(struct tb_regs_switch_header
) != 5 * 4);
105 BUILD_BUG_ON(sizeof(struct tb_regs_port_header
) != 8 * 4);
106 BUILD_BUG_ON(sizeof(struct tb_regs_hop
) != 2 * 4);
108 tb
= kzalloc(sizeof(*tb
), GFP_KERNEL
);
113 mutex_init(&tb
->lock
);
114 mutex_lock(&tb
->lock
);
116 tb
->wq
= alloc_ordered_workqueue("thunderbolt", 0);
120 tb
->ctl
= tb_ctl_alloc(tb
->nhi
, tb_schedule_hotplug_handler
, tb
);
124 * tb_schedule_hotplug_handler may be called as soon as the config
125 * channel is started. Thats why we have to hold the lock here.
127 tb_ctl_start(tb
->ctl
);
129 /* Allow tb_handle_hotplug to progress events */
130 tb
->hotplug_active
= true;
131 mutex_unlock(&tb
->lock
);
135 mutex_unlock(&tb
->lock
);
136 thunderbolt_shutdown_and_free(tb
);