wmi.c (bf9b608e63dfd71ab225c9d4211eb6d8dc582a3b) wmi.c (0c936b3c96337c3fd5ad4951ca7bdc54fa578a02)
1/*
2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *

--- 450 unchanged lines hidden (view full) ---

459 case WMI_TX_DESC_RING_ADD_CMDID:
460 return "WMI_TX_DESC_RING_ADD_CMD";
461 case WMI_RX_DESC_RING_ADD_CMDID:
462 return "WMI_RX_DESC_RING_ADD_CMD";
463 case WMI_BCAST_DESC_RING_ADD_CMDID:
464 return "WMI_BCAST_DESC_RING_ADD_CMD";
465 case WMI_CFG_DEF_RX_OFFLOAD_CMDID:
466 return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
1/*
2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *

--- 450 unchanged lines hidden (view full) ---

459 case WMI_TX_DESC_RING_ADD_CMDID:
460 return "WMI_TX_DESC_RING_ADD_CMD";
461 case WMI_RX_DESC_RING_ADD_CMDID:
462 return "WMI_RX_DESC_RING_ADD_CMD";
463 case WMI_BCAST_DESC_RING_ADD_CMDID:
464 return "WMI_BCAST_DESC_RING_ADD_CMD";
465 case WMI_CFG_DEF_RX_OFFLOAD_CMDID:
466 return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
467 case WMI_LINK_STATS_CMDID:
468 return "WMI_LINK_STATS_CMD";
467 default:
468 return "Untracked CMD";
469 }
470}
471
472static const char *eventid2name(u16 eventid)
473{
474 switch (eventid) {

--- 118 unchanged lines hidden (view full) ---

593 case WMI_RX_STATUS_RING_CFG_DONE_EVENTID:
594 return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
595 case WMI_TX_DESC_RING_CFG_DONE_EVENTID:
596 return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
597 case WMI_RX_DESC_RING_CFG_DONE_EVENTID:
598 return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
599 case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID:
600 return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
469 default:
470 return "Untracked CMD";
471 }
472}
473
474static const char *eventid2name(u16 eventid)
475{
476 switch (eventid) {

--- 118 unchanged lines hidden (view full) ---

595 case WMI_RX_STATUS_RING_CFG_DONE_EVENTID:
596 return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
597 case WMI_TX_DESC_RING_CFG_DONE_EVENTID:
598 return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
599 case WMI_RX_DESC_RING_CFG_DONE_EVENTID:
600 return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
601 case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID:
602 return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
603 case WMI_LINK_STATS_CONFIG_DONE_EVENTID:
604 return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
605 case WMI_LINK_STATS_EVENTID:
606 return "WMI_LINK_STATS_EVENT";
601 default:
602 return "Untracked EVENT";
603 }
604}
605
606static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid,
607 void *buf, u16 len)
608{

--- 715 unchanged lines hidden (view full) ---

1324 cfg80211_put_bss(wiphy, bss);
1325 } else {
1326 wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
1327 }
1328
1329 cfg80211_sched_scan_results(wiphy, 0);
1330}
1331
607 default:
608 return "Untracked EVENT";
609 }
610}
611
612static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid,
613 void *buf, u16 len)
614{

--- 715 unchanged lines hidden (view full) ---

1330 cfg80211_put_bss(wiphy, bss);
1331 } else {
1332 wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
1333 }
1334
1335 cfg80211_sched_scan_results(wiphy, 0);
1336}
1337
1338static void wil_link_stats_store_basic(struct wil6210_vif *vif,
1339 struct wmi_link_stats_basic *basic)
1340{
1341 struct wil6210_priv *wil = vif_to_wil(vif);
1342 u8 cid = basic->cid;
1343 struct wil_sta_info *sta;
1344
1345 if (cid < 0 || cid >= WIL6210_MAX_CID) {
1346 wil_err(wil, "invalid cid %d\n", cid);
1347 return;
1348 }
1349
1350 sta = &wil->sta[cid];
1351 sta->fw_stats_basic = *basic;
1352}
1353
1354static void wil_link_stats_store_global(struct wil6210_vif *vif,
1355 struct wmi_link_stats_global *global)
1356{
1357 struct wil6210_priv *wil = vif_to_wil(vif);
1358
1359 wil->fw_stats_global.stats = *global;
1360}
1361
1362static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf,
1363 bool has_next, void *payload,
1364 size_t payload_size)
1365{
1366 struct wil6210_priv *wil = vif_to_wil(vif);
1367 size_t hdr_size = sizeof(struct wmi_link_stats_record);
1368 size_t stats_size, record_size, expected_size;
1369 struct wmi_link_stats_record *hdr;
1370
1371 if (payload_size < hdr_size) {
1372 wil_err(wil, "link stats wrong event size %zu\n", payload_size);
1373 return;
1374 }
1375
1376 while (payload_size >= hdr_size) {
1377 hdr = payload;
1378 stats_size = le16_to_cpu(hdr->record_size);
1379 record_size = hdr_size + stats_size;
1380
1381 if (payload_size < record_size) {
1382 wil_err(wil, "link stats payload ended unexpectedly, size %zu < %zu\n",
1383 payload_size, record_size);
1384 return;
1385 }
1386
1387 switch (hdr->record_type_id) {
1388 case WMI_LINK_STATS_TYPE_BASIC:
1389 expected_size = sizeof(struct wmi_link_stats_basic);
1390 if (stats_size < expected_size) {
1391 wil_err(wil, "link stats invalid basic record size %zu < %zu\n",
1392 stats_size, expected_size);
1393 return;
1394 }
1395 if (vif->fw_stats_ready) {
1396 /* clean old statistics */
1397 vif->fw_stats_tsf = 0;
1398 vif->fw_stats_ready = 0;
1399 }
1400
1401 wil_link_stats_store_basic(vif, payload + hdr_size);
1402
1403 if (!has_next) {
1404 vif->fw_stats_tsf = tsf;
1405 vif->fw_stats_ready = 1;
1406 }
1407
1408 break;
1409 case WMI_LINK_STATS_TYPE_GLOBAL:
1410 expected_size = sizeof(struct wmi_link_stats_global);
1411 if (stats_size < sizeof(struct wmi_link_stats_global)) {
1412 wil_err(wil, "link stats invalid global record size %zu < %zu\n",
1413 stats_size, expected_size);
1414 return;
1415 }
1416
1417 if (wil->fw_stats_global.ready) {
1418 /* clean old statistics */
1419 wil->fw_stats_global.tsf = 0;
1420 wil->fw_stats_global.ready = 0;
1421 }
1422
1423 wil_link_stats_store_global(vif, payload + hdr_size);
1424
1425 if (!has_next) {
1426 wil->fw_stats_global.tsf = tsf;
1427 wil->fw_stats_global.ready = 1;
1428 }
1429
1430 break;
1431 default:
1432 break;
1433 }
1434
1435 /* skip to next record */
1436 payload += record_size;
1437 payload_size -= record_size;
1438 }
1439}
1440
1441static void
1442wmi_evt_link_stats(struct wil6210_vif *vif, int id, void *d, int len)
1443{
1444 struct wil6210_priv *wil = vif_to_wil(vif);
1445 struct wmi_link_stats_event *evt = d;
1446 size_t payload_size;
1447
1448 if (len < offsetof(struct wmi_link_stats_event, payload)) {
1449 wil_err(wil, "stats event way too short %d\n", len);
1450 return;
1451 }
1452 payload_size = le16_to_cpu(evt->payload_size);
1453 if (len < sizeof(struct wmi_link_stats_event) + payload_size) {
1454 wil_err(wil, "stats event too short %d\n", len);
1455 return;
1456 }
1457
1458 wmi_link_stats_parse(vif, le64_to_cpu(evt->tsf), evt->has_next,
1459 evt->payload, payload_size);
1460}
1461
1332/**
1333 * Some events are ignored for purpose; and need not be interpreted as
1334 * "unhandled events"
1335 */
1336static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
1337{
1338 struct wil6210_priv *wil = vif_to_wil(vif);
1339

--- 14 unchanged lines hidden (view full) ---

1354 {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect},
1355 {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx},
1356 {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
1357 {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
1358 {WMI_DELBA_EVENTID, wmi_evt_delba},
1359 {WMI_RING_EN_EVENTID, wmi_evt_ring_en},
1360 {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
1361 {WMI_SCHED_SCAN_RESULT_EVENTID, wmi_evt_sched_scan_result},
1462/**
1463 * Some events are ignored for purpose; and need not be interpreted as
1464 * "unhandled events"
1465 */
1466static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
1467{
1468 struct wil6210_priv *wil = vif_to_wil(vif);
1469

--- 14 unchanged lines hidden (view full) ---

1484 {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect},
1485 {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx},
1486 {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
1487 {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
1488 {WMI_DELBA_EVENTID, wmi_evt_delba},
1489 {WMI_RING_EN_EVENTID, wmi_evt_ring_en},
1490 {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
1491 {WMI_SCHED_SCAN_RESULT_EVENTID, wmi_evt_sched_scan_result},
1492 {WMI_LINK_STATS_EVENTID, wmi_evt_link_stats},
1362};
1363
1364/*
1365 * Run in IRQ context
1366 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1367 * that will be eventually handled by the @wmi_event_worker in the thread
1368 * context of thread "wil6210_wmi"
1369 */

--- 1867 unchanged lines hidden (view full) ---

3237 spin_lock_bh(&txdata->lock);
3238 ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3239 txdata->mid = vif->mid;
3240 txdata->enabled = 1;
3241 spin_unlock_bh(&txdata->lock);
3242
3243 return 0;
3244}
1493};
1494
1495/*
1496 * Run in IRQ context
1497 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
1498 * that will be eventually handled by the @wmi_event_worker in the thread
1499 * context of thread "wil6210_wmi"
1500 */

--- 1867 unchanged lines hidden (view full) ---

3368 spin_lock_bh(&txdata->lock);
3369 ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
3370 txdata->mid = vif->mid;
3371 txdata->enabled = 1;
3372 spin_unlock_bh(&txdata->lock);
3373
3374 return 0;
3375}
3376
3377int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval)
3378{
3379 struct wil6210_priv *wil = vif_to_wil(vif);
3380 struct wmi_link_stats_cmd cmd = {
3381 .record_type_mask = cpu_to_le32(type),
3382 .cid = cid,
3383 .action = WMI_LINK_STATS_SNAPSHOT,
3384 .interval_msec = cpu_to_le32(interval),
3385 };
3386 struct {
3387 struct wmi_cmd_hdr wmi;
3388 struct wmi_link_stats_config_done_event evt;
3389 } __packed reply = {
3390 .evt = {.status = WMI_FW_STATUS_FAILURE},
3391 };
3392 int rc;
3393
3394 rc = wmi_call(wil, WMI_LINK_STATS_CMDID, vif->mid, &cmd, sizeof(cmd),
3395 WMI_LINK_STATS_CONFIG_DONE_EVENTID, &reply,
3396 sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
3397 if (rc) {
3398 wil_err(wil, "WMI_LINK_STATS_CMDID failed, rc %d\n", rc);
3399 return rc;
3400 }
3401
3402 if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
3403 wil_err(wil, "Link statistics config failed, status %d\n",
3404 reply.evt.status);
3405 return -EINVAL;
3406 }
3407
3408 return 0;
3409}