Skip to content

Commit 3348acc

Browse files
pcercueiQuzarDC
authored andcommitted
maple: Fix race between driver attach and vblank irq
The device at unit 0 is probed using a shared frame dedicated to device detection; devices at unit > 0 are probed using the frame of the unit 0. This means that as soon as a unit 0 device is registered, its frame can be used to auto-detect itself (if previously unplugged) or its children. Therefore, prior to registering a unit 0 device into the device table, we must ensure that all fields have been properly initialized, or we will race with the vblank interrupt handler. Signed-off-by: Paul Cercueil <[email protected]>
1 parent 0e0205c commit 3348acc

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

kernel/arch/dreamcast/hardware/maple/maple_driver.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ int maple_driver_attach(maple_frame_t *det) {
7373
maple_devinfo_t *devinfo;
7474
maple_device_t *dev = maple_state.ports[det->dst_port].units[det->dst_unit];
7575
bool attached = false;
76+
bool dev_allocated = false;
7677

7778
/* Resolve some pointers first */
7879
resp = (maple_response_t *)det->recv_buf;
@@ -89,23 +90,28 @@ int maple_driver_attach(maple_frame_t *det) {
8990
if(!dev)
9091
return 1;
9192

92-
maple_state.ports[det->dst_port].units[det->dst_unit] = dev;
93-
9493
/* Add the basics for the initial version of the struct */
9594
dev->port = det->dst_port;
9695
dev->unit = det->dst_unit;
9796
dev->frame.state = MAPLE_FRAME_VACANT;
97+
dev_allocated = true;
9898
}
9999

100100
memcpy(&dev->info, devinfo, sizeof(maple_devinfo_t));
101101

102102
/* Now lets allocate a new status buffer */
103103
if(i->status_size && !dev->status) {
104104
dev->status = calloc(1, i->status_size);
105-
if(!dev->status)
105+
if(!dev->status) {
106+
if(dev_allocated)
107+
free(dev);
106108
return 1;
109+
}
107110
}
108111

112+
if(dev_allocated)
113+
maple_state.ports[det->dst_port].units[det->dst_unit] = dev;
114+
109115
if(!i->status_size || dev->status) {
110116
/* Try to attach if we need to then break out. */
111117
if(!(i->attach) || (i->attach(i, dev) >= 0)) {

0 commit comments

Comments
 (0)