mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
dm: change virtio-i2c transfer logic
1. Change i2c message transfer logic according to virtio spec v1.2 2. Other tiny fixes. Tracked-On: #8055 Signed-off-by: Conghui <conghui.chen@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
a8dd662635
commit
7a870e751a
@ -63,7 +63,7 @@
|
|||||||
static int virtio_i2c_debug=0;
|
static int virtio_i2c_debug=0;
|
||||||
#define VIRTIO_I2C_PREF "virtio_i2c: "
|
#define VIRTIO_I2C_PREF "virtio_i2c: "
|
||||||
#define DPRINTF(fmt, args...) \
|
#define DPRINTF(fmt, args...) \
|
||||||
do { if (virtio_i2c_debug) pr_dbg(VIRTIO_I2C_PREF fmt, ##args); } while (0)
|
do { if (virtio_i2c_debug) pr_info(VIRTIO_I2C_PREF fmt, ##args); } while (0)
|
||||||
#define WPRINTF(fmt, args...) pr_err(VIRTIO_I2C_PREF fmt, ##args)
|
#define WPRINTF(fmt, args...) pr_err(VIRTIO_I2C_PREF fmt, ##args)
|
||||||
|
|
||||||
#define MAX_NODE_NAME_LEN 20
|
#define MAX_NODE_NAME_LEN 20
|
||||||
@ -73,6 +73,11 @@ static int virtio_i2c_debug=0;
|
|||||||
#define I2C_MSG_ERR 1
|
#define I2C_MSG_ERR 1
|
||||||
#define I2C_NO_DEV 2
|
#define I2C_NO_DEV 2
|
||||||
|
|
||||||
|
#define I2C_NO_FLAGS 0
|
||||||
|
|
||||||
|
#define VIRTIO_I2C_FLAGS_FAIL_NEXT 1 << 0
|
||||||
|
#define VIRTIO_I2C_FLAGS_M_RD 1 << 1
|
||||||
|
|
||||||
static int acpi_i2c_adapter_num = 0;
|
static int acpi_i2c_adapter_num = 0;
|
||||||
static void acpi_add_i2c_adapter(struct pci_vdev *dev, int i2c_bus);
|
static void acpi_add_i2c_adapter(struct pci_vdev *dev, int i2c_bus);
|
||||||
static void acpi_add_cam1(struct pci_vdev *dev, int i2c_bus);
|
static void acpi_add_cam1(struct pci_vdev *dev, int i2c_bus);
|
||||||
@ -93,11 +98,15 @@ static struct acpi_node acpi_node_table[] = {
|
|||||||
{"default", acpi_add_default},
|
{"default", acpi_add_default},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct virtio_i2c_hdr {
|
struct virtio_i2c_out_hdr {
|
||||||
uint16_t addr; /* client address */
|
uint16_t addr; /* client address */
|
||||||
uint16_t flags;
|
uint16_t padding;
|
||||||
uint16_t len; /*msg length*/
|
uint32_t flags;
|
||||||
}__attribute__((packed));
|
};
|
||||||
|
|
||||||
|
struct virtio_i2c_in_hdr {
|
||||||
|
uint8_t status;
|
||||||
|
};
|
||||||
|
|
||||||
struct native_i2c_adapter {
|
struct native_i2c_adapter {
|
||||||
int fd;
|
int fd;
|
||||||
@ -404,8 +413,10 @@ native_adapter_proc(struct virtio_i2c *vi2c, struct i2c_msg *msg)
|
|||||||
|
|
||||||
addr = msg->addr;
|
addr = msg->addr;
|
||||||
adapter = native_adapter_find(vi2c, addr);
|
adapter = native_adapter_find(vi2c, addr);
|
||||||
if (!adapter)
|
if (!adapter) {
|
||||||
return I2C_NO_DEV;
|
DPRINTF("%s: could not find device for addr %x\n", __func__, msg->addr);
|
||||||
|
return I2C_MSG_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
work_queue.nmsgs = 1;
|
work_queue.nmsgs = 1;
|
||||||
work_queue.msgs = msg;
|
work_queue.msgs = msg;
|
||||||
@ -436,6 +447,7 @@ native_adapter_create(int bus, uint16_t client_addr[], int n_client)
|
|||||||
struct native_i2c_adapter *native_adapter;
|
struct native_i2c_adapter *native_adapter;
|
||||||
char native_path[20];
|
char native_path[20];
|
||||||
int i;
|
int i;
|
||||||
|
unsigned long funcs;
|
||||||
|
|
||||||
if (bus < 0)
|
if (bus < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -454,6 +466,16 @@ native_adapter_create(int bus, uint16_t client_addr[], int n_client)
|
|||||||
WPRINTF("virtio_i2c: failed to open %s\n", native_path);
|
WPRINTF("virtio_i2c: failed to open %s\n", native_path);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
|
||||||
|
WPRINTF("virtio_i2c: failed to get the funcs \n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(funcs & I2C_FUNC_I2C)) {
|
||||||
|
WPRINTF("virtio_i2c: this adapter %s doesn't support I2C_FUNC_I2C mode "
|
||||||
|
"(plain i2c-level commands)!\n", native_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
native_adapter->fd = fd;
|
native_adapter->fd = fd;
|
||||||
native_adapter->bus = bus;
|
native_adapter->bus = bus;
|
||||||
for (i = 0; i < n_client; i++) {
|
for (i = 0; i < n_client; i++) {
|
||||||
@ -513,10 +535,11 @@ virtio_i2c_proc_thread(void *arg)
|
|||||||
struct virtio_vq_info *vq = &vi2c->vq;
|
struct virtio_vq_info *vq = &vi2c->vq;
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
uint16_t idx, flags[3];
|
uint16_t idx, flags[3];
|
||||||
struct virtio_i2c_hdr *hdr;
|
|
||||||
struct i2c_msg msg;
|
struct i2c_msg msg;
|
||||||
uint8_t *status;
|
|
||||||
int n;
|
int n;
|
||||||
|
bool fail_next = false;
|
||||||
|
struct virtio_i2c_out_hdr *out_hdr;
|
||||||
|
struct virtio_i2c_in_hdr *in_hdr;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pthread_mutex_lock(&vi2c->req_mtx);
|
pthread_mutex_lock(&vi2c->req_mtx);
|
||||||
@ -537,20 +560,48 @@ virtio_i2c_proc_thread(void *arg)
|
|||||||
WPRINTF("virtio_i2c_proc: failed to get iov from virtqueue\n");
|
WPRINTF("virtio_i2c_proc: failed to get iov from virtqueue\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
hdr = iov[0].iov_base;
|
out_hdr = iov[0].iov_base;
|
||||||
msg.addr = hdr->addr;
|
/* From v1.2-cs01 virtio spec, 7-bit address is defined as:
|
||||||
msg.flags = hdr->flags;
|
* -----------------------------------------------------------
|
||||||
if (hdr->len) {
|
* Bits |15|14|13|12|11|10|9|8|7 |6 |5 |4 |3 |2 |1 |0|
|
||||||
|
* -------------+--+--+--+--+--+--+-+-+--+--+--+--+--+--+--+-+
|
||||||
|
* 7-bit address|0 |0 |0 |0 |0 |0 |0|0|A6|A5|A4|A3|A2|A1|A0|0|
|
||||||
|
* -------------+--+--+--+--+--+--+-+-+--+--+--+--+--+--+--+-+
|
||||||
|
*/
|
||||||
|
msg.addr = out_hdr->addr >> 1;
|
||||||
|
if (out_hdr->flags & VIRTIO_I2C_FLAGS_M_RD)
|
||||||
|
msg.flags = I2C_M_RD;
|
||||||
|
else
|
||||||
|
msg.flags = I2C_NO_FLAGS;
|
||||||
|
if (n == 3) {
|
||||||
msg.buf = iov[1].iov_base;
|
msg.buf = iov[1].iov_base;
|
||||||
msg.len = iov[1].iov_len;
|
msg.len = iov[1].iov_len;
|
||||||
status = iov[2].iov_base;
|
in_hdr = iov[2].iov_base;
|
||||||
} else {
|
} else {
|
||||||
|
// this is a zero-length request
|
||||||
msg.buf = NULL;
|
msg.buf = NULL;
|
||||||
msg.len = 0;
|
msg.len = 0;
|
||||||
status = iov[1].iov_base;
|
in_hdr = iov[1].iov_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From v1.2-cs01 virtio spec:
|
||||||
|
* VIRTIO_I2C_FLAGS_FAIL_NEXT(0) is used to group the requests. For a group requests,
|
||||||
|
* a driver clears this bit on the final request and sets it on the other requests.
|
||||||
|
* If this bit is set and a device fails to process the current request, it needs to
|
||||||
|
* fail the next request instead of attempting to execute it.
|
||||||
|
*/
|
||||||
|
if (!fail_next) {
|
||||||
|
in_hdr->status = native_adapter_proc(vi2c, &msg);
|
||||||
|
if ((out_hdr->flags & VIRTIO_I2C_FLAGS_FAIL_NEXT) && (in_hdr->status == I2C_MSG_ERR))
|
||||||
|
fail_next = true;
|
||||||
|
} else {
|
||||||
|
in_hdr->status = I2C_MSG_ERR;
|
||||||
}
|
}
|
||||||
*status = native_adapter_proc(vi2c, &msg);
|
|
||||||
vq_relchain(vq, idx, 1);
|
vq_relchain(vq, idx, 1);
|
||||||
|
|
||||||
|
if (!(out_hdr->flags & VIRTIO_I2C_FLAGS_FAIL_NEXT))
|
||||||
|
fail_next = false;
|
||||||
} while (vq_has_descs(vq));
|
} while (vq_has_descs(vq));
|
||||||
vq_endchains(vq, 0);
|
vq_endchains(vq, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user