Currently the bitbang_i2c_init() function allocates a
bitbang_i2c_interface struct which it returns. This is unfortunate
because it means that if the function is used from a DeviceState
init method then the memory will be leaked by an "init then delete"
cycle, as used by the qmp/hmp commands that list device properties.
Since three out of four of the uses of this function are in
device init methods, switch the function to do an in-place
initialization of a struct that can be embedded in the
device state struct of the caller.
This fixes LeakSanitizer leak warnings that have appeared in the
patchew configuration (which only tries to run the sanitizers
for the x86_64-softmmu target) now that we use the bitbang-i2c
code in an x86-64 config.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: BALATON Zoltan <balaton@eik.bme.hu>
Tested-by: BALATON Zoltan <balaton@eik.bme.hu>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id:
20190702163844.20458-1-peter.maydell@linaro.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
break;
case GPIO_DVI_DDC:
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
- s->regs.gpio_dvi_ddc = ati_i2c(s->bbi2c, data, 0);
+ s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0);
}
break;
case GPIO_MONID ... GPIO_MONID + 3:
*/
if ((s->regs.gpio_monid & BIT(25)) &&
addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) {
- s->regs.gpio_monid = ati_i2c(s->bbi2c, s->regs.gpio_monid, 1);
+ s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1);
}
}
break;
/* ddc, edid */
I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc");
- s->bbi2c = bitbang_i2c_init(i2cbus);
+ bitbang_i2c_init(&s->bbi2c, i2cbus);
I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC));
i2c_set_slave_address(i2cddc, 0x50);
ATIVGAState *s = ATI_VGA(dev);
graphic_console_close(s->vga.con);
- g_free(s->bbi2c);
}
static Property ati_vga_properties[] = {
uint16_t cursor_size;
uint32_t cursor_offset;
QEMUCursor *cursor;
- bitbang_i2c_interface *bbi2c;
+ bitbang_i2c_interface bbi2c;
MemoryRegion io;
MemoryRegion mm;
ATIVGARegs regs;
#define DPRINTF(fmt, ...) do {} while(0)
#endif
-typedef enum bitbang_i2c_state {
- STOPPED = 0,
- SENDING_BIT7,
- SENDING_BIT6,
- SENDING_BIT5,
- SENDING_BIT4,
- SENDING_BIT3,
- SENDING_BIT2,
- SENDING_BIT1,
- SENDING_BIT0,
- WAITING_FOR_ACK,
- RECEIVING_BIT7,
- RECEIVING_BIT6,
- RECEIVING_BIT5,
- RECEIVING_BIT4,
- RECEIVING_BIT3,
- RECEIVING_BIT2,
- RECEIVING_BIT1,
- RECEIVING_BIT0,
- SENDING_ACK,
- SENT_NACK
-} bitbang_i2c_state;
-
-struct bitbang_i2c_interface {
- I2CBus *bus;
- bitbang_i2c_state state;
- int last_data;
- int last_clock;
- int device_out;
- uint8_t buffer;
- int current_addr;
-};
-
static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
{
DPRINTF("STOP\n");
abort();
}
-bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus)
+void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus)
{
- bitbang_i2c_interface *s;
-
- s = g_malloc0(sizeof(bitbang_i2c_interface));
-
s->bus = bus;
s->last_data = 1;
s->last_clock = 1;
s->device_out = 1;
-
- return s;
}
/* GPIO interface. */
SysBusDevice parent_obj;
MemoryRegion dummy_iomem;
- bitbang_i2c_interface *bitbang;
+ bitbang_i2c_interface bitbang;
int last_level;
qemu_irq out;
} GPIOI2CState;
{
GPIOI2CState *s = opaque;
- level = bitbang_i2c_set(s->bitbang, irq, level);
+ level = bitbang_i2c_set(&s->bitbang, irq, level);
if (level != s->last_level) {
s->last_level = level;
qemu_set_irq(s->out, level);
sysbus_init_mmio(sbd, &s->dummy_iomem);
bus = i2c_init_bus(dev, "i2c");
- s->bitbang = bitbang_i2c_init(bus);
+ bitbang_i2c_init(&s->bitbang, bus);
qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2);
qdev_init_gpio_out(dev, &s->out, 1);
case IIC_DIRECTCNTL:
i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC);
i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0);
- bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SCL,
+ bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SCL,
i2c->directcntl & IIC_DIRECTCNTL_MSCL);
- i2c->directcntl |= bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SDA,
+ i2c->directcntl |= bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SDA,
(value & IIC_DIRECTCNTL_SDAC) != 0) << 1;
break;
default:
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
s->bus = i2c_init_bus(DEVICE(s), "i2c");
- s->bitbang = bitbang_i2c_init(s->bus);
+ bitbang_i2c_init(&s->bitbang, s->bus);
}
static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
SysBusDevice parent_obj;
MemoryRegion iomem;
- bitbang_i2c_interface *bitbang;
+ bitbang_i2c_interface bitbang;
int out;
int in;
} VersatileI2CState;
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%x\n", __func__, (int)offset);
}
- bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
- s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
+ bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
+ s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
}
static const MemoryRegionOps versatile_i2c_ops = {
I2CBus *bus;
bus = i2c_init_bus(dev, "i2c");
- s->bitbang = bitbang_i2c_init(bus);
+ bitbang_i2c_init(&s->bitbang, bus);
memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
"versatile_i2c", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
#define BITBANG_I2C_SDA 0
#define BITBANG_I2C_SCL 1
-bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus);
+typedef enum bitbang_i2c_state {
+ STOPPED = 0,
+ SENDING_BIT7,
+ SENDING_BIT6,
+ SENDING_BIT5,
+ SENDING_BIT4,
+ SENDING_BIT3,
+ SENDING_BIT2,
+ SENDING_BIT1,
+ SENDING_BIT0,
+ WAITING_FOR_ACK,
+ RECEIVING_BIT7,
+ RECEIVING_BIT6,
+ RECEIVING_BIT5,
+ RECEIVING_BIT4,
+ RECEIVING_BIT3,
+ RECEIVING_BIT2,
+ RECEIVING_BIT1,
+ RECEIVING_BIT0,
+ SENDING_ACK,
+ SENT_NACK
+} bitbang_i2c_state;
+
+struct bitbang_i2c_interface {
+ I2CBus *bus;
+ bitbang_i2c_state state;
+ int last_data;
+ int last_clock;
+ int device_out;
+ uint8_t buffer;
+ int current_addr;
+};
+
+/**
+ * bitbang_i2c_init: in-place initialize the bitbang_i2c_interface struct
+ */
+void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus);
int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level);
#endif
I2CBus *bus;
qemu_irq irq;
MemoryRegion iomem;
- bitbang_i2c_interface *bitbang;
+ bitbang_i2c_interface bitbang;
int mdidx;
uint8_t mdata[4];
uint8_t lmadr;