Commit 3768c74b authored by Jérôme Pouiller's avatar Jérôme Pouiller Committed by Greg Kroah-Hartman

staging: wfx: drop async field from struct hif_cmd

The parameter "async" in wfx_cmd_send() allows to send command without
waiting for the reply. In this case, the mutex hif_cmd.lock is released
asynchronously in the context of the receiver workqueue.

However, "kbuild test robot" complains about this architecture[1] since
it is not able to follow the lock duration of hif_cmd.lock (and indeed,
the state of the driver if the hardware wouldn't reply is not well
defined).

Besides, this feature is not really necessary. It is only used by
hif_shutdown(). This function hijack the 'async' flag to run a command
that won't answer.

So, this patch removes the 'async' flag and introduces a 'no_reply' flag.
Thus, the mutex hif_cmd.lock is only acquired/released from
hif_cmd_send(). Therefore:
  - hif_shutdown() does not have to touch the private data of the struct
    hif_cmd
  - Kbuild test robot should be happy
  - the resulting code is simpler

[1] https://lore.kernel.org/driverdev-devel/alpine.DEB.2.21.1910041317381.2992@hadrien/Reported-by: default avatarkbuild test robot <lkp@intel.com>
Reported-by: default avatarJulia Lawall <julia.lawall@lip6.fr>
Signed-off-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200907101521.66082-31-Jerome.Pouiller@silabs.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c8fb8809
...@@ -47,12 +47,7 @@ static int hif_generic_confirm(struct wfx_dev *wdev, ...@@ -47,12 +47,7 @@ static int hif_generic_confirm(struct wfx_dev *wdev,
} }
wdev->hif_cmd.ret = status; wdev->hif_cmd.ret = status;
if (!wdev->hif_cmd.async) {
complete(&wdev->hif_cmd.done); complete(&wdev->hif_cmd.done);
} else {
wdev->hif_cmd.buf_send = NULL;
mutex_unlock(&wdev->hif_cmd.lock);
}
return status; return status;
} }
......
...@@ -47,7 +47,7 @@ static void *wfx_alloc_hif(size_t body_len, struct hif_msg **hif) ...@@ -47,7 +47,7 @@ static void *wfx_alloc_hif(size_t body_len, struct hif_msg **hif)
} }
int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request,
void *reply, size_t reply_len, bool async) void *reply, size_t reply_len, bool no_reply)
{ {
const char *mib_name = ""; const char *mib_name = "";
const char *mib_sep = ""; const char *mib_sep = "";
...@@ -55,8 +55,6 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, ...@@ -55,8 +55,6 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request,
int vif = request->interface; int vif = request->interface;
int ret; int ret;
WARN(wdev->hif_cmd.buf_recv && wdev->hif_cmd.async, "API usage error");
// Do not wait for any reply if chip is frozen // Do not wait for any reply if chip is frozen
if (wdev->chip_frozen) if (wdev->chip_frozen)
return -ETIMEDOUT; return -ETIMEDOUT;
...@@ -69,14 +67,18 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, ...@@ -69,14 +67,18 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request,
wdev->hif_cmd.buf_send = request; wdev->hif_cmd.buf_send = request;
wdev->hif_cmd.buf_recv = reply; wdev->hif_cmd.buf_recv = reply;
wdev->hif_cmd.len_recv = reply_len; wdev->hif_cmd.len_recv = reply_len;
wdev->hif_cmd.async = async;
complete(&wdev->hif_cmd.ready); complete(&wdev->hif_cmd.ready);
wfx_bh_request_tx(wdev); wfx_bh_request_tx(wdev);
// NOTE: no timeout is caught async is enabled if (no_reply) {
if (async) // Chip won't reply. Give enough time to the wq to send the
// buffer.
msleep(100);
wdev->hif_cmd.buf_send = NULL;
mutex_unlock(&wdev->hif_cmd.lock);
return 0; return 0;
}
if (wdev->poll_irq) if (wdev->poll_irq)
wfx_bh_poll_irq(wdev); wfx_bh_poll_irq(wdev);
...@@ -118,29 +120,21 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, ...@@ -118,29 +120,21 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request,
} }
// This function is special. After HIF_REQ_ID_SHUT_DOWN, chip won't reply to any // This function is special. After HIF_REQ_ID_SHUT_DOWN, chip won't reply to any
// request anymore. We need to slightly hack struct wfx_hif_cmd for that job. Be // request anymore. Obviously, only call this function during device unregister.
// careful to only call this function during device unregister.
int hif_shutdown(struct wfx_dev *wdev) int hif_shutdown(struct wfx_dev *wdev)
{ {
int ret; int ret;
struct hif_msg *hif; struct hif_msg *hif;
if (wdev->chip_frozen)
return 0;
wfx_alloc_hif(0, &hif); wfx_alloc_hif(0, &hif);
if (!hif) if (!hif)
return -ENOMEM; return -ENOMEM;
wfx_fill_header(hif, -1, HIF_REQ_ID_SHUT_DOWN, 0); wfx_fill_header(hif, -1, HIF_REQ_ID_SHUT_DOWN, 0);
ret = wfx_cmd_send(wdev, hif, NULL, 0, true); ret = wfx_cmd_send(wdev, hif, NULL, 0, true);
// After this command, chip won't reply. Be sure to give enough time to
// bh to send buffer:
msleep(100);
wdev->hif_cmd.buf_send = NULL;
if (wdev->pdata.gpio_wakeup) if (wdev->pdata.gpio_wakeup)
gpiod_set_value(wdev->pdata.gpio_wakeup, 0); gpiod_set_value(wdev->pdata.gpio_wakeup, 0);
else else
control_reg_write(wdev, 0); control_reg_write(wdev, 0);
mutex_unlock(&wdev->hif_cmd.lock);
kfree(hif); kfree(hif);
return ret; return ret;
} }
......
...@@ -22,7 +22,6 @@ struct wfx_hif_cmd { ...@@ -22,7 +22,6 @@ struct wfx_hif_cmd {
struct mutex lock; struct mutex lock;
struct completion ready; struct completion ready;
struct completion done; struct completion done;
bool async;
struct hif_msg *buf_send; struct hif_msg *buf_send;
void *buf_recv; void *buf_recv;
size_t len_recv; size_t len_recv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment