samples: mei: don't wait on read completion upon write.

The original mei driver communication was strictly write command and
receive response flow, the completion of write was determined when
response was ready using select(). This paradigm is a long time not
true.  There can be write without a response and an unsolicited read.
The driver is capable of handling those.
Adjust also the sample code and remove select() on read() from the
write flow. Add select to the read flow to showcase how to do the
read with a timeout.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20210801072532.8668-1-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alexander Usyskin 2021-08-01 10:25:32 +03:00 committed by Greg Kroah-Hartman
parent 9b945d74a5
commit 0fc7ca624b

View File

@ -154,31 +154,52 @@ err:
static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
ssize_t len, unsigned long timeout) ssize_t len, unsigned long timeout)
{ {
struct timeval tv;
fd_set set;
ssize_t rc; ssize_t rc;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000000;
mei_msg(me, "call read length = %zd\n", len); mei_msg(me, "call read length = %zd\n", len);
FD_ZERO(&set);
FD_SET(me->fd, &set);
rc = select(me->fd + 1, &set, NULL, NULL, &tv);
if (rc > 0 && FD_ISSET(me->fd, &set)) {
mei_msg(me, "have reply\n");
} else if (rc == 0) {
rc = -1;
mei_err(me, "read failed on timeout\n");
goto out;
} else { /* rc < 0 */
rc = errno;
mei_err(me, "read failed on select with status %zd %s\n",
rc, strerror(errno));
goto out;
}
rc = read(me->fd, buffer, len); rc = read(me->fd, buffer, len);
if (rc < 0) { if (rc < 0) {
mei_err(me, "read failed with status %zd %s\n", mei_err(me, "read failed with status %zd %s\n",
rc, strerror(errno)); rc, strerror(errno));
mei_deinit(me); goto out;
} else {
mei_msg(me, "read succeeded with result %zd\n", rc);
} }
mei_msg(me, "read succeeded with result %zd\n", rc);
out:
if (rc < 0)
mei_deinit(me);
return rc; return rc;
} }
static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
ssize_t len, unsigned long timeout) ssize_t len, unsigned long timeout)
{ {
struct timeval tv;
ssize_t written; ssize_t written;
ssize_t rc; ssize_t rc;
fd_set set;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000000;
mei_msg(me, "call write length = %zd\n", len); mei_msg(me, "call write length = %zd\n", len);
@ -189,19 +210,7 @@ static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
written, strerror(errno)); written, strerror(errno));
goto out; goto out;
} }
mei_msg(me, "write success\n");
FD_ZERO(&set);
FD_SET(me->fd, &set);
rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
if (rc > 0 && FD_ISSET(me->fd, &set)) {
mei_msg(me, "write success\n");
} else if (rc == 0) {
mei_err(me, "write failed on timeout with status\n");
goto out;
} else { /* rc < 0 */
mei_err(me, "write failed on select with status %zd\n", rc);
goto out;
}
rc = written; rc = written;
out: out: