Skip to content

Commit b6f9ed3

Browse files
conghuic23acrnsi
authored andcommitted
DM: virtio-i2c: add msg process logic
Create a new thread for virtio-i2c to process i2c msg from FE. After receive the msg, BE will dispatch it to corresponding native adapter, after the process done, it will kick the FE. Tracked-On: #3357 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Reviewed-by: Yuan Liu <yuan1.liu@intel.com> Reviewed-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Wang Yu <yu1.wang@intel.com>
1 parent 859af9e commit b6f9ed3

File tree

1 file changed

+140
-1
lines changed

1 file changed

+140
-1
lines changed

devicemodel/hw/pci/virtio/virtio_i2c.c

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ static int virtio_i2c_debug=0;
6464

6565
#define MAX_I2C_VDEV 128
6666
#define MAX_NATIVE_I2C_ADAPTER 16
67+
#define I2C_MSG_OK 0
68+
#define I2C_MSG_ERR 1
69+
#define I2C_NO_DEV 2
70+
71+
struct virtio_i2c_hdr {
72+
uint16_t addr; /* slave address */
73+
uint16_t flags;
74+
uint16_t len; /*msg length*/
75+
}__attribute__((packed));
6776

6877
struct native_i2c_adapter {
6978
int fd;
@@ -82,6 +91,11 @@ struct virtio_i2c {
8291
uint16_t adapter_map[MAX_I2C_VDEV];
8392
struct virtio_vq_info vq;
8493
char ident[256];
94+
pthread_t req_tid;
95+
pthread_mutex_t req_mtx;
96+
pthread_cond_t req_cond;
97+
int in_process;
98+
int closing;
8599
};
86100

87101
static void virtio_i2c_reset(void *);
@@ -113,6 +127,53 @@ native_slave_access_ok(struct native_i2c_adapter *adapter, uint16_t addr)
113127
return true;
114128
}
115129

130+
static struct native_i2c_adapter *
131+
native_adapter_find(struct virtio_i2c *vi2c, uint16_t addr)
132+
{
133+
int idx;
134+
135+
if (addr < MAX_I2C_VDEV && ((idx = vi2c->adapter_map[addr]) != 0)) {
136+
return vi2c->native_adapter[idx - 1];
137+
}
138+
return NULL;
139+
}
140+
141+
static uint8_t
142+
native_adapter_proc(struct virtio_i2c *vi2c, struct i2c_msg *msg)
143+
{
144+
int ret;
145+
uint16_t addr;
146+
struct i2c_rdwr_ioctl_data work_queue;
147+
struct native_i2c_adapter *adapter;
148+
uint8_t status;
149+
150+
addr = msg->addr;
151+
adapter = native_adapter_find(vi2c, addr);
152+
if (!adapter)
153+
return I2C_NO_DEV;
154+
155+
work_queue.nmsgs = 1;
156+
work_queue.msgs = msg;
157+
158+
ret = ioctl(adapter->fd, I2C_RDWR, &work_queue);
159+
if (ret < 0)
160+
status = I2C_MSG_ERR;
161+
else
162+
status = I2C_MSG_OK;
163+
if (msg->len)
164+
DPRINTF("i2c_core: i2c msg: flags=0x%x, addr=0x%x, len=0x%x buf=%x\n",
165+
msg->flags,
166+
msg->addr,
167+
msg->len,
168+
msg->buf[0]);
169+
else
170+
DPRINTF("i2c_core: i2c msg: flags=0x%x, addr=0x%x, len=0x%x\n",
171+
msg->flags,
172+
msg->addr,
173+
msg->len);
174+
return status;
175+
}
176+
116177
static struct native_i2c_adapter *
117178
native_adapter_create(int bus, uint16_t slave_addr[], int n_slave)
118179
{
@@ -176,6 +237,68 @@ native_adapter_remove(struct virtio_i2c *vi2c)
176237
}
177238
}
178239

240+
static void
241+
virtio_i2c_req_stop(struct virtio_i2c *vi2c)
242+
{
243+
void *jval;
244+
245+
pthread_mutex_lock(&vi2c->req_mtx);
246+
vi2c->closing = 1;
247+
pthread_cond_broadcast(&vi2c->req_cond);
248+
pthread_mutex_unlock(&vi2c->req_mtx);
249+
pthread_join(vi2c->req_tid, &jval);
250+
}
251+
252+
static void *
253+
virtio_i2c_proc_thread(void *arg)
254+
{
255+
struct virtio_i2c *vi2c = arg;
256+
struct virtio_vq_info *vq = &vi2c->vq;
257+
struct iovec iov[3];
258+
uint16_t idx, flags[3];
259+
struct virtio_i2c_hdr *hdr;
260+
struct i2c_msg msg;
261+
uint8_t *status;
262+
int n;
263+
264+
for (;;) {
265+
pthread_mutex_lock(&vi2c->req_mtx);
266+
267+
vi2c->in_process = 0;
268+
while (!vq_has_descs(vq) && !vi2c->closing)
269+
pthread_cond_wait(&vi2c->req_cond, &vi2c->req_mtx);
270+
271+
if (vi2c->closing) {
272+
pthread_mutex_unlock(&vi2c->req_mtx);
273+
return NULL;
274+
}
275+
vi2c->in_process = 1;
276+
pthread_mutex_unlock(&vi2c->req_mtx);
277+
do {
278+
n = vq_getchain(vq, &idx, iov, 3, flags);
279+
if (n < 2 || n > 3) {
280+
WPRINTF("virtio_i2c_proc: failed to get iov from virtqueue\n");
281+
continue;
282+
}
283+
hdr = iov[0].iov_base;
284+
msg.addr = hdr->addr;
285+
msg.flags = hdr->flags;
286+
if (hdr->len) {
287+
msg.buf = iov[1].iov_base;
288+
msg.len = iov[1].iov_len;
289+
status = iov[2].iov_base;
290+
} else {
291+
msg.buf = NULL;
292+
msg.len = 0;
293+
status = iov[1].iov_base;
294+
}
295+
*status = native_adapter_proc(vi2c, &msg);
296+
vq_relchain(vq, idx, 1);
297+
} while (vq_has_descs(vq));
298+
vq_endchains(vq, 0);
299+
}
300+
}
301+
179302
static int
180303
virtio_i2c_map(struct virtio_i2c *vi2c)
181304
{
@@ -282,7 +405,15 @@ virtio_i2c_reset(void *vdev)
282405
static void
283406
virtio_i2c_notify(void *vdev, struct virtio_vq_info *vq)
284407
{
285-
/* TODO: Add notify logic */
408+
struct virtio_i2c *vi2c = vdev;
409+
410+
if (!vq_has_descs(vq))
411+
return;
412+
413+
pthread_mutex_lock(&vi2c->req_mtx);
414+
if (!vi2c->in_process)
415+
pthread_cond_signal(&vi2c->req_cond);
416+
pthread_mutex_unlock(&vi2c->req_mtx);
286417
}
287418

288419
static int
@@ -361,6 +492,12 @@ virtio_i2c_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
361492
goto fail;
362493
}
363494
virtio_set_io_bar(&vi2c->base, 0);
495+
vi2c->in_process = 0;
496+
vi2c->closing = 0;
497+
pthread_mutex_init(&vi2c->req_mtx, NULL);
498+
pthread_cond_init(&vi2c->req_cond, NULL);
499+
pthread_create(&vi2c->req_tid, NULL, virtio_i2c_proc_thread, vi2c);
500+
pthread_setname_np(vi2c->req_tid, "virtio-i2c");
364501
return 0;
365502

366503
fail:
@@ -379,7 +516,9 @@ virtio_i2c_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
379516
if (dev->arg) {
380517
DPRINTF("deinit\n");
381518
vi2c = (struct virtio_i2c *) dev->arg;
519+
virtio_i2c_req_stop(vi2c);
382520
native_adapter_remove(vi2c);
521+
pthread_mutex_destroy(&vi2c->req_mtx);
383522
pthread_mutex_destroy(&vi2c->mtx);
384523
free(vi2c);
385524
dev->arg = NULL;

0 commit comments

Comments
 (0)