qcacmn: Add target information details to target_iflayer

Add a new target_psoc_info structure in the target if layer with the
following members

wmi_handle
target_type
target_version
target_revision

Also update the psoc data member tgt_if_handle to point to target_psoc_info
instead of pointing to WMI handle directly.

Updated all calls to psoc_get_tgt_if_handle to target_if_get_wmi_handle
which inturn calls psoc_get_tgt_if_handle and getting the tgt_if_handle
returns the WMI handle

CRs-Fixed: 2048277

Change-Id: Icb02d5f3c09f7f9bb7eff4d814ef3ce90ddb84bd
This commit is contained in:
Vivek
2017-06-04 23:12:00 +05:30
committed by snandini
parent d9ac9a2abe
commit 57522058e9
9 changed files with 82 additions and 40 deletions

View File

@@ -49,7 +49,8 @@
#define TARGET_IF_ENTER() target_if_logfl(QDF_TRACE_LEVEL_INFO, "enter") #define TARGET_IF_ENTER() target_if_logfl(QDF_TRACE_LEVEL_INFO, "enter")
#define TARGET_IF_EXIT() target_if_logfl(QDF_TRACE_LEVEL_INFO, "exit") #define TARGET_IF_EXIT() target_if_logfl(QDF_TRACE_LEVEL_INFO, "exit")
#define GET_WMI_HDL_FROM_PSOC(psoc) (psoc->tgt_if_handle) #define GET_WMI_HDL_FROM_PSOC(psoc) \
(((struct target_psoc_info *)(psoc->tgt_if_handle))->wmi_handle)
typedef struct wlan_objmgr_psoc *(*get_psoc_handle_callback)( typedef struct wlan_objmgr_psoc *(*get_psoc_handle_callback)(
void *scn_handle); void *scn_handle);
@@ -72,6 +73,21 @@ struct target_if_ctx {
qdf_spinlock_t lock; qdf_spinlock_t lock;
}; };
/**
* struct target_psoc_info - target psoc information
* @tgt_if_handle: target interface handle
* @target_type: target type
* @target_version: target version
* @target_revision: target revision
*/
struct target_psoc_info {
void *wmi_handle;
uint32_t target_type;
uint32_t target_version;
uint32_t target_revision;
};
/** /**
* target_if_open() - target_if open * target_if_open() - target_if open
* @get_wmi_handle: function pointer to get wmi handle * @get_wmi_handle: function pointer to get wmi handle
@@ -142,5 +158,6 @@ target_if_get_psoc_legacy_service_ready_cb(void);
QDF_STATUS target_if_register_legacy_service_ready_cb( QDF_STATUS target_if_register_legacy_service_ready_cb(
wmi_legacy_service_ready_callback service_ready_cb); wmi_legacy_service_ready_callback service_ready_cb);
void *target_if_get_wmi_handle(struct wlan_objmgr_psoc *psoc);
#endif #endif

View File

@@ -308,3 +308,27 @@ QDF_STATUS target_if_register_legacy_service_ready_cb(
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
EXPORT_SYMBOL(target_if_register_legacy_service_ready_cb); EXPORT_SYMBOL(target_if_register_legacy_service_ready_cb);
void *target_if_get_wmi_handle(struct wlan_objmgr_psoc *psoc)
{
struct target_psoc_info *tgt_psoc_info;
void *wmi_handle;
if (psoc == NULL) {
target_if_err("%s: pSOC is NULL", __func__);
return NULL;
}
tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
if (tgt_psoc_info == NULL) {
target_if_err("%s: psoc tgt_if_handle is NULL", __func__);
return NULL;
}
wmi_handle = tgt_psoc_info->wmi_handle;
return wmi_handle;
}

View File

@@ -151,12 +151,12 @@ static QDF_STATUS target_if_dfs_reg_offload_events(
{ {
int ret1, ret2; int ret1, ret2;
ret1 = wmi_unified_register_event(psoc->tgt_if_handle, ret1 = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_dfs_radar_detection_event_id, wmi_dfs_radar_detection_event_id,
target_if_dfs_radar_detection_event_handler); target_if_dfs_radar_detection_event_handler);
target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1); target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1);
ret2 = wmi_unified_register_event(psoc->tgt_if_handle, ret2 = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_dfs_cac_complete_id, wmi_dfs_cac_complete_id,
target_if_dfs_cac_complete_event_handler); target_if_dfs_cac_complete_event_handler);
target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2); target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2);

View File

@@ -87,7 +87,7 @@ int init_deinit_service_ready_event_handler(ol_scn_t scn_handle,
return -EINVAL; return -EINVAL;
} }
wmi_handle = psoc->tgt_if_handle; wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
service_param = qdf_mem_malloc(sizeof(*service_param)); service_param = qdf_mem_malloc(sizeof(*service_param));
if (!service_param) { if (!service_param) {
@@ -282,7 +282,7 @@ int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle,
return -EINVAL; return -EINVAL;
} }
wmi_handle = psoc->tgt_if_handle; wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
service_param = service_param =
qdf_mem_malloc(sizeof(*service_param)); qdf_mem_malloc(sizeof(*service_param));

View File

@@ -161,7 +161,7 @@ QDF_STATUS target_if_p2p_register_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg) struct wlan_objmgr_psoc *psoc, void *arg)
{ {
int status; int status;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, arg:%p", psoc, arg); target_if_debug("psoc:%p, arg:%p", psoc, arg);
@@ -184,7 +184,7 @@ QDF_STATUS target_if_p2p_register_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg) struct wlan_objmgr_psoc *psoc, void *arg)
{ {
int status; int status;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, arg:%p", psoc, arg); target_if_debug("psoc:%p, arg:%p", psoc, arg);
@@ -207,7 +207,7 @@ QDF_STATUS target_if_p2p_unregister_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg) struct wlan_objmgr_psoc *psoc, void *arg)
{ {
int status; int status;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, arg:%p", psoc, arg); target_if_debug("psoc:%p, arg:%p", psoc, arg);
@@ -229,7 +229,7 @@ QDF_STATUS target_if_p2p_unregister_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg) struct wlan_objmgr_psoc *psoc, void *arg)
{ {
int status; int status;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, arg:%p", psoc, arg); target_if_debug("psoc:%p, arg:%p", psoc, arg);
@@ -252,7 +252,7 @@ QDF_STATUS target_if_p2p_set_ps(struct wlan_objmgr_psoc *psoc,
{ {
struct p2p_ps_params cmd; struct p2p_ps_params cmd;
QDF_STATUS status; QDF_STATUS status;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, vdev_id:%d, opp_ps:%d", psoc, target_if_debug("psoc:%p, vdev_id:%d, opp_ps:%d", psoc,
ps_config->vdev_id, ps_config->opp_ps); ps_config->vdev_id, ps_config->opp_ps);
@@ -293,7 +293,7 @@ QDF_STATUS target_if_p2p_set_ps(struct wlan_objmgr_psoc *psoc,
QDF_STATUS target_if_p2p_lo_start(struct wlan_objmgr_psoc *psoc, QDF_STATUS target_if_p2p_lo_start(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_start *lo_start) struct p2p_lo_start *lo_start)
{ {
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, vdev_id:%d", psoc, lo_start->vdev_id); target_if_debug("psoc:%p, vdev_id:%d", psoc, lo_start->vdev_id);
@@ -313,7 +313,7 @@ QDF_STATUS target_if_p2p_lo_start(struct wlan_objmgr_psoc *psoc,
QDF_STATUS target_if_p2p_lo_stop(struct wlan_objmgr_psoc *psoc, QDF_STATUS target_if_p2p_lo_stop(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id) uint32_t vdev_id)
{ {
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
target_if_debug("psoc:%p, vdev_id:%d", psoc, vdev_id); target_if_debug("psoc:%p, vdev_id:%d", psoc, vdev_id);
@@ -330,7 +330,7 @@ QDF_STATUS target_if_p2p_set_noa(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id, bool disable_noa) uint32_t vdev_id, bool disable_noa)
{ {
struct vdev_set_params param; struct vdev_set_params param;
wmi_unified_t wmi_handle = wlan_psoc_get_tgt_if_handle(psoc); wmi_unified_t wmi_handle = target_if_get_wmi_handle(psoc);
if (!wmi_handle) { if (!wmi_handle) {
target_if_err("Invalid wmi handle"); target_if_err("Invalid wmi handle");

View File

@@ -193,7 +193,7 @@ target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc,
{ {
QDF_STATUS status; QDF_STATUS status;
status = wmi_unified_register_event(psoc->tgt_if_handle, status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_nlo_match_event_id, wmi_nlo_match_event_id,
target_if_nlo_match_event_handler); target_if_nlo_match_event_handler);
if (status) { if (status) {
@@ -201,7 +201,7 @@ target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
status = wmi_unified_register_event(psoc->tgt_if_handle, status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_nlo_scan_complete_event_id, wmi_nlo_scan_complete_event_id,
target_if_nlo_complete_handler); target_if_nlo_complete_handler);
if (status) { if (status) {
@@ -218,14 +218,14 @@ target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc,
{ {
QDF_STATUS status; QDF_STATUS status;
status = wmi_unified_unregister_event(psoc->tgt_if_handle, status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_nlo_match_event_id); wmi_nlo_match_event_id);
if (status) { if (status) {
target_if_err("Failed to unregister nlo match event cb"); target_if_err("Failed to unregister nlo match event cb");
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
status = wmi_unified_unregister_event(psoc->tgt_if_handle, status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_nlo_scan_complete_event_id); wmi_nlo_scan_complete_event_id);
if (status) { if (status) {
target_if_err("Failed to unregister nlo scan comp event cb"); target_if_err("Failed to unregister nlo scan comp event cb");
@@ -239,14 +239,14 @@ static QDF_STATUS
target_if_pno_start(struct wlan_objmgr_psoc *psoc, target_if_pno_start(struct wlan_objmgr_psoc *psoc,
struct pno_scan_req_params *req) struct pno_scan_req_params *req)
{ {
return wmi_unified_pno_start_cmd(psoc->tgt_if_handle, req); return wmi_unified_pno_start_cmd(GET_WMI_HDL_FROM_PSOC(psoc), req);
} }
static QDF_STATUS static QDF_STATUS
target_if_pno_stop(struct wlan_objmgr_psoc *psoc, target_if_pno_stop(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id) uint8_t vdev_id)
{ {
return wmi_unified_pno_stop_cmd(psoc->tgt_if_handle, vdev_id); return wmi_unified_pno_stop_cmd(GET_WMI_HDL_FROM_PSOC(psoc), vdev_id);
} }
#else #else
@@ -286,7 +286,7 @@ target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg)
{ {
QDF_STATUS status; QDF_STATUS status;
status = wmi_unified_register_event(psoc->tgt_if_handle, status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_scan_event_id, target_if_scan_event_handler); wmi_scan_event_id, target_if_scan_event_handler);
if (status) { if (status) {
target_if_err("Failed to register Scan match event cb"); target_if_err("Failed to register Scan match event cb");
@@ -304,7 +304,7 @@ target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
{ {
QDF_STATUS status; QDF_STATUS status;
status = wmi_unified_unregister_event(psoc->tgt_if_handle, status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_scan_event_id); wmi_scan_event_id);
if (status) { if (status) {
target_if_err("Failed to unregister Scan match event cb"); target_if_err("Failed to unregister Scan match event cb");
@@ -320,7 +320,7 @@ QDF_STATUS
target_if_scan_start(struct wlan_objmgr_psoc *psoc, target_if_scan_start(struct wlan_objmgr_psoc *psoc,
struct scan_start_request *req) struct scan_start_request *req)
{ {
return wmi_unified_scan_start_cmd_send(psoc->tgt_if_handle, return wmi_unified_scan_start_cmd_send(GET_WMI_HDL_FROM_PSOC(psoc),
&req->scan_req); &req->scan_req);
} }
@@ -328,7 +328,7 @@ QDF_STATUS
target_if_scan_cancel(struct wlan_objmgr_psoc *psoc, target_if_scan_cancel(struct wlan_objmgr_psoc *psoc,
struct scan_cancel_param *req) struct scan_cancel_param *req)
{ {
return wmi_unified_scan_stop_cmd_send(psoc->tgt_if_handle, req); return wmi_unified_scan_stop_cmd_send(GET_WMI_HDL_FROM_PSOC(psoc), req);
} }
QDF_STATUS QDF_STATUS

View File

@@ -18,6 +18,7 @@
*/ */
#include <target_if_son.h> #include <target_if_son.h>
#include <target_if.h>
#include <wlan_lmac_if_def.h> #include <wlan_lmac_if_def.h>
#include <wmi_unified_api.h> #include <wmi_unified_api.h>
#include <cdp_txrx_ctrl.h> #include <cdp_txrx_ctrl.h>
@@ -100,8 +101,8 @@ QDF_STATUS son_ol_send_null(struct wlan_objmgr_pdev *pdev,
param.vdev_id = wlan_vdev_get_id(vdev); param.vdev_id = wlan_vdev_get_id(vdev);
param.stats_id = WMI_HOST_REQUEST_INST_STAT; param.stats_id = WMI_HOST_REQUEST_INST_STAT;
return wmi_unified_stats_request_send(psoc->tgt_if_handle, return wmi_unified_stats_request_send(GET_WMI_HDL_FROM_PSOC(psoc),
macaddr, &param); macaddr, &param);
} }
int son_ol_lmac_create(struct wlan_objmgr_pdev *pdev) int son_ol_lmac_create(struct wlan_objmgr_pdev *pdev)

View File

@@ -91,7 +91,7 @@ target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc,
else else
tdls_state = WMI_TDLS_DISABLE; tdls_state = WMI_TDLS_DISABLE;
status = wmi_unified_update_fw_tdls_state_cmd(psoc->tgt_if_handle, status = wmi_unified_update_fw_tdls_state_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
param, tdls_state); param, tdls_state);
target_if_debug("vdev_id %d", param->vdev_id); target_if_debug("vdev_id %d", param->vdev_id);
@@ -111,7 +111,7 @@ target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
{ {
QDF_STATUS status; QDF_STATUS status;
status = wmi_unified_set_tdls_offchan_mode_cmd(psoc->tgt_if_handle, status = wmi_unified_set_tdls_offchan_mode_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
params); params);
return status; return status;
@@ -131,7 +131,7 @@ target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
params->vdevid); params->vdevid);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(psoc->tgt_if_handle, ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
params); params);
if (QDF_IS_STATUS_ERROR(ret)) if (QDF_IS_STATUS_ERROR(ret))
@@ -144,7 +144,7 @@ QDF_STATUS
target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc, target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg) void *arg)
{ {
return wmi_unified_register_event(psoc->tgt_if_handle, return wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_tdls_peer_event_id, wmi_tdls_peer_event_id,
target_if_tdls_event_handler); target_if_tdls_event_handler);
} }
@@ -153,7 +153,7 @@ QDF_STATUS
target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc, target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg) void *arg)
{ {
return wmi_unified_unregister_event(psoc->tgt_if_handle, return wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_tdls_peer_event_id); wmi_tdls_peer_event_id);
} }

View File

@@ -341,12 +341,12 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
{ {
int ret; int ret;
if (!psoc || !psoc->tgt_if_handle) { if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
target_if_err("psoc or psoc->tgt_if_handle is null"); target_if_err("psoc or psoc->tgt_if_handle is null");
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
WMI_OEM_RESPONSE_EVENTID, WMI_OEM_RESPONSE_EVENTID,
target_if_wifi_pos_oem_rsp_ev_handler, target_if_wifi_pos_oem_rsp_ev_handler,
WMI_RX_WORK_CTX); WMI_RX_WORK_CTX);
@@ -355,7 +355,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_cap_event_id, wmi_oem_cap_event_id,
wifi_pos_oem_cap_ev_handler, wifi_pos_oem_cap_ev_handler,
WMI_RX_WORK_CTX); WMI_RX_WORK_CTX);
@@ -364,7 +364,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_meas_report_event_id, wmi_oem_meas_report_event_id,
wifi_pos_oem_meas_rpt_ev_handler, wifi_pos_oem_meas_rpt_ev_handler,
WMI_RX_WORK_CTX); WMI_RX_WORK_CTX);
@@ -373,7 +373,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, ret = wmi_unified_register_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_report_event_id, wmi_oem_report_event_id,
wifi_pos_oem_err_rpt_ev_handler, wifi_pos_oem_err_rpt_ev_handler,
WMI_RX_WORK_CTX); WMI_RX_WORK_CTX);
@@ -387,18 +387,18 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc)
{ {
if (!psoc || !psoc->tgt_if_handle) { if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
target_if_err("psoc or psoc->tgt_if_handle is null"); target_if_err("psoc or psoc->tgt_if_handle is null");
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
wmi_unified_unregister_event_handler(psoc->tgt_if_handle, wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
WMI_OEM_RESPONSE_EVENTID); WMI_OEM_RESPONSE_EVENTID);
wmi_unified_unregister_event_handler(psoc->tgt_if_handle, wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_cap_event_id); wmi_oem_cap_event_id);
wmi_unified_unregister_event_handler(psoc->tgt_if_handle, wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_meas_report_event_id); wmi_oem_meas_report_event_id);
wmi_unified_unregister_event_handler(psoc->tgt_if_handle, wmi_unified_unregister_event_handler(GET_WMI_HDL_FROM_PSOC(psoc),
wmi_oem_report_event_id); wmi_oem_report_event_id);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;