staging: wfx: handle firmware events synchronously

Currently, events from firmware are handled in a work queue with a
complex event queue mechanism. It is probably overkill since there is
only two events to handle: bss_loss and CQM events. Handling these
events synchronously is sufficient.

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200420160311.57323-5-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jérôme Pouiller 2020-04-20 18:02:59 +02:00 committed by Greg Kroah-Hartman
parent 5c442b6a39
commit 988cf07bb9
4 changed files with 24 additions and 95 deletions

View file

@ -158,26 +158,31 @@ static int hif_event_indication(struct wfx_dev *wdev,
{
struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
const struct hif_ind_event *body = buf;
struct wfx_hif_event *event;
int first;
WARN_ON(!wvif);
if (!wvif)
if (!wvif) {
dev_warn(wdev->dev, "received event for non-existent vif\n");
return 0;
}
event = kzalloc(sizeof(*event), GFP_KERNEL);
if (!event)
return -ENOMEM;
memcpy(&event->evt, body, sizeof(struct hif_ind_event));
spin_lock(&wvif->event_queue_lock);
first = list_empty(&wvif->event_queue);
list_add_tail(&event->link, &wvif->event_queue);
spin_unlock(&wvif->event_queue_lock);
if (first)
schedule_work(&wvif->event_handler_work);
switch (body->event_id) {
case HIF_EVENT_IND_RCPI_RSSI:
wfx_event_report_rssi(wvif, body->event_data.rcpi_rssi);
break;
case HIF_EVENT_IND_BSSLOST:
schedule_delayed_work(&wvif->beacon_loss_work, 0);
break;
case HIF_EVENT_IND_BSSREGAINED:
cancel_delayed_work(&wvif->beacon_loss_work);
dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n");
break;
case HIF_EVENT_IND_PS_MODE_ERROR:
dev_warn(wdev->dev, "error while processing power save request\n");
break;
default:
dev_warn(wdev->dev, "unhandled event indication: %.2x\n",
body->event_id);
break;
}
return 0;
}

View file

@ -38,27 +38,6 @@ u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
return ret;
}
static void __wfx_free_event_queue(struct list_head *list)
{
struct wfx_hif_event *event, *tmp;
list_for_each_entry_safe(event, tmp, list, link) {
list_del(&event->link);
kfree(event);
}
}
static void wfx_free_event_queue(struct wfx_vif *wvif)
{
LIST_HEAD(list);
spin_lock(&wvif->event_queue_lock);
list_splice_init(&wvif->event_queue, &list);
spin_unlock(&wvif->event_queue_lock);
__wfx_free_event_queue(&list);
}
static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
{
const struct hif_ie_table_entry filter_ies[] = {
@ -269,7 +248,7 @@ int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
/* WSM callbacks */
static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
{
/* RSSI: signed Q8.0, RCPI: unsigned Q7.1
* RSSI = RCPI / 2 - 110
@ -296,44 +275,6 @@ static void wfx_beacon_loss_work(struct work_struct *work)
msecs_to_jiffies(bss_conf->beacon_int));
}
static void wfx_event_handler_work(struct work_struct *work)
{
struct wfx_vif *wvif =
container_of(work, struct wfx_vif, event_handler_work);
struct wfx_hif_event *event;
LIST_HEAD(list);
spin_lock(&wvif->event_queue_lock);
list_splice_init(&wvif->event_queue, &list);
spin_unlock(&wvif->event_queue_lock);
list_for_each_entry(event, &list, link) {
switch (event->evt.event_id) {
case HIF_EVENT_IND_BSSLOST:
schedule_delayed_work(&wvif->beacon_loss_work, 0);
break;
case HIF_EVENT_IND_BSSREGAINED:
cancel_delayed_work(&wvif->beacon_loss_work);
break;
case HIF_EVENT_IND_RCPI_RSSI:
wfx_event_report_rssi(wvif,
event->evt.event_data.rcpi_rssi);
break;
case HIF_EVENT_IND_PS_MODE_ERROR:
dev_warn(wvif->wdev->dev,
"error while processing power save request\n");
break;
default:
dev_warn(wvif->wdev->dev,
"unhandled event indication: %.2x\n",
event->evt.event_id);
break;
}
}
__wfx_free_event_queue(&list);
}
// Call it with wdev->conf_mutex locked
static void wfx_do_unjoin(struct wfx_vif *wvif)
{
@ -351,9 +292,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif)
wfx_tx_policy_init(wvif);
if (wvif_count(wvif->wdev) <= 1)
hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
wfx_free_event_queue(wvif);
cancel_work_sync(&wvif->event_handler_work);
wfx_tx_unlock(wvif->wdev);
cancel_delayed_work_sync(&wvif->beacon_loss_work);
}
@ -844,10 +782,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
wvif->wep_default_key_id = -1;
INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work);
spin_lock_init(&wvif->event_queue_lock);
INIT_LIST_HEAD(&wvif->event_queue);
INIT_WORK(&wvif->event_handler_work, wfx_event_handler_work);
init_completion(&wvif->set_pm_mode_complete);
complete(&wvif->set_pm_mode_complete);
INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
@ -904,9 +838,7 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
/* FIXME: In add to reset MAC address, try to reset interface */
hif_set_macaddr(wvif, NULL);
wfx_free_event_queue(wvif);
cancel_delayed_work_sync(&wvif->beacon_loss_work);
wdev->vif[wvif->id] = NULL;
wvif->vif = NULL;

View file

@ -23,11 +23,6 @@ enum wfx_state {
WFX_STATE_AP,
};
struct wfx_hif_event {
struct list_head link;
struct hif_ind_event evt;
};
struct wfx_sta_priv {
int link_id;
int vif_id;
@ -79,6 +74,7 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
// WSM Callbacks
void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd);
void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi);
// Other Helpers
u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates);

View file

@ -98,10 +98,6 @@ struct wfx_vif {
struct ieee80211_scan_request *scan_req;
struct completion set_pm_mode_complete;
struct list_head event_queue;
spinlock_t event_queue_lock;
struct work_struct event_handler_work;
};
static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id)