From b6719a845241709481727306ed3e3b753685c25f Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Mon, 5 Sep 2016 10:10:57 +0300 Subject: [PATCH 01/10] wil6210: align to latest auto generated wmi.h Align to latest version of the auto generated wmi file describing the interface with FW. Change-Id: I95c14c0fe7a33c078eb7d9aa44dd97a64f9b0fae Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 0163b03199006a6ba0d2c991c311e8ac93fcb208 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/wmi.h | 640 ++++++++++++++++++++++--- 1 file changed, 561 insertions(+), 79 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 685fe0ddea26..349510cdb153 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -120,6 +120,8 @@ enum wmi_command_id { WMI_BF_SM_MGMT_CMDID = 0x838, WMI_BF_RXSS_MGMT_CMDID = 0x839, WMI_BF_TRIG_CMDID = 0x83A, + WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842, + WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843, WMI_SET_SECTORS_CMDID = 0x849, WMI_MAINTAIN_PAUSE_CMDID = 0x850, WMI_MAINTAIN_RESUME_CMDID = 0x851, @@ -134,10 +136,15 @@ enum wmi_command_id { WMI_BF_CTRL_CMDID = 0x862, WMI_NOTIFY_REQ_CMDID = 0x863, WMI_GET_STATUS_CMDID = 0x864, + WMI_GET_RF_STATUS_CMDID = 0x866, + WMI_GET_BASEBAND_TYPE_CMDID = 0x867, WMI_UNIT_TEST_CMDID = 0x900, WMI_HICCUP_CMDID = 0x901, WMI_FLASH_READ_CMDID = 0x902, WMI_FLASH_WRITE_CMDID = 0x903, + /* Power management */ + WMI_TRAFFIC_DEFERRAL_CMDID = 0x904, + WMI_TRAFFIC_RESUME_CMDID = 0x905, /* P2P */ WMI_P2P_CFG_CMDID = 0x910, WMI_PORT_ALLOCATE_CMDID = 0x911, @@ -150,6 +157,19 @@ enum wmi_command_id { WMI_PCP_START_CMDID = 0x918, WMI_PCP_STOP_CMDID = 0x919, WMI_GET_PCP_FACTOR_CMDID = 0x91B, + /* Power Save Configuration Commands */ + WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C, + /* Not supported yet */ + WMI_PS_DEV_CFG_CMDID = 0x91D, + /* Not supported yet */ + WMI_PS_DEV_CFG_READ_CMDID = 0x91E, + /* Per MAC Power Save Configuration commands + * Not supported yet + */ + WMI_PS_MID_CFG_CMDID = 0x91F, + /* Not supported yet */ + WMI_PS_MID_CFG_READ_CMDID = 0x920, + WMI_RS_CFG_CMDID = 0x921, WMI_SET_MAC_ADDRESS_CMDID = 0xF003, WMI_ABORT_SCAN_CMDID = 0xF007, WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, @@ -291,9 +311,8 @@ enum wmi_scan_type { /* WMI_START_SCAN_CMDID */ struct wmi_start_scan_cmd { u8 direct_scan_mac_addr[WMI_MAC_LEN]; - /* DMG Beacon frame is transmitted during active scanning */ + /* run scan with discovery beacon. Relevant for ACTIVE scan only. */ u8 discovery_mode; - /* reserved */ u8 reserved; /* Max duration in the home channel(ms) */ __le32 dwell_time; @@ -453,6 +472,12 @@ struct wmi_port_delete_cmd { u8 reserved[3]; } __packed; +/* WMI_TRAFFIC_DEFERRAL_CMDID */ +struct wmi_traffic_deferral_cmd { + /* Bit vector: bit[0] - wake on Unicast, bit[1] - wake on Broadcast */ + u8 wakeup_trigger; +} __packed; + /* WMI_P2P_CFG_CMDID */ enum wmi_discovery_mode { WMI_DISCOVERY_MODE_NON_OFFLOAD = 0x00, @@ -822,81 +847,99 @@ struct wmi_pmc_cmd { * List of Events (target to host) */ enum wmi_event_id { - WMI_READY_EVENTID = 0x1001, - WMI_CONNECT_EVENTID = 0x1002, - WMI_DISCONNECT_EVENTID = 0x1003, - WMI_SCAN_COMPLETE_EVENTID = 0x100A, - WMI_REPORT_STATISTICS_EVENTID = 0x100B, - WMI_RD_MEM_RSP_EVENTID = 0x1800, - WMI_FW_READY_EVENTID = 0x1801, - WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200, - WMI_ECHO_RSP_EVENTID = 0x1803, - WMI_FS_TUNE_DONE_EVENTID = 0x180A, - WMI_CORR_MEASURE_EVENTID = 0x180B, - WMI_READ_RSSI_EVENTID = 0x180C, - WMI_TEMP_SENSE_DONE_EVENTID = 0x180E, - WMI_DC_CALIB_DONE_EVENTID = 0x180F, - WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, - WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, - WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, - WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, - WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, - WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, - WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181A, - WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181D, - WMI_RF_RX_TEST_DONE_EVENTID = 0x181E, - WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, - WMI_VRING_CFG_DONE_EVENTID = 0x1821, - WMI_BA_STATUS_EVENTID = 0x1823, - WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, - WMI_RCP_ADDBA_RESP_SENT_EVENTID = 0x1825, - WMI_DELBA_EVENTID = 0x1826, - WMI_GET_SSID_EVENTID = 0x1828, - WMI_GET_PCP_CHANNEL_EVENTID = 0x182A, - WMI_SW_TX_COMPLETE_EVENTID = 0x182B, - WMI_READ_MAC_RXQ_EVENTID = 0x1830, - WMI_READ_MAC_TXQ_EVENTID = 0x1831, - WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, - WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, - WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, - WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836, - WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, - WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, - WMI_RS_MGMT_DONE_EVENTID = 0x1852, - WMI_RF_MGMT_STATUS_EVENTID = 0x1853, - WMI_THERMAL_THROTTLING_STATUS_EVENTID = 0x1855, - WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, - WMI_RX_MGMT_PACKET_EVENTID = 0x1840, - WMI_TX_MGMT_PACKET_EVENTID = 0x1841, - WMI_OTP_READ_RESULT_EVENTID = 0x1856, - WMI_LED_CFG_DONE_EVENTID = 0x1858, + WMI_READY_EVENTID = 0x1001, + WMI_CONNECT_EVENTID = 0x1002, + WMI_DISCONNECT_EVENTID = 0x1003, + WMI_SCAN_COMPLETE_EVENTID = 0x100A, + WMI_REPORT_STATISTICS_EVENTID = 0x100B, + WMI_RD_MEM_RSP_EVENTID = 0x1800, + WMI_FW_READY_EVENTID = 0x1801, + WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200, + WMI_ECHO_RSP_EVENTID = 0x1803, + WMI_FS_TUNE_DONE_EVENTID = 0x180A, + WMI_CORR_MEASURE_EVENTID = 0x180B, + WMI_READ_RSSI_EVENTID = 0x180C, + WMI_TEMP_SENSE_DONE_EVENTID = 0x180E, + WMI_DC_CALIB_DONE_EVENTID = 0x180F, + WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, + WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, + WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, + WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, + WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, + WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, + WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181A, + WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181D, + WMI_RF_RX_TEST_DONE_EVENTID = 0x181E, + WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, + WMI_VRING_CFG_DONE_EVENTID = 0x1821, + WMI_BA_STATUS_EVENTID = 0x1823, + WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, + WMI_RCP_ADDBA_RESP_SENT_EVENTID = 0x1825, + WMI_DELBA_EVENTID = 0x1826, + WMI_GET_SSID_EVENTID = 0x1828, + WMI_GET_PCP_CHANNEL_EVENTID = 0x182A, + WMI_SW_TX_COMPLETE_EVENTID = 0x182B, + WMI_READ_MAC_RXQ_EVENTID = 0x1830, + WMI_READ_MAC_TXQ_EVENTID = 0x1831, + WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, + WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, + WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, + WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836, + WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, + WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, + WMI_RS_MGMT_DONE_EVENTID = 0x1852, + WMI_RF_MGMT_STATUS_EVENTID = 0x1853, + WMI_THERMAL_THROTTLING_STATUS_EVENTID = 0x1855, + WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, + WMI_RX_MGMT_PACKET_EVENTID = 0x1840, + WMI_TX_MGMT_PACKET_EVENTID = 0x1841, + WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID = 0x1842, + WMI_LINK_MAINTAIN_CFG_READ_DONE_EVENTID = 0x1843, + WMI_OTP_READ_RESULT_EVENTID = 0x1856, + WMI_LED_CFG_DONE_EVENTID = 0x1858, /* Performance monitoring events */ - WMI_DATA_PORT_OPEN_EVENTID = 0x1860, - WMI_WBE_LINK_DOWN_EVENTID = 0x1861, - WMI_BF_CTRL_DONE_EVENTID = 0x1862, - WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, - WMI_GET_STATUS_DONE_EVENTID = 0x1864, - WMI_VRING_EN_EVENTID = 0x1865, - WMI_UNIT_TEST_EVENTID = 0x1900, - WMI_FLASH_READ_DONE_EVENTID = 0x1902, - WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, + WMI_DATA_PORT_OPEN_EVENTID = 0x1860, + WMI_WBE_LINK_DOWN_EVENTID = 0x1861, + WMI_BF_CTRL_DONE_EVENTID = 0x1862, + WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, + WMI_GET_STATUS_DONE_EVENTID = 0x1864, + WMI_VRING_EN_EVENTID = 0x1865, + WMI_GET_RF_STATUS_EVENTID = 0x1866, + WMI_GET_BASEBAND_TYPE_EVENTID = 0x1867, + WMI_UNIT_TEST_EVENTID = 0x1900, + WMI_FLASH_READ_DONE_EVENTID = 0x1902, + WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, + /* Power management */ + WMI_TRAFFIC_DEFERRAL_EVENTID = 0x1904, + WMI_TRAFFIC_RESUME_EVENTID = 0x1905, /* P2P */ - WMI_P2P_CFG_DONE_EVENTID = 0x1910, - WMI_PORT_ALLOCATED_EVENTID = 0x1911, - WMI_PORT_DELETED_EVENTID = 0x1912, - WMI_LISTEN_STARTED_EVENTID = 0x1914, - WMI_SEARCH_STARTED_EVENTID = 0x1915, - WMI_DISCOVERY_STARTED_EVENTID = 0x1916, - WMI_DISCOVERY_STOPPED_EVENTID = 0x1917, - WMI_PCP_STARTED_EVENTID = 0x1918, - WMI_PCP_STOPPED_EVENTID = 0x1919, - WMI_PCP_FACTOR_EVENTID = 0x191A, - WMI_SET_CHANNEL_EVENTID = 0x9000, - WMI_ASSOC_REQ_EVENTID = 0x9001, - WMI_EAPOL_RX_EVENTID = 0x9002, - WMI_MAC_ADDR_RESP_EVENTID = 0x9003, - WMI_FW_VER_EVENTID = 0x9004, - WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005, + WMI_P2P_CFG_DONE_EVENTID = 0x1910, + WMI_PORT_ALLOCATED_EVENTID = 0x1911, + WMI_PORT_DELETED_EVENTID = 0x1912, + WMI_LISTEN_STARTED_EVENTID = 0x1914, + WMI_SEARCH_STARTED_EVENTID = 0x1915, + WMI_DISCOVERY_STARTED_EVENTID = 0x1916, + WMI_DISCOVERY_STOPPED_EVENTID = 0x1917, + WMI_PCP_STARTED_EVENTID = 0x1918, + WMI_PCP_STOPPED_EVENTID = 0x1919, + WMI_PCP_FACTOR_EVENTID = 0x191A, + /* Power Save Configuration Events */ + WMI_PS_DEV_PROFILE_CFG_EVENTID = 0x191C, + /* Not supported yet */ + WMI_PS_DEV_CFG_EVENTID = 0x191D, + /* Not supported yet */ + WMI_PS_DEV_CFG_READ_EVENTID = 0x191E, + /* Not supported yet */ + WMI_PS_MID_CFG_EVENTID = 0x191F, + /* Not supported yet */ + WMI_PS_MID_CFG_READ_EVENTID = 0x1920, + WMI_RS_CFG_DONE_EVENTID = 0x1921, + WMI_SET_CHANNEL_EVENTID = 0x9000, + WMI_ASSOC_REQ_EVENTID = 0x9001, + WMI_EAPOL_RX_EVENTID = 0x9002, + WMI_MAC_ADDR_RESP_EVENTID = 0x9003, + WMI_FW_VER_EVENTID = 0x9004, + WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005, }; /* Events data structures */ @@ -943,10 +986,78 @@ struct wmi_get_status_done_event { /* WMI_FW_VER_EVENTID */ struct wmi_fw_ver_event { - u8 major; - u8 minor; - __le16 subminor; - __le16 build; + /* FW image version */ + __le32 fw_major; + __le32 fw_minor; + __le32 fw_subminor; + __le32 fw_build; + /* FW image build time stamp */ + __le32 hour; + __le32 minute; + __le32 second; + __le32 day; + __le32 month; + __le32 year; + /* Boot Loader image version */ + __le32 bl_major; + __le32 bl_minor; + __le32 bl_subminor; + __le32 bl_build; +} __packed; + +/* WMI_GET_RF_STATUS_EVENTID */ +enum rf_type { + RF_UNKNOWN = 0x00, + RF_MARLON = 0x01, + RF_SPARROW = 0x02, +}; + +/* WMI_GET_RF_STATUS_EVENTID */ +enum board_file_rf_type { + BF_RF_MARLON = 0x00, + BF_RF_SPARROW = 0x01, +}; + +/* WMI_GET_RF_STATUS_EVENTID */ +enum rf_status { + RF_OK = 0x00, + RF_NO_COMM = 0x01, + RF_WRONG_BOARD_FILE = 0x02, +}; + +/* WMI_GET_RF_STATUS_EVENTID */ +struct wmi_get_rf_status_event { + /* enum rf_type */ + __le32 rf_type; + /* attached RFs bit vector */ + __le32 attached_rf_vector; + /* enabled RFs bit vector */ + __le32 enabled_rf_vector; + /* enum rf_status, refers to enabled RFs */ + u8 rf_status[32]; + /* enum board file RF type */ + __le32 board_file_rf_type; + /* board file platform type */ + __le32 board_file_platform_type; + /* board file version */ + __le32 board_file_version; + __le32 reserved[2]; +} __packed; + +/* WMI_GET_BASEBAND_TYPE_EVENTID */ +enum baseband_type { + BASEBAND_UNKNOWN = 0x00, + BASEBAND_SPARROW_M_A0 = 0x03, + BASEBAND_SPARROW_M_A1 = 0x04, + BASEBAND_SPARROW_M_B0 = 0x05, + BASEBAND_SPARROW_M_C0 = 0x06, + BASEBAND_SPARROW_M_D0 = 0x07, +}; + +/* WMI_GET_BASEBAND_TYPE_EVENTID */ +struct wmi_get_baseband_type_event { + /* enum baseband_type */ + __le32 baseband_type; } __packed; /* WMI_MAC_ADDR_RESP_EVENTID */ @@ -1410,4 +1521,375 @@ struct wmi_led_cfg_done_event { __le32 status; } __packed; +#define WMI_NUM_MCS (13) + +/* Rate search parameters configuration per connection */ +struct wmi_rs_cfg { + /* The maximal allowed PER for each MCS + * MCS will be considered as failed if PER during RS is higher + */ + u8 per_threshold[WMI_NUM_MCS]; + /* Number of MPDUs for each MCS + * this is the minimal statistic required to make an educated + * decision + */ + u8 min_frame_cnt[WMI_NUM_MCS]; + /* stop threshold [0-100] */ + u8 stop_th; + /* MCS1 stop threshold [0-100] */ + u8 mcs1_fail_th; + u8 max_back_failure_th; + /* Debug feature for disabling internal RS trigger (which is + * currently triggered by BF Done) + */ + u8 dbg_disable_internal_trigger; + __le32 back_failure_mask; + __le32 mcs_en_vec; +} __packed; + +/* WMI_RS_CFG_CMDID */ +struct wmi_rs_cfg_cmd { + /* connection id */ + u8 cid; + /* enable or disable rate search */ + u8 rs_enable; + /* rate search configuration */ + struct wmi_rs_cfg rs_cfg; +} __packed; + +/* WMI_RS_CFG_DONE_EVENTID */ +struct wmi_rs_cfg_done_event { + u8 cid; + /* enum wmi_fw_status */ + u8 status; + u8 reserved[2]; +} __packed; + +/* broadcast connection ID */ +#define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST (0xFFFFFFFF) + +/* Types wmi_link_maintain_cfg presets for WMI_LINK_MAINTAIN_CFG_WRITE_CMD */ +enum wmi_link_maintain_cfg_type { + /* AP/PCP default normal (non-FST) configuration settings */ + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_NORMAL_AP = 0x00, + /* AP/PCP default FST configuration settings */ + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_FST_AP = 0x01, + /* STA default normal (non-FST) configuration settings */ + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_NORMAL_STA = 0x02, + /* STA default FST configuration settings */ + WMI_LINK_MAINTAIN_CFG_TYPE_DEFAULT_FST_STA = 0x03, + /* custom configuration settings */ + WMI_LINK_MAINTAIN_CFG_TYPE_CUSTOM = 0x04, + /* number of defined configuration types */ + WMI_LINK_MAINTAIN_CFG_TYPES_NUM = 0x05, +}; + +/* Response status codes for WMI_LINK_MAINTAIN_CFG_WRITE/READ commands */ +enum wmi_link_maintain_cfg_response_status { + /* WMI_LINK_MAINTAIN_CFG_WRITE/READ command successfully accomplished + */ + WMI_LINK_MAINTAIN_CFG_RESPONSE_STATUS_OK = 0x00, + /* ERROR due to bad argument in WMI_LINK_MAINTAIN_CFG_WRITE/READ + * command request + */ + WMI_LINK_MAINTAIN_CFG_RESPONSE_STATUS_BAD_ARGUMENT = 0x01, +}; + +/* Link Loss and Keep Alive configuration */ +struct wmi_link_maintain_cfg { + /* link_loss_enable_detectors_vec */ + __le32 link_loss_enable_detectors_vec; + /* detectors check period usec */ + __le32 check_link_loss_period_usec; + /* max allowed tx ageing */ + __le32 tx_ageing_threshold_usec; + /* keep alive period for high SNR */ + __le32 keep_alive_period_usec_high_snr; + /* keep alive period for low SNR */ + __le32 keep_alive_period_usec_low_snr; + /* lower snr limit for keep alive period update */ + __le32 keep_alive_snr_threshold_low_db; + /* upper snr limit for keep alive period update */ + __le32 keep_alive_snr_threshold_high_db; + /* num of successive bad bcons causing link-loss */ + __le32 bad_beacons_num_threshold; + /* SNR limit for bad_beacons_detector */ + __le32 bad_beacons_snr_threshold_db; +} __packed; + +/* WMI_LINK_MAINTAIN_CFG_WRITE_CMDID */ +struct wmi_link_maintain_cfg_write_cmd { + /* enum wmi_link_maintain_cfg_type_e - type of requested default + * configuration to be applied + */ + __le32 cfg_type; + /* requested connection ID or WMI_LINK_MAINTAIN_CFG_CID_BROADCAST */ + __le32 cid; + /* custom configuration settings to be applied (relevant only if + * cfg_type==WMI_LINK_MAINTAIN_CFG_TYPE_CUSTOM) + */ + struct wmi_link_maintain_cfg lm_cfg; +} __packed; + +/* WMI_LINK_MAINTAIN_CFG_READ_CMDID */ +struct wmi_link_maintain_cfg_read_cmd { + /* connection ID which configuration settings are requested */ + __le32 cid; +} __packed; + +/* WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID */ +struct wmi_link_maintain_cfg_write_done_event { + /* requested connection ID */ + __le32 cid; + /* wmi_link_maintain_cfg_response_status_e - write status */ + __le32 status; +} __packed; + +/* \WMI_LINK_MAINTAIN_CFG_READ_DONE_EVENT */ +struct wmi_link_maintain_cfg_read_done_event { + /* requested connection ID */ + __le32 cid; + /* wmi_link_maintain_cfg_response_status_e - read status */ + __le32 status; + /* Retrieved configuration settings */ + struct wmi_link_maintain_cfg lm_cfg; +} __packed; + +enum wmi_traffic_deferral_status { + WMI_TRAFFIC_DEFERRAL_APPROVED = 0x0, + WMI_TRAFFIC_DEFERRAL_REJECTED = 0x1, +}; + +/* WMI_TRAFFIC_DEFERRAL_EVENTID */ +struct wmi_traffic_deferral_event { + /* enum wmi_traffic_deferral_status_e */ + u8 status; +} __packed; + +enum wmi_traffic_resume_status { + WMI_TRAFFIC_RESUME_SUCCESS = 0x0, + WMI_TRAFFIC_RESUME_FAILED = 0x1, +}; + +/* WMI_TRAFFIC_RESUME_EVENTID */ +struct wmi_traffic_resume_event { + /* enum wmi_traffic_resume_status_e */ + u8 status; +} __packed; + +/* Power Save command completion status codes */ +enum wmi_ps_cfg_cmd_status { + WMI_PS_CFG_CMD_STATUS_SUCCESS = 0x00, + WMI_PS_CFG_CMD_STATUS_BAD_PARAM = 0x01, + /* other error */ + WMI_PS_CFG_CMD_STATUS_ERROR = 0x02, +}; + +/* Device Power Save Profiles */ +enum wmi_ps_profile_type { + WMI_PS_PROFILE_TYPE_DEFAULT = 0x00, + WMI_PS_PROFILE_TYPE_PS_DISABLED = 0x01, + WMI_PS_PROFILE_TYPE_MAX_PS = 0x02, + WMI_PS_PROFILE_TYPE_LOW_LATENCY_PS = 0x03, +}; + +/* WMI_PS_DEV_PROFILE_CFG_CMDID + * + * Power save profile to be used by the device + * + * Returned event: + * - WMI_PS_DEV_PROFILE_CFG_EVENTID + */ +struct wmi_ps_dev_profile_cfg_cmd { + /* wmi_ps_profile_type_e */ + u8 ps_profile; + u8 reserved[3]; +} __packed; + +/* WMI_PS_DEV_PROFILE_CFG_EVENTID */ +struct wmi_ps_dev_profile_cfg_event { + /* wmi_ps_cfg_cmd_status_e */ + __le32 status; +} __packed; + +enum wmi_ps_level { + WMI_PS_LEVEL_DEEP_SLEEP = 0x00, + WMI_PS_LEVEL_SHALLOW_SLEEP = 0x01, + /* awake = all PS mechanisms are disabled */ + WMI_PS_LEVEL_AWAKE = 0x02, +}; + +enum wmi_ps_deep_sleep_clk_level { + /* 33k */ + WMI_PS_DEEP_SLEEP_CLK_LEVEL_RTC = 0x00, + /* 10k */ + WMI_PS_DEEP_SLEEP_CLK_LEVEL_OSC = 0x01, + /* @RTC Low latency */ + WMI_PS_DEEP_SLEEP_CLK_LEVEL_RTC_LT = 0x02, + WMI_PS_DEEP_SLEEP_CLK_LEVEL_XTAL = 0x03, + WMI_PS_DEEP_SLEEP_CLK_LEVEL_SYSCLK = 0x04, + /* Not Applicable */ + WMI_PS_DEEP_SLEEP_CLK_LEVEL_N_A = 0xFF, +}; + +/* Response by the FW to a D3 entry request */ +enum wmi_ps_d3_resp_policy { + WMI_PS_D3_RESP_POLICY_DEFAULT = 0x00, + /* debug -D3 req is always denied */ + WMI_PS_D3_RESP_POLICY_DENIED = 0x01, + /* debug -D3 req is always approved */ + WMI_PS_D3_RESP_POLICY_APPROVED = 0x02, +}; + +/* Device common power save configurations */ +struct wmi_ps_dev_cfg { + /* lowest level of PS allowed while unassociated, enum wmi_ps_level_e + */ + u8 ps_unassoc_min_level; + /* lowest deep sleep clock level while nonassoc, enum + * wmi_ps_deep_sleep_clk_level_e + */ + u8 ps_unassoc_deep_sleep_min_level; + /* lowest level of PS allowed while associated, enum wmi_ps_level_e */ + u8 ps_assoc_min_level; + /* lowest deep sleep clock level while assoc, enum + * wmi_ps_deep_sleep_clk_level_e + */ + u8 ps_assoc_deep_sleep_min_level; + /* enum wmi_ps_deep_sleep_clk_level_e */ + u8 ps_assoc_low_latency_ds_min_level; + /* enum wmi_ps_d3_resp_policy_e */ + u8 ps_D3_response_policy; + /* BOOL */ + u8 ps_D3_pm_pme_enabled; + /* BOOL */ + u8 ps_halp_enable; + u8 ps_deep_sleep_enter_thresh_msec; + /* BOOL */ + u8 ps_voltage_scaling_en; +} __packed; + +/* WMI_PS_DEV_CFG_CMDID + * + * Configure common Power Save parameters of the device and all MIDs. + * + * Returned event: + * - WMI_PS_DEV_CFG_EVENTID + */ +struct wmi_ps_dev_cfg_cmd { + /* Device Power Save configuration to be applied */ + struct wmi_ps_dev_cfg ps_dev_cfg; + /* alignment to 32b */ + u8 reserved[2]; +} __packed; + +/* WMI_PS_DEV_CFG_EVENTID */ +struct wmi_ps_dev_cfg_event { + /* wmi_ps_cfg_cmd_status_e */ + __le32 status; +} __packed; + +/* WMI_PS_DEV_CFG_READ_CMDID + * + * request to retrieve device Power Save configuration + * (WMI_PS_DEV_CFG_CMD params) + * + * Returned event: + * - WMI_PS_DEV_CFG_READ_EVENTID + */ +struct wmi_ps_dev_cfg_read_cmd { + __le32 reserved; +} __packed; + +/* WMI_PS_DEV_CFG_READ_EVENTID */ +struct wmi_ps_dev_cfg_read_event { + /* wmi_ps_cfg_cmd_status_e */ + __le32 status; + /* Retrieved device Power Save configuration (WMI_PS_DEV_CFG_CMD + * params) + */ + struct wmi_ps_dev_cfg dev_ps_cfg; + /* alignment to 32b */ + u8 reserved[2]; +} __packed; + +/* Per Mac Power Save configurations */ +struct wmi_ps_mid_cfg { + /* Low power RX in BTI is enabled, BOOL */ + u8 beacon_lprx_enable; + /* Sync to sector ID enabled, BOOL */ + u8 beacon_sync_to_sectorId_enable; + /* Low power RX in DTI is enabled, BOOL */ + u8 frame_exchange_lprx_enable; + /* Sleep Cycle while in scheduled PS, 1-31 */ + u8 scheduled_sleep_cycle_pow2; + /* Stay Awake for k BIs every (sleep_cycle - k) BIs, 1-31 */ + u8 scheduled_num_of_awake_bis; + u8 am_to_traffic_load_thresh_mbp; + u8 traffic_to_am_load_thresh_mbps; + u8 traffic_to_am_num_of_no_traffic_bis; + /* BOOL */ + u8 continuous_traffic_psm; + __le16 no_traffic_to_min_usec; + __le16 no_traffic_to_max_usec; + __le16 snoozing_sleep_interval_milisec; + u8 max_no_data_awake_events; + /* Trigger WEB after k failed beacons */ + u8 num_of_failed_beacons_rx_to_trigger_web; + /* Trigger BF after k failed beacons */ + u8 num_of_failed_beacons_rx_to_trigger_bf; + /* Trigger SOB after k successful beacons */ + u8 num_of_successful_beacons_rx_to_trigger_sob; +} __packed; + +/* WMI_PS_MID_CFG_CMDID + * + * Configure Power Save parameters of a specific MID. + * These parameters are relevant for the specific BSS this MID belongs to. + * + * Returned event: + * - WMI_PS_MID_CFG_EVENTID + */ +struct wmi_ps_mid_cfg_cmd { + /* MAC ID */ + u8 mid; + /* mid PS configuration to be applied */ + struct wmi_ps_mid_cfg ps_mid_cfg; +} __packed; + +/* WMI_PS_MID_CFG_EVENTID */ +struct wmi_ps_mid_cfg_event { + /* MAC ID */ + u8 mid; + /* alignment to 32b */ + u8 reserved[3]; + /* wmi_ps_cfg_cmd_status_e */ + __le32 status; +} __packed; + +/* WMI_PS_MID_CFG_READ_CMDID + * + * request to retrieve Power Save configuration of mid + * (WMI_PS_MID_CFG_CMD params) + * + * Returned event: + * - WMI_PS_MID_CFG_READ_EVENTID + */ +struct wmi_ps_mid_cfg_read_cmd { + /* MAC ID */ + u8 mid; + /* alignment to 32b */ + u8 reserved[3]; +} __packed; + +/* WMI_PS_MID_CFG_READ_EVENTID */ +struct wmi_ps_mid_cfg_read_event { + /* MAC ID */ + u8 mid; + /* Retrieved MID Power Save configuration(WMI_PS_MID_CFG_CMD params) */ + struct wmi_ps_mid_cfg mid_ps_cfg; + /* wmi_ps_cfg_cmd_status_e */ + __le32 status; +} __packed; + #endif /* __WILOCITY_WMI_H__ */ From 4e5eb632f476728e0566ca7c6efca5535adbaf98 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Mon, 5 Sep 2016 10:54:18 +0300 Subject: [PATCH 02/10] wil6210: support rx key setting for all TIDs According to the spec the PN should be calculated per TID. In the current implementation, the PN and key_set were set only for TID 0, therefore only traffic for TID 0 was supported. In order to support all TIDs, the key_set and PN should be set for all the TIDs. Change-Id: Ib5c55a37208d76505658635b12afc88552d5a220 Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 74b6ac586d9cb7f45c894841e4204b3648ae865c Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 116 ++++++++++++++------ 1 file changed, 81 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 18e95148e891..9ac56013a412 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -760,14 +760,11 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, return rc; } -static struct wil_tid_crypto_rx_single * -wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index, - enum wmi_key_usage key_usage, const u8 *mac_addr) +static struct wil_sta_info * +wil_find_sta_by_key_usage(struct wil6210_priv *wil, + enum wmi_key_usage key_usage, const u8 *mac_addr) { int cid = -EINVAL; - int tid = 0; - struct wil_sta_info *s; - struct wil_tid_crypto_rx *c; if (key_usage == WMI_KEY_USE_TX_GROUP) return NULL; /* not needed */ @@ -778,18 +775,72 @@ wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index, else if (key_usage == WMI_KEY_USE_RX_GROUP) cid = wil_find_cid_by_idx(wil, 0); if (cid < 0) { - wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr, - key_usage_str[key_usage], key_index); + wil_err(wil, "No CID for %pM %s\n", mac_addr, + key_usage_str[key_usage]); return ERR_PTR(cid); } - s = &wil->sta[cid]; - if (key_usage == WMI_KEY_USE_PAIRWISE) - c = &s->tid_crypto_rx[tid]; - else - c = &s->group_crypto_rx; + return &wil->sta[cid]; +} - return &c->key_id[key_index]; +static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage, + struct wil_sta_info *cs, + struct key_params *params) +{ + struct wil_tid_crypto_rx_single *cc; + int tid; + + if (!cs) + return; + + switch (key_usage) { + case WMI_KEY_USE_PAIRWISE: + for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { + cc = &cs->tid_crypto_rx[tid].key_id[key_index]; + if (params->seq) + memcpy(cc->pn, params->seq, + IEEE80211_GCMP_PN_LEN); + else + memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN); + cc->key_set = true; + } + break; + case WMI_KEY_USE_RX_GROUP: + cc = &cs->group_crypto_rx.key_id[key_index]; + if (params->seq) + memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN); + else + memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN); + cc->key_set = true; + break; + default: + break; + } +} + +static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage, + struct wil_sta_info *cs) +{ + struct wil_tid_crypto_rx_single *cc; + int tid; + + if (!cs) + return; + + switch (key_usage) { + case WMI_KEY_USE_PAIRWISE: + for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { + cc = &cs->tid_crypto_rx[tid].key_id[key_index]; + cc->key_set = false; + } + break; + case WMI_KEY_USE_RX_GROUP: + cc = &cs->group_crypto_rx.key_id[key_index]; + cc->key_set = false; + break; + default: + break; + } } static int wil_cfg80211_add_key(struct wiphy *wiphy, @@ -801,24 +852,26 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); - struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil, - key_index, - key_usage, - mac_addr); + struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, + mac_addr); + + if (!params) { + wil_err(wil, "NULL params\n"); + return -EINVAL; + } wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__, mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); - if (IS_ERR(cc)) { + if (IS_ERR(cs)) { wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n", __func__, mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); return -EINVAL; } - if (cc) - cc->key_set = false; + wil_del_rx_key(key_index, key_usage, cs); if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { wil_err(wil, @@ -831,13 +884,8 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len, params->key, key_usage); - if ((rc == 0) && cc) { - if (params->seq) - memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN); - else - memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN); - cc->key_set = true; - } + if (!rc) + wil_set_crypto_rx(key_index, key_usage, cs, params); return rc; } @@ -849,20 +897,18 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); - struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil, - key_index, - key_usage, - mac_addr); + struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, + mac_addr); wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr, key_usage_str[key_usage], key_index); - if (IS_ERR(cc)) + if (IS_ERR(cs)) wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__, mac_addr, key_usage_str[key_usage], key_index); - if (!IS_ERR_OR_NULL(cc)) - cc->key_set = false; + if (!IS_ERR_OR_NULL(cs)) + wil_del_rx_key(key_index, key_usage, cs); return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage); } From ada668c8a16c9106a0211b7bdd96b4dbb007ce2a Mon Sep 17 00:00:00 2001 From: Lior David Date: Mon, 5 Sep 2016 10:58:43 +0300 Subject: [PATCH 03/10] wil6210: change HALP logging category to IRQ Change the logging category of HALP functions from MISC to IRQ, since the HALP mechanism is closely related to interrupts. Both HALP and IRQ create a heavy load of logging messages when enabled, so their logging is typically disabled during normal debug scenarios. Having them in the same logging category will make it easier to disable logging for both in one go. Change-Id: I51e58438672a45d210df5db3ac813e656cb525df Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: ef86f249fa4980fc78fe1546e45d8cab6be424b6 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/interrupt.c | 4 +-- drivers/net/wireless/ath/wil6210/main.c | 26 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index f10c47dcbde5..64046e0bd0a2 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -599,7 +599,7 @@ void wil6210_clear_irq(struct wil6210_priv *wil) void wil6210_set_halp(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), BIT_DMA_EP_MISC_ICR_HALP); @@ -607,7 +607,7 @@ void wil6210_set_halp(struct wil6210_priv *wil) void wil6210_clear_halp(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), BIT_DMA_EP_MISC_ICR_HALP); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 49bd9b45ce22..41978f2f407c 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1113,8 +1113,8 @@ void wil_halp_vote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, - wil->halp.ref_cnt); + wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); if (++wil->halp.ref_cnt == 1) { wil6210_set_halp(wil); @@ -1124,15 +1124,15 @@ void wil_halp_vote(struct wil6210_priv *wil) /* Mask HALP as done in case the interrupt is raised */ wil6210_mask_halp(wil); } else { - wil_dbg_misc(wil, - "%s: HALP vote completed after %d ms\n", - __func__, - jiffies_to_msecs(to_jiffies - rc)); + wil_dbg_irq(wil, + "%s: HALP vote completed after %d ms\n", + __func__, + jiffies_to_msecs(to_jiffies - rc)); } } - wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, - wil->halp.ref_cnt); + wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); } @@ -1143,16 +1143,16 @@ void wil_halp_unvote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, - wil->halp.ref_cnt); + wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); if (--wil->halp.ref_cnt == 0) { wil6210_clear_halp(wil); - wil_dbg_misc(wil, "%s: HALP unvote\n", __func__); + wil_dbg_irq(wil, "%s: HALP unvote\n", __func__); } - wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, - wil->halp.ref_cnt); + wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); } From ff026fee548310f383e84ee50ea434cdc133b6b5 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Wed, 7 Sep 2016 22:17:58 +0300 Subject: [PATCH 04/10] wil6210: fix stop p2p device handling fix stop p2p device handling to identify between search and listen and update the upper layers with the appropriate notification. The stop of p2p radio operations also needs to be performed in __wil_down. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: d35c2b6f8ffa75d430fd0fbbc5062f738c44f6e4 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Change-Id: I79f8522ae84dd209cb98c3bbc52cfaeb199dd342 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 21 +++++----- drivers/net/wireless/ath/wil6210/main.c | 2 +- drivers/net/wireless/ath/wil6210/p2p.c | 43 +++++++++++++++++++++ drivers/net/wireless/ath/wil6210/pcie_bus.c | 5 ++- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9ac56013a412..aad7039b00dc 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1409,19 +1409,16 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - u8 started; + struct wil_p2p_info *p2p = &wil->p2p; + + if (!p2p->p2p_dev_started) + return; wil_dbg_misc(wil, "%s: entered\n", __func__); mutex_lock(&wil->mutex); - started = wil_p2p_stop_discovery(wil); - if (started && wil->scan_request) { - cfg80211_scan_done(wil->scan_request, 1); - wil->scan_request = NULL; - wil->radio_wdev = wil->wdev; - } + wil_p2p_stop_radio_operations(wil); + p2p->p2p_dev_started = 0; mutex_unlock(&wil->mutex); - - wil->p2p.p2p_dev_started = 0; } static struct cfg80211_ops wil_cfg80211_ops = { @@ -1540,11 +1537,11 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil) mutex_lock(&wil->p2p_wdev_mutex); p2p_wdev = wil->p2p_wdev; + wil->p2p_wdev = NULL; + wil->radio_wdev = wil_to_wdev(wil); + mutex_unlock(&wil->p2p_wdev_mutex); if (p2p_wdev) { - wil->p2p_wdev = NULL; - wil->radio_wdev = wil_to_wdev(wil); cfg80211_unregister_wdev(p2p_wdev); kfree(p2p_wdev); } - mutex_unlock(&wil->p2p_wdev_mutex); } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 41978f2f407c..6d41e8de03b1 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1049,7 +1049,7 @@ int __wil_down(struct wil6210_priv *wil) } wil_enable_irq(wil); - (void)wil_p2p_stop_discovery(wil); + wil_p2p_stop_radio_operations(wil); if (wil->scan_request) { wil_dbg_misc(wil, "Abort scan_request 0x%p\n", diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 213b8259638c..42148da111f1 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -259,3 +259,46 @@ void wil_p2p_search_expired(struct work_struct *work) mutex_unlock(&wil->p2p_wdev_mutex); } } + +void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) +{ + struct wil_p2p_info *p2p = &wil->p2p; + + lockdep_assert_held(&wil->mutex); + + mutex_lock(&wil->p2p_wdev_mutex); + + if (wil->radio_wdev != wil->p2p_wdev) + goto out; + + if (!p2p->discovery_started) { + /* Regular scan on the p2p device */ + if (wil->scan_request && + wil->scan_request->wdev == wil->p2p_wdev) { + cfg80211_scan_done(wil->scan_request, 1); + wil->scan_request = NULL; + } + goto out; + } + + /* Search or listen on p2p device */ + mutex_unlock(&wil->p2p_wdev_mutex); + wil_p2p_stop_discovery(wil); + mutex_lock(&wil->p2p_wdev_mutex); + + if (wil->scan_request) { + /* search */ + cfg80211_scan_done(wil->scan_request, 1); + wil->scan_request = NULL; + } else { + /* listen */ + cfg80211_remain_on_channel_expired(wil->radio_wdev, + p2p->cookie, + &p2p->listen_chan, + GFP_KERNEL); + } + +out: + wil->radio_wdev = wil->wdev; + mutex_unlock(&wil->p2p_wdev_mutex); +} diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 7b5c4222bc33..5b7a9d2f0c29 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -20,6 +20,7 @@ #include #include #include "wil6210.h" +#include static bool use_msi = true; module_param(use_msi, bool, S_IRUGO); @@ -293,6 +294,9 @@ static void wil_pcie_remove(struct pci_dev *pdev) #endif /* CONFIG_PM */ wil6210_debugfs_remove(wil); + rtnl_lock(); + wil_p2p_wdev_free(wil); + rtnl_unlock(); wil_if_remove(wil); wil_if_pcie_disable(wil); pci_iounmap(pdev, csr); @@ -300,7 +304,6 @@ static void wil_pcie_remove(struct pci_dev *pdev) pci_disable_device(pdev); if (wil->platform_ops.uninit) wil->platform_ops.uninit(wil->platform_handle); - wil_p2p_wdev_free(wil); wil_if_free(wil); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 16e8ba570011..da9cbb2340e1 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -844,6 +844,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); void wil_p2p_listen_expired(struct work_struct *work); void wil_p2p_search_expired(struct work_struct *work); +void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); /* WMI for P2P */ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); From f3d407b89bf12b1247680a7da3110595ddb1079c Mon Sep 17 00:00:00 2001 From: Lazar Alexei Date: Mon, 5 Sep 2016 11:15:08 +0300 Subject: [PATCH 05/10] wil6210: Fix driver down flow Stations disconnection is executed as part of wil_reset so no need to do it in wil_down. Removal of the disconnect operation will also preserve the lock of wil->mutex during the whole reset flow and prevent handling of connect event while resetting. Set wil_status_resetting in earlier stage in the flow to prevent double resetting call in case communication with FW fails while bringing the interface down. Change-Id: Ifb92501aab14843309fed8e1214a867b2ccccfce Signed-off-by: Lazar Alexei Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: b0c0e688e523eba14abf21ac246b7dd88f5574fa Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/main.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6d41e8de03b1..01245b3f2821 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1034,10 +1034,10 @@ int wil_up(struct wil6210_priv *wil) int __wil_down(struct wil6210_priv *wil) { - int rc; - WARN_ON(!mutex_is_locked(&wil->mutex)); + set_bit(wil_status_resetting, wil->status); + if (wil->platform_ops.bus_request) wil->platform_ops.bus_request(wil->platform_handle, 0); @@ -1059,18 +1059,6 @@ int __wil_down(struct wil6210_priv *wil) wil->scan_request = NULL; } - if (test_bit(wil_status_fwconnected, wil->status) || - test_bit(wil_status_fwconnecting, wil->status)) { - - mutex_unlock(&wil->mutex); - rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, - WMI_DISCONNECT_EVENTID, NULL, 0, - WIL6210_DISCONNECT_TO_MS); - mutex_lock(&wil->mutex); - if (rc) - wil_err(wil, "timeout waiting for disconnect\n"); - } - wil_reset(wil, false); return 0; From dd2c4e67bf63d055ed058c3106459b6def329225 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Mon, 5 Sep 2016 11:20:05 +0300 Subject: [PATCH 06/10] wil6210: prevent usage of incorrect TX hwtail txdata->enabled is used in order to determine if the TX vring is valid. As the data transmit is handled in a different context, in case txdata->enabled is set before vring->hwtail is updated, an old or corrupted vring->hwtail can be used. Protect setting of txdata->enabled and vring->hwtail to prevent a case where TX vring start handling TX packets before setting vring->hwtail. Change-Id: Id17271823d167677a323dd1f52c7de4c6025b56e Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: dc90506f145875b9d88160802cc5fe06a7c79dda Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/txrx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index f2f6a404d3d1..4c38520d4dd2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -873,9 +873,12 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, rc = -EINVAL; goto out_free; } - vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); + spin_lock_bh(&txdata->lock); + vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); txdata->enabled = 1; + spin_unlock_bh(&txdata->lock); + if (txdata->dot1x_open && (agg_wsize >= 0)) wil_addba_tx_request(wil, id, agg_wsize); @@ -950,9 +953,11 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) rc = -EINVAL; goto out_free; } - vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); + spin_lock_bh(&txdata->lock); + vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); txdata->enabled = 1; + spin_unlock_bh(&txdata->lock); return 0; out_free: From 096ca9dc58d3b1d3375060fad8fa1c9efd63a534 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Wed, 7 Sep 2016 22:20:17 +0300 Subject: [PATCH 07/10] wil6210: fix wiphy registration sequence Currently wiphy structure is initialized and registered in wil_if_alloc, before some information is available such as MAC address and capabilities. As a result there is a small chance user space will get incorrect information from calls such as NL80211_CMD_GET_WIPHY. Fix this by seperating the registration and moving it to wil_if_add which is executed later, after all relevant information is known. Change-Id: Id38c8e21a853907c884bccd2978f2fd0a547a1ca Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 2690c4c0e83b1aa5aa8b8b258ae422b067720224 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 7 ----- drivers/net/wireless/ath/wil6210/main.c | 3 ++ drivers/net/wireless/ath/wil6210/netdev.c | 32 +++++++++++++++------ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index aad7039b00dc..ab3bc9d2ca23 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1503,14 +1503,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev) set_wiphy_dev(wdev->wiphy, dev); wil_wiphy_init(wdev->wiphy); - rc = wiphy_register(wdev->wiphy); - if (rc < 0) - goto out_failed_reg; - return wdev; -out_failed_reg: - wiphy_free(wdev->wiphy); out: kfree(wdev); @@ -1526,7 +1520,6 @@ void wil_wdev_free(struct wil6210_priv *wil) if (!wdev) return; - wiphy_unregister(wdev->wiphy); wiphy_free(wdev->wiphy); kfree(wdev); } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 01245b3f2821..4fed3ef44ee0 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -232,6 +232,9 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *wdev = wil->wdev; + if (unlikely(!ndev)) + return; + might_sleep(); wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, reason_code, from_event ? "+" : "-"); diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index bd4c17ca2484..81a4c6a684f5 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -185,13 +185,6 @@ void *wil_if_alloc(struct device *dev) SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; - netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, - WIL6210_NAPI_BUDGET); - netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, - WIL6210_NAPI_BUDGET); - - netif_tx_stop_all_queues(ndev); - return wil; out_priv: @@ -222,25 +215,46 @@ void wil_if_free(struct wil6210_priv *wil) int wil_if_add(struct wil6210_priv *wil) { + struct wireless_dev *wdev = wil_to_wdev(wil); + struct wiphy *wiphy = wdev->wiphy; struct net_device *ndev = wil_to_ndev(wil); int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "entered"); + + rc = wiphy_register(wiphy); + if (rc < 0) { + wil_err(wil, "failed to register wiphy, err %d\n", rc); + return rc; + } + + netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, + WIL6210_NAPI_BUDGET); + netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, + WIL6210_NAPI_BUDGET); + + netif_tx_stop_all_queues(ndev); rc = register_netdev(ndev); if (rc < 0) { dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); - return rc; + goto out_wiphy; } return 0; + +out_wiphy: + wiphy_unregister(wdev->wiphy); + return rc; } void wil_if_remove(struct wil6210_priv *wil) { struct net_device *ndev = wil_to_ndev(wil); + struct wireless_dev *wdev = wil_to_wdev(wil); wil_dbg_misc(wil, "%s()\n", __func__); unregister_netdev(ndev); + wiphy_unregister(wdev->wiphy); } From 043f51594b8c5874cb1f4550c1face3420484c97 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Wed, 7 Sep 2016 22:20:50 +0300 Subject: [PATCH 08/10] wil6210: fix protection of wil->scan_request Currently the places that check wil->scan_request and call cfg80211_scan_done are not consistently protected, so there is a risk that cfg80211_scan_done will be called with NULL scan_request, causing a kernel crash. Fix this by using p2p_wdev_mutex in few other places that access scan_request. This makes sense since scan_request may point to p2p_wdev, and it is not worth the extra complexity of adding a new mutex. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit 5ffae43208ec160e584117fabee2cddc5ad0e39a Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Change-Id: Ibc1e6dc2994268a60384b7d9bd459abc3791a0c4 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 3 +++ drivers/net/wireless/ath/wil6210/main.c | 4 ++++ drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- drivers/net/wireless/ath/wil6210/wmi.c | 4 ++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index ab3bc9d2ca23..60f2a2e541a9 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -354,10 +354,13 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", __func__, wdev, wdev->iftype); + mutex_lock(&wil->p2p_wdev_mutex); if (wil->scan_request) { wil_err(wil, "Already scanning\n"); + mutex_unlock(&wil->p2p_wdev_mutex); return -EAGAIN; } + mutex_unlock(&wil->p2p_wdev_mutex); /* check we are client side */ switch (wdev->iftype) { diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 4fed3ef44ee0..dd1dc0d226e6 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -855,6 +855,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) bitmap_zero(wil->status, wil_status_last); mutex_unlock(&wil->wmi_mutex); + mutex_lock(&wil->p2p_wdev_mutex); if (wil->scan_request) { wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); @@ -862,6 +863,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) cfg80211_scan_done(wil->scan_request, true); wil->scan_request = NULL; } + mutex_unlock(&wil->p2p_wdev_mutex); wil_mask_irq(wil); @@ -1054,6 +1056,7 @@ int __wil_down(struct wil6210_priv *wil) wil_p2p_stop_radio_operations(wil); + mutex_lock(&wil->p2p_wdev_mutex); if (wil->scan_request) { wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); @@ -1061,6 +1064,7 @@ int __wil_down(struct wil6210_priv *wil) cfg80211_scan_done(wil->scan_request, true); wil->scan_request = NULL; } + mutex_unlock(&wil->p2p_wdev_mutex); wil_reset(wil, false); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index da9cbb2340e1..de1b88555a3a 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -660,7 +660,7 @@ struct wil6210_priv { /* P2P_DEVICE vif */ struct wireless_dev *p2p_wdev; - struct mutex p2p_wdev_mutex; /* protect @p2p_wdev */ + struct mutex p2p_wdev_mutex; /* protect @p2p_wdev and @scan_request */ struct wireless_dev *radio_wdev; /* High Access Latency Policy voting */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index c9fef36977ca..0c5db9584159 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -424,6 +424,7 @@ static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, void *d, int len) { + mutex_lock(&wil->p2p_wdev_mutex); if (wil->scan_request) { struct wmi_scan_complete_event *data = d; bool aborted = (data->status != WMI_SCAN_SUCCESS); @@ -433,14 +434,13 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, wil->scan_request, aborted); del_timer_sync(&wil->scan_timer); - mutex_lock(&wil->p2p_wdev_mutex); cfg80211_scan_done(wil->scan_request, aborted); wil->radio_wdev = wil->wdev; - mutex_unlock(&wil->p2p_wdev_mutex); wil->scan_request = NULL; } else { wil_err(wil, "SCAN_COMPLETE while not scanning\n"); } + mutex_unlock(&wil->p2p_wdev_mutex); } static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) From 90499748e3a94314a3819407273a8c7315c49ba0 Mon Sep 17 00:00:00 2001 From: Lior David Date: Mon, 5 Sep 2016 11:50:24 +0300 Subject: [PATCH 09/10] wil6210: align to latest auto generated wmi.h Align to latest version of the auto generated wmi file describing the interface with FW. Change-Id: I169e0c94edf5df31336af1ede36900ec337f4314 Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 08989f9640a03939ec170916f80d371a8e3504b0 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/wmi.h | 292 +++++++++++++++++++++++++ 1 file changed, 292 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 349510cdb153..f430e8a80603 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -46,6 +46,16 @@ enum wmi_mid { MID_BROADCAST = 0xFF, }; +/* FW capability IDs + * Each ID maps to a bit in a 32-bit bitmask value provided by the FW to + * the host + */ +enum wmi_fw_capability { + WMI_FW_CAPABILITY_FTM = 0, + WMI_FW_CAPABILITY_PS_CONFIG = 1, + WMI_FW_CAPABILITY_MAX, +}; + /* WMI_CMD_HDR */ struct wmi_cmd_hdr { u8 mid; @@ -170,6 +180,13 @@ enum wmi_command_id { /* Not supported yet */ WMI_PS_MID_CFG_READ_CMDID = 0x920, WMI_RS_CFG_CMDID = 0x921, + WMI_GET_DETAILED_RS_RES_CMDID = 0x922, + WMI_AOA_MEAS_CMDID = 0x923, + WMI_TOF_SESSION_START_CMDID = 0x991, + WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, + WMI_TOF_SET_LCR_CMDID = 0x993, + WMI_TOF_SET_LCI_CMDID = 0x994, + WMI_TOF_CHANNEL_INFO_CMDID = 0x995, WMI_SET_MAC_ADDRESS_CMDID = 0xF003, WMI_ABORT_SCAN_CMDID = 0xF007, WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, @@ -843,6 +860,88 @@ struct wmi_pmc_cmd { __le64 mem_base; } __packed; +enum wmi_aoa_meas_type { + WMI_AOA_PHASE_MEAS = 0x00, + WMI_AOA_PHASE_AMP_MEAS = 0x01, +}; + +/* WMI_AOA_MEAS_CMDID */ +struct wmi_aoa_meas_cmd { + u8 mac_addr[WMI_MAC_LEN]; + /* channels IDs: + * 0 - 58320 MHz + * 1 - 60480 MHz + * 2 - 62640 MHz + */ + u8 channel; + /* enum wmi_aoa_meas_type */ + u8 aoa_meas_type; + __le32 meas_rf_mask; +} __packed; + +enum wmi_tof_burst_duration { + WMI_TOF_BURST_DURATION_250_USEC = 2, + WMI_TOF_BURST_DURATION_500_USEC = 3, + WMI_TOF_BURST_DURATION_1_MSEC = 4, + WMI_TOF_BURST_DURATION_2_MSEC = 5, + WMI_TOF_BURST_DURATION_4_MSEC = 6, + WMI_TOF_BURST_DURATION_8_MSEC = 7, + WMI_TOF_BURST_DURATION_16_MSEC = 8, + WMI_TOF_BURST_DURATION_32_MSEC = 9, + WMI_TOF_BURST_DURATION_64_MSEC = 10, + WMI_TOF_BURST_DURATION_128_MSEC = 11, + WMI_TOF_BURST_DURATION_NO_PREFERENCES = 15, +}; + +enum wmi_tof_session_start_flags { + WMI_TOF_SESSION_START_FLAG_SECURED = 0x1, + WMI_TOF_SESSION_START_FLAG_ASAP = 0x2, + WMI_TOF_SESSION_START_FLAG_LCI_REQ = 0x4, + WMI_TOF_SESSION_START_FLAG_LCR_REQ = 0x8, +}; + +/* WMI_TOF_SESSION_START_CMDID */ +struct wmi_ftm_dest_info { + u8 channel; + /* wmi_tof_session_start_flags_e */ + u8 flags; + u8 initial_token; + u8 num_of_ftm_per_burst; + u8 num_of_bursts_exp; + /* wmi_tof_burst_duration_e */ + u8 burst_duration; + /* Burst Period indicate interval between two consecutive burst + * instances, in units of 100 ms + */ + __le16 burst_period; + u8 dst_mac[WMI_MAC_LEN]; + __le16 reserved; +} __packed; + +/* WMI_TOF_SESSION_START_CMDID */ +struct wmi_tof_session_start_cmd { + __le32 session_id; + u8 num_of_aoa_measures; + u8 aoa_type; + __le16 num_of_dest; + u8 reserved[4]; + struct wmi_ftm_dest_info ftm_dest_info[0]; +} __packed; + +enum wmi_tof_channel_info_report_type { + WMI_TOF_CHANNEL_INFO_TYPE_CIR = 0x1, + WMI_TOF_CHANNEL_INFO_TYPE_RSSI = 0x2, + WMI_TOF_CHANNEL_INFO_TYPE_SNR = 0x4, + WMI_TOF_CHANNEL_INFO_TYPE_DEBUG_DATA = 0x8, + WMI_TOF_CHANNEL_INFO_TYPE_VENDOR_SPECIFIC = 0x10, +}; + +/* WMI_TOF_CHANNEL_INFO_CMDID */ +struct wmi_tof_channel_info_cmd { + /* wmi_tof_channel_info_report_type_e */ + __le32 channel_info_report_request; +} __packed; + /* WMI Events * List of Events (target to host) */ @@ -934,6 +1033,14 @@ enum wmi_event_id { /* Not supported yet */ WMI_PS_MID_CFG_READ_EVENTID = 0x1920, WMI_RS_CFG_DONE_EVENTID = 0x1921, + WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922, + WMI_AOA_MEAS_EVENTID = 0x1923, + WMI_TOF_SESSION_END_EVENTID = 0x1991, + WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992, + WMI_TOF_SET_LCR_EVENTID = 0x1993, + WMI_TOF_SET_LCI_EVENTID = 0x1994, + WMI_TOF_FTM_PER_DEST_RES_EVENTID = 0x1995, + WMI_TOF_CHANNEL_INFO_EVENTID = 0x1996, WMI_SET_CHANNEL_EVENTID = 0x9000, WMI_ASSOC_REQ_EVENTID = 0x9001, WMI_EAPOL_RX_EVENTID = 0x9002, @@ -1003,6 +1110,13 @@ struct wmi_fw_ver_event { __le32 bl_minor; __le32 bl_subminor; __le32 bl_build; + /* The number of entries in the FW capabilies array */ + u8 fw_capabilities_len; + u8 reserved[3]; + /* FW capabilities info + * Must be the last member of the struct + */ + __le32 fw_capabilities[0]; } __packed; /* WMI_GET_RF_STATUS_EVENTID */ @@ -1565,6 +1679,41 @@ struct wmi_rs_cfg_done_event { u8 reserved[2]; } __packed; +/* WMI_GET_DETAILED_RS_RES_CMDID */ +struct wmi_get_detailed_rs_res_cmd { + /* connection id */ + u8 cid; + u8 reserved[3]; +} __packed; + +/* RS results status */ +enum wmi_rs_results_status { + WMI_RS_RES_VALID = 0x00, + WMI_RS_RES_INVALID = 0x01, +}; + +/* Rate search results */ +struct wmi_rs_results { + /* number of sent MPDUs */ + u8 num_of_tx_pkt[WMI_NUM_MCS]; + /* number of non-acked MPDUs */ + u8 num_of_non_acked_pkt[WMI_NUM_MCS]; + /* RS timestamp */ + __le32 tsf; + /* RS selected MCS */ + u8 mcs; +} __packed; + +/* WMI_GET_DETAILED_RS_RES_EVENTID */ +struct wmi_get_detailed_rs_res_event { + u8 cid; + /* enum wmi_rs_results_status */ + u8 status; + /* detailed rs results */ + struct wmi_rs_results rs_results; + u8 reserved[3]; +} __packed; + /* broadcast connection ID */ #define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST (0xFFFFFFFF) @@ -1892,4 +2041,147 @@ struct wmi_ps_mid_cfg_read_event { __le32 status; } __packed; +#define WMI_AOA_MAX_DATA_SIZE (128) + +enum wmi_aoa_meas_status { + WMI_AOA_MEAS_SUCCESS = 0x00, + WMI_AOA_MEAS_PEER_INCAPABLE = 0x01, + WMI_AOA_MEAS_FAILURE = 0x02, +}; + +/* WMI_AOA_MEAS_EVENTID */ +struct wmi_aoa_meas_event { + u8 mac_addr[WMI_MAC_LEN]; + /* channels IDs: + * 0 - 58320 MHz + * 1 - 60480 MHz + * 2 - 62640 MHz + */ + u8 channel; + /* enum wmi_aoa_meas_type */ + u8 aoa_meas_type; + /* Measurments are from RFs, defined by the mask */ + __le32 meas_rf_mask; + /* enum wmi_aoa_meas_status */ + u8 meas_status; + u8 reserved; + /* Length of meas_data in bytes */ + __le16 length; + u8 meas_data[WMI_AOA_MAX_DATA_SIZE]; +} __packed; + +/* WMI_TOF_GET_CAPABILITIES_EVENTID */ +struct wmi_tof_get_capabilities_event { + u8 ftm_capability; + /* maximum supported number of destination to start TOF */ + u8 max_num_of_dest; + /* maximum supported number of measurements per burst */ + u8 max_num_of_meas_per_burst; + u8 reserved; + /* maximum supported multi bursts */ + __le16 max_multi_bursts_sessions; + /* maximum supported FTM burst duration , wmi_tof_burst_duration_e */ + __le16 max_ftm_burst_duration; + /* AOA supported types */ + __le32 aoa_supported_types; +} __packed; + +enum wmi_tof_session_end_status { + WMI_TOF_SESSION_END_NO_ERROR = 0x00, + WMI_TOF_SESSION_END_FAIL = 0x01, + WMI_TOF_SESSION_END_PARAMS_ERROR = 0x02, + WMI_TOF_SESSION_END_ABORTED = 0x03, +}; + +/* WMI_TOF_SESSION_END_EVENTID */ +struct wmi_tof_session_end_event { + /* FTM session ID */ + __le32 session_id; + /* wmi_tof_session_end_status_e */ + u8 status; + u8 reserved[3]; +} __packed; + +/* Responder FTM Results */ +struct wmi_responder_ftm_res { + u8 t1[6]; + u8 t2[6]; + u8 t3[6]; + u8 t4[6]; + __le16 tod_err; + __le16 toa_err; + __le16 tod_err_initiator; + __le16 toa_err_initiator; +} __packed; + +enum wmi_tof_ftm_per_dest_res_status { + WMI_PER_DEST_RES_NO_ERROR = 0x00, + WMI_PER_DEST_RES_TX_RX_FAIL = 0x01, + WMI_PER_DEST_RES_PARAM_DONT_MATCH = 0x02, +}; + +enum wmi_tof_ftm_per_dest_res_flags { + WMI_PER_DEST_RES_REQ_START = 0x01, + WMI_PER_DEST_RES_BURST_REPORT_END = 0x02, + WMI_PER_DEST_RES_REQ_END = 0x04, + WMI_PER_DEST_RES_PARAM_UPDATE = 0x08, +}; + +/* WMI_TOF_FTM_PER_DEST_RES_EVENTID */ +struct wmi_tof_ftm_per_dest_res_event { + /* FTM session ID */ + __le32 session_id; + /* destination MAC address */ + u8 dst_mac[WMI_MAC_LEN]; + /* wmi_tof_ftm_per_dest_res_flags_e */ + u8 flags; + /* wmi_tof_ftm_per_dest_res_status_e */ + u8 status; + /* responder ASAP */ + u8 responder_asap; + /* responder number of FTM per burst */ + u8 responder_num_ftm_per_burst; + /* responder number of FTM burst exponent */ + u8 responder_num_ftm_bursts_exp; + /* responder burst duration ,wmi_tof_burst_duration_e */ + u8 responder_burst_duration; + /* responder burst period, indicate interval between two consecutive + * burst instances, in units of 100 ms + */ + __le16 responder_burst_period; + /* receive burst counter */ + __le16 bursts_cnt; + /* tsf of responder start burst */ + __le32 tsf_sync; + /* actual received ftm per burst */ + u8 actual_ftm_per_burst; + u8 reserved0[7]; + struct wmi_responder_ftm_res responder_ftm_res[0]; +} __packed; + +enum wmi_tof_channel_info_type { + WMI_TOF_CHANNEL_INFO_AOA = 0x00, + WMI_TOF_CHANNEL_INFO_LCI = 0x01, + WMI_TOF_CHANNEL_INFO_LCR = 0x02, + WMI_TOF_CHANNEL_INFO_VENDOR_SPECIFIC = 0x03, + WMI_TOF_CHANNEL_INFO_CIR = 0x04, + WMI_TOF_CHANNEL_INFO_RSSI = 0x05, + WMI_TOF_CHANNEL_INFO_SNR = 0x06, + WMI_TOF_CHANNEL_INFO_DEBUG = 0x07, +}; + +/* WMI_TOF_CHANNEL_INFO_EVENTID */ +struct wmi_tof_channel_info_event { + /* FTM session ID */ + __le32 session_id; + /* destination MAC address */ + u8 dst_mac[WMI_MAC_LEN]; + /* wmi_tof_channel_info_type_e */ + u8 type; + /* data report length */ + u8 len; + /* data report payload */ + u8 report[0]; +} __packed; + #endif /* __WILOCITY_WMI_H__ */ From 71b6cf244bfbce2199e4179c0a951921359555e8 Mon Sep 17 00:00:00 2001 From: Lior David Date: Mon, 5 Sep 2016 11:51:30 +0300 Subject: [PATCH 10/10] wil6210: extract firmware capabilities from FW file When driver is loaded, extract a capabilities record from the FW file. This record contains bits indicating which optional features are supported by this FW. The driver can use this information to determine which functionality to support and/or expose to user space. The extraction is done before wiphy structure is registered, because the capabilities can affect information published by the this structure. Change-Id: I20bc8d4b2b58fc3235ec3fe778738055d7535276 Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo git-commit: 12bace75704ec0d64621be6ebf6e51772ce2cb0f Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git CRs-Fixed: 1063261 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/debugfs.c | 25 ++++++ drivers/net/wireless/ath/wil6210/fw.h | 11 ++- drivers/net/wireless/ath/wil6210/fw_inc.c | 85 +++++++++++++++------ drivers/net/wireless/ath/wil6210/main.c | 4 +- drivers/net/wireless/ath/wil6210/pcie_bus.c | 4 + drivers/net/wireless/ath/wil6210/wil6210.h | 4 +- 6 files changed, 106 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index f8e36ba47ac7..ce115c98a72f 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1559,6 +1559,30 @@ static const struct file_operations fops_led_blink_time = { .open = simple_open, }; +/*---------FW capabilities------------*/ +static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data) +{ + struct wil6210_priv *wil = s->private; + + seq_printf(s, "fw_capabilities : %*pb\n", WMI_FW_CAPABILITY_MAX, + wil->fw_capabilities); + + return 0; +} + +static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, wil_fw_capabilities_debugfs_show, + inode->i_private); +} + +static const struct file_operations fops_fw_capabilities = { + .open = wil_fw_capabilities_seq_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + /*----------------*/ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, struct dentry *dbg) @@ -1609,6 +1633,7 @@ static const struct { {"recovery", S_IRUGO | S_IWUSR, &fops_recovery}, {"led_cfg", S_IRUGO | S_IWUSR, &fops_led_cfg}, {"led_blink_time", S_IRUGO | S_IWUSR, &fops_led_blink_time}, + {"fw_capabilities", S_IRUGO, &fops_fw_capabilities}, }; static void wil6210_debugfs_init_files(struct wil6210_priv *wil, diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h index 7a2c6c129ad5..c3191c61832c 100644 --- a/drivers/net/wireless/ath/wil6210/fw.h +++ b/drivers/net/wireless/ath/wil6210/fw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Qualcomm Atheros, Inc. + * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -58,6 +58,15 @@ struct wil_fw_record_comment { /* type == wil_fw_type_comment */ u8 data[0]; /* free-form data [data_size], see above */ } __packed; +/* FW capabilities encoded inside a comment record */ +#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba) +struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ + /* identifies capabilities record */ + __le32 magic; + /* capabilities (variable size), see enum wmi_fw_capability */ + u8 capabilities[0]; +}; + /* perform action * data_size = @head.size - offsetof(struct wil_fw_record_action, data) */ diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index d30657ee7e83..3860238840ba 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -118,6 +118,12 @@ static int wil_fw_verify(struct wil6210_priv *wil, const u8 *data, size_t size) return (int)dlen; } +static int fw_ignore_section(struct wil6210_priv *wil, const void *data, + size_t size) +{ + return 0; +} + static int fw_handle_comment(struct wil6210_priv *wil, const void *data, size_t size) { @@ -126,6 +132,27 @@ static int fw_handle_comment(struct wil6210_priv *wil, const void *data, return 0; } +static int +fw_handle_capabilities(struct wil6210_priv *wil, const void *data, + size_t size) +{ + const struct wil_fw_record_capabilities *rec = data; + size_t capa_size; + + if (size < sizeof(*rec) || + le32_to_cpu(rec->magic) != WIL_FW_CAPABILITIES_MAGIC) + return 0; + + capa_size = size - offsetof(struct wil_fw_record_capabilities, + capabilities); + bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); + memcpy(wil->fw_capabilities, rec->capabilities, + min(sizeof(wil->fw_capabilities), capa_size)); + wil_hex_dump_fw("CAPA", DUMP_PREFIX_OFFSET, 16, 1, + rec->capabilities, capa_size, false); + return 0; +} + static int fw_handle_data(struct wil6210_priv *wil, const void *data, size_t size) { @@ -383,42 +410,51 @@ static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data, static const struct { int type; - int (*handler)(struct wil6210_priv *wil, const void *data, size_t size); + int (*load_handler)(struct wil6210_priv *wil, const void *data, + size_t size); + int (*parse_handler)(struct wil6210_priv *wil, const void *data, + size_t size); } wil_fw_handlers[] = { - {wil_fw_type_comment, fw_handle_comment}, - {wil_fw_type_data, fw_handle_data}, - {wil_fw_type_fill, fw_handle_fill}, + {wil_fw_type_comment, fw_handle_comment, fw_handle_capabilities}, + {wil_fw_type_data, fw_handle_data, fw_ignore_section}, + {wil_fw_type_fill, fw_handle_fill, fw_ignore_section}, /* wil_fw_type_action */ /* wil_fw_type_verify */ - {wil_fw_type_file_header, fw_handle_file_header}, - {wil_fw_type_direct_write, fw_handle_direct_write}, - {wil_fw_type_gateway_data, fw_handle_gateway_data}, - {wil_fw_type_gateway_data4, fw_handle_gateway_data4}, + {wil_fw_type_file_header, fw_handle_file_header, + fw_handle_file_header}, + {wil_fw_type_direct_write, fw_handle_direct_write, fw_ignore_section}, + {wil_fw_type_gateway_data, fw_handle_gateway_data, fw_ignore_section}, + {wil_fw_type_gateway_data4, fw_handle_gateway_data4, + fw_ignore_section}, }; static int wil_fw_handle_record(struct wil6210_priv *wil, int type, - const void *data, size_t size) + const void *data, size_t size, bool load) { int i; - for (i = 0; i < ARRAY_SIZE(wil_fw_handlers); i++) { + for (i = 0; i < ARRAY_SIZE(wil_fw_handlers); i++) if (wil_fw_handlers[i].type == type) - return wil_fw_handlers[i].handler(wil, data, size); - } + return load ? + wil_fw_handlers[i].load_handler( + wil, data, size) : + wil_fw_handlers[i].parse_handler( + wil, data, size); wil_err_fw(wil, "unknown record type: %d\n", type); return -EINVAL; } /** - * wil_fw_load - load FW into device - * - * Load the FW and uCode code and data to the corresponding device - * memory regions + * wil_fw_process - process section from FW file + * if load is true: Load the FW and uCode code and data to the + * corresponding device memory regions, + * otherwise only parse and look for capabilities * * Return error code */ -static int wil_fw_load(struct wil6210_priv *wil, const void *data, size_t size) +static int wil_fw_process(struct wil6210_priv *wil, const void *data, + size_t size, bool load) { int rc = 0; const struct wil_fw_record_head *hdr; @@ -437,7 +473,7 @@ static int wil_fw_load(struct wil6210_priv *wil, const void *data, size_t size) return -EINVAL; } rc = wil_fw_handle_record(wil, le16_to_cpu(hdr->type), - &hdr[1], hdr_sz); + &hdr[1], hdr_sz, load); if (rc) return rc; } @@ -456,13 +492,16 @@ static int wil_fw_load(struct wil6210_priv *wil, const void *data, size_t size) } /** - * wil_request_firmware - Request firmware and load to device + * wil_request_firmware - Request firmware * - * Request firmware image from the file and load it to device + * Request firmware image from the file + * If load is true, load firmware to device, otherwise + * only parse and extract capabilities * * Return error code */ -int wil_request_firmware(struct wil6210_priv *wil, const char *name) +int wil_request_firmware(struct wil6210_priv *wil, const char *name, + bool load) { int rc, rc1; const struct firmware *fw; @@ -482,7 +521,7 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name) rc = rc1; goto out; } - rc = wil_fw_load(wil, d, rc1); + rc = wil_fw_process(wil, d, rc1, load); if (rc < 0) goto out; } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index dd1dc0d226e6..88dfb93d0f3d 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -893,10 +893,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil_halt_cpu(wil); /* Loading f/w from the file */ - rc = wil_request_firmware(wil, WIL_FW_NAME); + rc = wil_request_firmware(wil, WIL_FW_NAME, true); if (rc) return rc; - rc = wil_request_firmware(wil, WIL_FW2_NAME); + rc = wil_request_firmware(wil, WIL_FW2_NAME, true); if (rc) return rc; diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 5b7a9d2f0c29..44746ca0d2e6 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -39,6 +39,7 @@ void wil_set_capabilities(struct wil6210_priv *wil) u32 rev_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); bitmap_zero(wil->hw_capabilities, hw_capability_last); + bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); switch (rev_id) { case JTAG_DEV_ID_SPARROW_B0: @@ -52,6 +53,9 @@ void wil_set_capabilities(struct wil6210_priv *wil) } wil_info(wil, "Board hardware is %s\n", wil->hw_name); + + /* extract FW capabilities from file without loading the FW */ + wil_request_firmware(wil, WIL_FW_NAME, false); } void wil_disable_irq(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index de1b88555a3a..1e0536adb6e7 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -583,6 +583,7 @@ struct wil6210_priv { u32 hw_version; const char *hw_name; DECLARE_BITMAP(hw_capabilities, hw_capability_last); + DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); u8 n_mids; /* number of additional MIDs as reported by FW */ u32 recovery_count; /* num of FW recovery attempts in a short time */ u32 recovery_state; /* FW recovery state machine */ @@ -898,7 +899,8 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil); int wil_iftype_nl2wmi(enum nl80211_iftype type); int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd); -int wil_request_firmware(struct wil6210_priv *wil, const char *name); +int wil_request_firmware(struct wil6210_priv *wil, const char *name, + bool load); int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime);