Loading drivers/soc/qcom/dfc_qmi.c +86 −51 Original line number Diff line number Diff line Loading @@ -58,12 +58,15 @@ struct dfc_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; struct svc_info svc; struct work_struct qmi_ind_work; struct list_head qmi_ind_q; spinlock_t qmi_ind_lock; int index; int restart_state; }; static void dfc_svc_init(struct work_struct *work); static void dfc_do_burst_flow_control(struct work_struct *work); /* **************************************************** */ #define DFC_SERVICE_ID_V01 0x4E Loading Loading @@ -307,8 +310,7 @@ struct dfc_flow_status_ind_msg_v01 { }; struct dfc_svc_ind { struct work_struct work; struct dfc_qmi_data *data; struct list_head list; struct dfc_flow_status_ind_msg_v01 dfc_info; }; Loading Loading @@ -618,12 +620,11 @@ dfc_indication_register_req(struct qmi_handle *dfc_handle, return ret; } static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) static int dfc_init_service(struct dfc_qmi_data *data) { int rc; rc = dfc_bind_client_req(&data->handle, &data->ssctl, &qmi->fc_info[data->index].svc); rc = dfc_bind_client_req(&data->handle, &data->ssctl, &data->svc); if (rc < 0) return rc; Loading Loading @@ -674,16 +675,13 @@ static int dfc_bearer_flow_ctl(struct net_device *dev, struct rmnet_bearer_map *bearer, struct qos_info *qos) { struct list_head *p; struct rmnet_flow_map *itm; int rc = 0, qlen; int enable; enable = bearer->grant_size ? 1 : 0; list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); list_for_each_entry(itm, &qos->flow_head, list) { if (itm->bearer_id == bearer->bearer_id) { /* * Do not flow disable ancillary q if ancillary is true Loading Loading @@ -713,14 +711,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 ack_req, u32 ancillary, struct dfc_flow_status_info_type_v01 *fc_info) { struct list_head *p; struct rmnet_bearer_map *bearer_itm = NULL; int enable; int rc = 0; struct rmnet_bearer_map *bearer_itm; struct rmnet_flow_map *flow_itm; int rc = 0, qlen; bool enable; list_for_each(p, &qos->bearer_head) { bearer_itm = list_entry(p, struct rmnet_bearer_map, list); enable = fc_info->num_bytes > 0 ? 1 : 0; list_for_each_entry(bearer_itm, &qos->bearer_head, list) { bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->grant_thresh = qmi_rmnet_grant_per(bearer_itm->grant_size); Loading @@ -729,14 +727,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, bearer_itm->ancillary = ancillary; } enable = fc_info->num_bytes > 0 ? 1 : 0; if (enable) netif_tx_wake_all_queues(dev); else netif_tx_stop_all_queues(dev); trace_dfc_qmi_tc(dev->name, 0xFF, 0, fc_info->num_bytes, 0, 0, enable); list_for_each_entry(flow_itm, &qos->flow_head, list) { qlen = qmi_rmnet_flow_control(dev, flow_itm->tcm_handle, enable); trace_dfc_qmi_tc(dev->name, flow_itm->bearer_id, flow_itm->flow_id, fc_info->num_bytes, qlen, flow_itm->tcm_handle, enable); rc++; } if (enable == 0 && ack_req) dfc_send_ack(dev, fc_info->bearer_id, Loading Loading @@ -776,9 +774,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, return rc; } static void dfc_do_burst_flow_control(struct work_struct *work) static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_svc_ind *svc_ind) { struct dfc_svc_ind *svc_ind = (struct dfc_svc_ind *)work; struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->dfc_info; struct net_device *dev; struct qos_info *qos; Loading @@ -788,11 +786,6 @@ static void dfc_do_burst_flow_control(struct work_struct *work) u32 ancillary; int i, j; if (unlikely(svc_ind->data->restart_state)) { kfree(svc_ind); return; } rcu_read_lock(); for (i = 0; i < ind->flow_status_len; i++) { Loading @@ -810,7 +803,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) } } trace_dfc_flow_ind(svc_ind->data->index, trace_dfc_flow_ind(dfc->index, i, flow_status->mux_id, flow_status->bearer_id, flow_status->num_bytes, Loading @@ -818,7 +811,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) ack_req, ancillary); dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, dev = rmnet_get_rmnet_dev(dfc->rmnet_port, flow_status->mux_id); if (!dev) goto clean_out; Loading @@ -841,8 +834,37 @@ static void dfc_do_burst_flow_control(struct work_struct *work) clean_out: rcu_read_unlock(); } static void dfc_qmi_ind_work(struct work_struct *work) { struct dfc_qmi_data *dfc = container_of(work, struct dfc_qmi_data, qmi_ind_work); struct dfc_svc_ind *svc_ind; unsigned long flags; if (!dfc) return; local_bh_disable(); do { spin_lock_irqsave(&dfc->qmi_ind_lock, flags); svc_ind = list_first_entry_or_null(&dfc->qmi_ind_q, struct dfc_svc_ind, list); if (svc_ind) list_del(&svc_ind->list); spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); if (svc_ind) { if (!dfc->restart_state) dfc_do_burst_flow_control(dfc, svc_ind); kfree(svc_ind); } } while (svc_ind != NULL); local_bh_enable(); } static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *data) Loading @@ -851,6 +873,7 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, handle); struct dfc_flow_status_ind_msg_v01 *ind_msg; struct dfc_svc_ind *svc_ind; unsigned long flags; if (qmi != &dfc->handle) return; Loading @@ -867,13 +890,13 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, if (!svc_ind) return; INIT_WORK((struct work_struct *)svc_ind, dfc_do_burst_flow_control); memcpy(&svc_ind->dfc_info, ind_msg, sizeof(*ind_msg)); svc_ind->data = dfc; queue_work(dfc->dfc_wq, (struct work_struct *)svc_ind); spin_lock_irqsave(&dfc->qmi_ind_lock, flags); list_add_tail(&svc_ind->list, &dfc->qmi_ind_q); spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); queue_work(dfc->dfc_wq, &dfc->qmi_ind_work); } } Loading @@ -884,19 +907,26 @@ static void dfc_svc_init(struct work_struct *work) svc_arrive); struct qmi_info *qmi; qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) goto clean_out; rc = dfc_init_service(data, qmi); rc = dfc_init_service(data); if (rc < 0) goto clean_out; qmi->fc_info[data->index].dfc_client = (void *)data; trace_dfc_client_state_up(data->index, qmi->fc_info[data->index].svc.instance, qmi->fc_info[data->index].svc.ep_type, qmi->fc_info[data->index].svc.iface_id); data->svc.instance, data->svc.ep_type, data->svc.iface_id); rtnl_lock(); qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) { rtnl_unlock(); goto clean_out; } qmi->dfc_clients[data->index] = (void *)data; rtnl_unlock(); pr_info("Connection established with the DFC Service\n"); return; clean_out: Loading Loading @@ -944,7 +974,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { struct dfc_qmi_data *data; int rc = -ENOMEM; Loading @@ -956,6 +986,11 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) data->rmnet_port = port; data->index = index; data->restart_state = 0; memcpy(&data->svc, psvc, sizeof(data->svc)); INIT_WORK(&data->qmi_ind_work, dfc_qmi_ind_work); INIT_LIST_HEAD(&data->qmi_ind_q); spin_lock_init(&data->qmi_ind_lock); data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { Loading @@ -974,7 +1009,7 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, qmi->fc_info[index].svc.instance); psvc->instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; Loading Loading @@ -1058,7 +1093,7 @@ void dfc_qmi_wq_flush(struct qmi_info *qmi) int i; for (i = 0; i < MAX_CLIENT_NUM; i++) { dfc_data = (struct dfc_qmi_data *)(qmi->fc_info[i].dfc_client); dfc_data = (struct dfc_qmi_data *)(qmi->dfc_clients[i]); if (dfc_data) flush_workqueue(dfc_data->dfc_wq); } Loading drivers/soc/qcom/qmi_rmnet.c +13 −13 Original line number Diff line number Diff line Loading @@ -87,8 +87,8 @@ void *qmi_rmnet_has_dfc_client(struct qmi_info *qmi) return NULL; for (i = 0; i < MAX_CLIENT_NUM; i++) { if (qmi->fc_info[i].dfc_client) return qmi->fc_info[i].dfc_client; if (qmi->dfc_clients[i]) return qmi->dfc_clients[i]; } return NULL; Loading Loading @@ -365,6 +365,7 @@ static int qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) { int idx, rc, err = 0; struct svc_info svc; ASSERT_RTNL(); Loading @@ -375,7 +376,7 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) idx = (tcm->tcm_handle == 0) ? 0 : 1; if (!qmi) { qmi = kzalloc(sizeof(struct qmi_info), GFP_KERNEL); qmi = kzalloc(sizeof(struct qmi_info), GFP_ATOMIC); if (!qmi) return -ENOMEM; Loading @@ -383,20 +384,20 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) } qmi->flag = tcm->tcm_ifindex; qmi->fc_info[idx].svc.instance = tcm->tcm_handle; qmi->fc_info[idx].svc.ep_type = tcm->tcm_info; qmi->fc_info[idx].svc.iface_id = tcm->tcm_parent; svc.instance = tcm->tcm_handle; svc.ep_type = tcm->tcm_info; svc.iface_id = tcm->tcm_parent; if (((tcm->tcm_ifindex & FLAG_DFC_MASK) == DFC_MODE_MULTIQ) && (qmi->fc_info[idx].dfc_client == NULL)) { rc = dfc_qmi_client_init(port, idx, qmi); (qmi->dfc_clients[idx] == NULL)) { rc = dfc_qmi_client_init(port, idx, &svc); if (rc < 0) err = rc; } if ((tcm->tcm_ifindex & FLAG_POWERSAVE_MASK) && (idx == 0) && (qmi->wda_client == NULL)) { rc = wda_qmi_client_init(port, tcm->tcm_handle); rc = wda_qmi_client_init(port, &svc); if (rc < 0) err = rc; } Loading @@ -407,12 +408,11 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) static int __qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx) { ASSERT_RTNL(); if (qmi->fc_info[idx].dfc_client) { dfc_qmi_client_exit(qmi->fc_info[idx].dfc_client); qmi->fc_info[idx].dfc_client = NULL; if (qmi->dfc_clients[idx]) { dfc_qmi_client_exit(qmi->dfc_clients[idx]); qmi->dfc_clients[idx] = NULL; } if (!qmi_rmnet_has_client(qmi)) { Loading drivers/soc/qcom/qmi_rmnet_i.h +8 −13 Original line number Diff line number Diff line Loading @@ -51,11 +51,6 @@ struct svc_info { u32 iface_id; }; struct fc_info { struct svc_info svc; void *dfc_client; }; struct qos_info { u8 mux_id; struct net_device *real_dev; Loading @@ -74,7 +69,7 @@ struct flow_info { struct qmi_info { int flag; void *wda_client; struct fc_info fc_info[MAX_CLIENT_NUM]; void *dfc_clients[MAX_CLIENT_NUM]; unsigned long ps_work_active; int ps_enabled; }; Loading Loading @@ -109,7 +104,7 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); unsigned int qmi_rmnet_grant_per(unsigned int grant); int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc); void dfc_qmi_client_exit(void *dfc_data); Loading @@ -129,13 +124,13 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, } static inline struct rmnet_bearer_map * qmi_rmnet_get_bearer_map(struct qos_info *qos_info, uint8_t bearer_id) qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id) { return NULL; } static inline int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { return -EINVAL; } Loading @@ -157,11 +152,11 @@ dfc_qmi_wq_flush(struct qmi_info *qmi) #endif #ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE int wda_qmi_client_init(void *port, uint32_t instance); int wda_qmi_client_init(void *port, struct svc_info *psvc); void wda_qmi_client_exit(void *wda_data); int wda_set_powersave_mode(void *wda_data, uint8_t enable); int wda_set_powersave_mode(void *wda_data, u8 enable); #else static inline int wda_qmi_client_init(void *port, uint32_t instance) static inline int wda_qmi_client_init(void *port, struct svc_info *psvc) { return -EINVAL; } Loading @@ -170,7 +165,7 @@ static inline void wda_qmi_client_exit(void *wda_data) { } static inline int wda_set_powersave_mode(void *wda_data, uint8_t enable) static inline int wda_set_powersave_mode(void *wda_data, u8 enable) { return -EINVAL; } Loading drivers/soc/qcom/wda_qmi.c +21 −14 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ * */ #include <linux/rtnetlink.h> #include <linux/soc/qcom/qmi.h> #include <soc/qcom/rmnet_qmi.h> #define CREATE_TRACE_POINTS Loading @@ -23,6 +24,7 @@ struct wda_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; struct svc_info svc; }; static void wda_svc_config(struct work_struct *work); Loading Loading @@ -255,8 +257,7 @@ static int wda_set_powersave_mode_req(void *wda_data, uint8_t enable) return ret; } static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, struct qmi_info *qmi) static int wda_set_powersave_config_req(struct qmi_handle *wda_handle) { struct wda_qmi_data *data = container_of(wda_handle, struct wda_qmi_data, handle); Loading @@ -283,8 +284,8 @@ static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, goto out; } req->ep_id.ep_type = qmi->fc_info[0].svc.ep_type; req->ep_id.iface_id = qmi->fc_info[0].svc.iface_id; req->ep_id.ep_type = data->svc.ep_type; req->ep_id.iface_id = data->svc.iface_id; req->req_data_cfg_valid = 1; req->req_data_cfg = WDA_DATA_POWERSAVE_CONFIG_ALL_MASK_V01; ret = qmi_send_request(wda_handle, &data->ssctl, &txn, Loading Loading @@ -319,20 +320,25 @@ static void wda_svc_config(struct work_struct *work) svc_arrive); struct qmi_info *qmi; qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) goto clean_out; if (wda_set_powersave_config_req(&data->handle, qmi) < 0) { if (wda_set_powersave_config_req(&data->handle) < 0) { pr_err("%s() failed, qmi handle pt: %p\n", __func__, &data->handle); goto clean_out; } trace_wda_client_state_up(qmi->fc_info[0].svc.instance, qmi->fc_info[0].svc.ep_type, qmi->fc_info[0].svc.iface_id); trace_wda_client_state_up(data->svc.instance, data->svc.ep_type, data->svc.iface_id); rtnl_lock(); qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) { rtnl_unlock(); goto clean_out; } qmi->wda_client = (void *)data; rtnl_unlock(); pr_info("Connection established with the WDA Service\n"); return; Loading Loading @@ -370,7 +376,7 @@ static struct qmi_ops server_ops = { .del_server = wda_svc_exit, }; int wda_qmi_client_init(void *port, uint32_t instance) int wda_qmi_client_init(void *port, struct svc_info *psvc) { struct wda_qmi_data *data; int rc = 0; Loading @@ -392,6 +398,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } data->rmnet_port = port; memcpy(&data->svc, psvc, sizeof(data->svc)); INIT_WORK(&data->svc_arrive, wda_svc_config); rc = qmi_handle_init(&data->handle, Loading @@ -404,7 +411,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } rc = qmi_add_lookup(&data->handle, WDA_SERVICE_ID_V01, WDA_SERVICE_VERS_V01, instance); WDA_SERVICE_VERS_V01, psvc->instance); if (rc < 0) { pr_err("%s(): Failed qmi_add_lookup, err: %d\n", __func__, rc); qmi_handle_release(&data->handle); Loading Loading
drivers/soc/qcom/dfc_qmi.c +86 −51 Original line number Diff line number Diff line Loading @@ -58,12 +58,15 @@ struct dfc_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; struct svc_info svc; struct work_struct qmi_ind_work; struct list_head qmi_ind_q; spinlock_t qmi_ind_lock; int index; int restart_state; }; static void dfc_svc_init(struct work_struct *work); static void dfc_do_burst_flow_control(struct work_struct *work); /* **************************************************** */ #define DFC_SERVICE_ID_V01 0x4E Loading Loading @@ -307,8 +310,7 @@ struct dfc_flow_status_ind_msg_v01 { }; struct dfc_svc_ind { struct work_struct work; struct dfc_qmi_data *data; struct list_head list; struct dfc_flow_status_ind_msg_v01 dfc_info; }; Loading Loading @@ -618,12 +620,11 @@ dfc_indication_register_req(struct qmi_handle *dfc_handle, return ret; } static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) static int dfc_init_service(struct dfc_qmi_data *data) { int rc; rc = dfc_bind_client_req(&data->handle, &data->ssctl, &qmi->fc_info[data->index].svc); rc = dfc_bind_client_req(&data->handle, &data->ssctl, &data->svc); if (rc < 0) return rc; Loading Loading @@ -674,16 +675,13 @@ static int dfc_bearer_flow_ctl(struct net_device *dev, struct rmnet_bearer_map *bearer, struct qos_info *qos) { struct list_head *p; struct rmnet_flow_map *itm; int rc = 0, qlen; int enable; enable = bearer->grant_size ? 1 : 0; list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); list_for_each_entry(itm, &qos->flow_head, list) { if (itm->bearer_id == bearer->bearer_id) { /* * Do not flow disable ancillary q if ancillary is true Loading Loading @@ -713,14 +711,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 ack_req, u32 ancillary, struct dfc_flow_status_info_type_v01 *fc_info) { struct list_head *p; struct rmnet_bearer_map *bearer_itm = NULL; int enable; int rc = 0; struct rmnet_bearer_map *bearer_itm; struct rmnet_flow_map *flow_itm; int rc = 0, qlen; bool enable; list_for_each(p, &qos->bearer_head) { bearer_itm = list_entry(p, struct rmnet_bearer_map, list); enable = fc_info->num_bytes > 0 ? 1 : 0; list_for_each_entry(bearer_itm, &qos->bearer_head, list) { bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->grant_thresh = qmi_rmnet_grant_per(bearer_itm->grant_size); Loading @@ -729,14 +727,14 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, bearer_itm->ancillary = ancillary; } enable = fc_info->num_bytes > 0 ? 1 : 0; if (enable) netif_tx_wake_all_queues(dev); else netif_tx_stop_all_queues(dev); trace_dfc_qmi_tc(dev->name, 0xFF, 0, fc_info->num_bytes, 0, 0, enable); list_for_each_entry(flow_itm, &qos->flow_head, list) { qlen = qmi_rmnet_flow_control(dev, flow_itm->tcm_handle, enable); trace_dfc_qmi_tc(dev->name, flow_itm->bearer_id, flow_itm->flow_id, fc_info->num_bytes, qlen, flow_itm->tcm_handle, enable); rc++; } if (enable == 0 && ack_req) dfc_send_ack(dev, fc_info->bearer_id, Loading Loading @@ -776,9 +774,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, return rc; } static void dfc_do_burst_flow_control(struct work_struct *work) static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_svc_ind *svc_ind) { struct dfc_svc_ind *svc_ind = (struct dfc_svc_ind *)work; struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->dfc_info; struct net_device *dev; struct qos_info *qos; Loading @@ -788,11 +786,6 @@ static void dfc_do_burst_flow_control(struct work_struct *work) u32 ancillary; int i, j; if (unlikely(svc_ind->data->restart_state)) { kfree(svc_ind); return; } rcu_read_lock(); for (i = 0; i < ind->flow_status_len; i++) { Loading @@ -810,7 +803,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) } } trace_dfc_flow_ind(svc_ind->data->index, trace_dfc_flow_ind(dfc->index, i, flow_status->mux_id, flow_status->bearer_id, flow_status->num_bytes, Loading @@ -818,7 +811,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) ack_req, ancillary); dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, dev = rmnet_get_rmnet_dev(dfc->rmnet_port, flow_status->mux_id); if (!dev) goto clean_out; Loading @@ -841,8 +834,37 @@ static void dfc_do_burst_flow_control(struct work_struct *work) clean_out: rcu_read_unlock(); } static void dfc_qmi_ind_work(struct work_struct *work) { struct dfc_qmi_data *dfc = container_of(work, struct dfc_qmi_data, qmi_ind_work); struct dfc_svc_ind *svc_ind; unsigned long flags; if (!dfc) return; local_bh_disable(); do { spin_lock_irqsave(&dfc->qmi_ind_lock, flags); svc_ind = list_first_entry_or_null(&dfc->qmi_ind_q, struct dfc_svc_ind, list); if (svc_ind) list_del(&svc_ind->list); spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); if (svc_ind) { if (!dfc->restart_state) dfc_do_burst_flow_control(dfc, svc_ind); kfree(svc_ind); } } while (svc_ind != NULL); local_bh_enable(); } static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *data) Loading @@ -851,6 +873,7 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, handle); struct dfc_flow_status_ind_msg_v01 *ind_msg; struct dfc_svc_ind *svc_ind; unsigned long flags; if (qmi != &dfc->handle) return; Loading @@ -867,13 +890,13 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, if (!svc_ind) return; INIT_WORK((struct work_struct *)svc_ind, dfc_do_burst_flow_control); memcpy(&svc_ind->dfc_info, ind_msg, sizeof(*ind_msg)); svc_ind->data = dfc; queue_work(dfc->dfc_wq, (struct work_struct *)svc_ind); spin_lock_irqsave(&dfc->qmi_ind_lock, flags); list_add_tail(&svc_ind->list, &dfc->qmi_ind_q); spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags); queue_work(dfc->dfc_wq, &dfc->qmi_ind_work); } } Loading @@ -884,19 +907,26 @@ static void dfc_svc_init(struct work_struct *work) svc_arrive); struct qmi_info *qmi; qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) goto clean_out; rc = dfc_init_service(data, qmi); rc = dfc_init_service(data); if (rc < 0) goto clean_out; qmi->fc_info[data->index].dfc_client = (void *)data; trace_dfc_client_state_up(data->index, qmi->fc_info[data->index].svc.instance, qmi->fc_info[data->index].svc.ep_type, qmi->fc_info[data->index].svc.iface_id); data->svc.instance, data->svc.ep_type, data->svc.iface_id); rtnl_lock(); qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) { rtnl_unlock(); goto clean_out; } qmi->dfc_clients[data->index] = (void *)data; rtnl_unlock(); pr_info("Connection established with the DFC Service\n"); return; clean_out: Loading Loading @@ -944,7 +974,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { struct dfc_qmi_data *data; int rc = -ENOMEM; Loading @@ -956,6 +986,11 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) data->rmnet_port = port; data->index = index; data->restart_state = 0; memcpy(&data->svc, psvc, sizeof(data->svc)); INIT_WORK(&data->qmi_ind_work, dfc_qmi_ind_work); INIT_LIST_HEAD(&data->qmi_ind_q); spin_lock_init(&data->qmi_ind_lock); data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { Loading @@ -974,7 +1009,7 @@ int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, qmi->fc_info[index].svc.instance); psvc->instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; Loading Loading @@ -1058,7 +1093,7 @@ void dfc_qmi_wq_flush(struct qmi_info *qmi) int i; for (i = 0; i < MAX_CLIENT_NUM; i++) { dfc_data = (struct dfc_qmi_data *)(qmi->fc_info[i].dfc_client); dfc_data = (struct dfc_qmi_data *)(qmi->dfc_clients[i]); if (dfc_data) flush_workqueue(dfc_data->dfc_wq); } Loading
drivers/soc/qcom/qmi_rmnet.c +13 −13 Original line number Diff line number Diff line Loading @@ -87,8 +87,8 @@ void *qmi_rmnet_has_dfc_client(struct qmi_info *qmi) return NULL; for (i = 0; i < MAX_CLIENT_NUM; i++) { if (qmi->fc_info[i].dfc_client) return qmi->fc_info[i].dfc_client; if (qmi->dfc_clients[i]) return qmi->dfc_clients[i]; } return NULL; Loading Loading @@ -365,6 +365,7 @@ static int qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) { int idx, rc, err = 0; struct svc_info svc; ASSERT_RTNL(); Loading @@ -375,7 +376,7 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) idx = (tcm->tcm_handle == 0) ? 0 : 1; if (!qmi) { qmi = kzalloc(sizeof(struct qmi_info), GFP_KERNEL); qmi = kzalloc(sizeof(struct qmi_info), GFP_ATOMIC); if (!qmi) return -ENOMEM; Loading @@ -383,20 +384,20 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) } qmi->flag = tcm->tcm_ifindex; qmi->fc_info[idx].svc.instance = tcm->tcm_handle; qmi->fc_info[idx].svc.ep_type = tcm->tcm_info; qmi->fc_info[idx].svc.iface_id = tcm->tcm_parent; svc.instance = tcm->tcm_handle; svc.ep_type = tcm->tcm_info; svc.iface_id = tcm->tcm_parent; if (((tcm->tcm_ifindex & FLAG_DFC_MASK) == DFC_MODE_MULTIQ) && (qmi->fc_info[idx].dfc_client == NULL)) { rc = dfc_qmi_client_init(port, idx, qmi); (qmi->dfc_clients[idx] == NULL)) { rc = dfc_qmi_client_init(port, idx, &svc); if (rc < 0) err = rc; } if ((tcm->tcm_ifindex & FLAG_POWERSAVE_MASK) && (idx == 0) && (qmi->wda_client == NULL)) { rc = wda_qmi_client_init(port, tcm->tcm_handle); rc = wda_qmi_client_init(port, &svc); if (rc < 0) err = rc; } Loading @@ -407,12 +408,11 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) static int __qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx) { ASSERT_RTNL(); if (qmi->fc_info[idx].dfc_client) { dfc_qmi_client_exit(qmi->fc_info[idx].dfc_client); qmi->fc_info[idx].dfc_client = NULL; if (qmi->dfc_clients[idx]) { dfc_qmi_client_exit(qmi->dfc_clients[idx]); qmi->dfc_clients[idx] = NULL; } if (!qmi_rmnet_has_client(qmi)) { Loading
drivers/soc/qcom/qmi_rmnet_i.h +8 −13 Original line number Diff line number Diff line Loading @@ -51,11 +51,6 @@ struct svc_info { u32 iface_id; }; struct fc_info { struct svc_info svc; void *dfc_client; }; struct qos_info { u8 mux_id; struct net_device *real_dev; Loading @@ -74,7 +69,7 @@ struct flow_info { struct qmi_info { int flag; void *wda_client; struct fc_info fc_info[MAX_CLIENT_NUM]; void *dfc_clients[MAX_CLIENT_NUM]; unsigned long ps_work_active; int ps_enabled; }; Loading Loading @@ -109,7 +104,7 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); unsigned int qmi_rmnet_grant_per(unsigned int grant); int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc); void dfc_qmi_client_exit(void *dfc_data); Loading @@ -129,13 +124,13 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, } static inline struct rmnet_bearer_map * qmi_rmnet_get_bearer_map(struct qos_info *qos_info, uint8_t bearer_id) qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id) { return NULL; } static inline int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) dfc_qmi_client_init(void *port, int index, struct svc_info *psvc) { return -EINVAL; } Loading @@ -157,11 +152,11 @@ dfc_qmi_wq_flush(struct qmi_info *qmi) #endif #ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE int wda_qmi_client_init(void *port, uint32_t instance); int wda_qmi_client_init(void *port, struct svc_info *psvc); void wda_qmi_client_exit(void *wda_data); int wda_set_powersave_mode(void *wda_data, uint8_t enable); int wda_set_powersave_mode(void *wda_data, u8 enable); #else static inline int wda_qmi_client_init(void *port, uint32_t instance) static inline int wda_qmi_client_init(void *port, struct svc_info *psvc) { return -EINVAL; } Loading @@ -170,7 +165,7 @@ static inline void wda_qmi_client_exit(void *wda_data) { } static inline int wda_set_powersave_mode(void *wda_data, uint8_t enable) static inline int wda_set_powersave_mode(void *wda_data, u8 enable) { return -EINVAL; } Loading
drivers/soc/qcom/wda_qmi.c +21 −14 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ * */ #include <linux/rtnetlink.h> #include <linux/soc/qcom/qmi.h> #include <soc/qcom/rmnet_qmi.h> #define CREATE_TRACE_POINTS Loading @@ -23,6 +24,7 @@ struct wda_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; struct svc_info svc; }; static void wda_svc_config(struct work_struct *work); Loading Loading @@ -255,8 +257,7 @@ static int wda_set_powersave_mode_req(void *wda_data, uint8_t enable) return ret; } static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, struct qmi_info *qmi) static int wda_set_powersave_config_req(struct qmi_handle *wda_handle) { struct wda_qmi_data *data = container_of(wda_handle, struct wda_qmi_data, handle); Loading @@ -283,8 +284,8 @@ static int wda_set_powersave_config_req(struct qmi_handle *wda_handle, goto out; } req->ep_id.ep_type = qmi->fc_info[0].svc.ep_type; req->ep_id.iface_id = qmi->fc_info[0].svc.iface_id; req->ep_id.ep_type = data->svc.ep_type; req->ep_id.iface_id = data->svc.iface_id; req->req_data_cfg_valid = 1; req->req_data_cfg = WDA_DATA_POWERSAVE_CONFIG_ALL_MASK_V01; ret = qmi_send_request(wda_handle, &data->ssctl, &txn, Loading Loading @@ -319,20 +320,25 @@ static void wda_svc_config(struct work_struct *work) svc_arrive); struct qmi_info *qmi; qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) goto clean_out; if (wda_set_powersave_config_req(&data->handle, qmi) < 0) { if (wda_set_powersave_config_req(&data->handle) < 0) { pr_err("%s() failed, qmi handle pt: %p\n", __func__, &data->handle); goto clean_out; } trace_wda_client_state_up(qmi->fc_info[0].svc.instance, qmi->fc_info[0].svc.ep_type, qmi->fc_info[0].svc.iface_id); trace_wda_client_state_up(data->svc.instance, data->svc.ep_type, data->svc.iface_id); rtnl_lock(); qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (!qmi) { rtnl_unlock(); goto clean_out; } qmi->wda_client = (void *)data; rtnl_unlock(); pr_info("Connection established with the WDA Service\n"); return; Loading Loading @@ -370,7 +376,7 @@ static struct qmi_ops server_ops = { .del_server = wda_svc_exit, }; int wda_qmi_client_init(void *port, uint32_t instance) int wda_qmi_client_init(void *port, struct svc_info *psvc) { struct wda_qmi_data *data; int rc = 0; Loading @@ -392,6 +398,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } data->rmnet_port = port; memcpy(&data->svc, psvc, sizeof(data->svc)); INIT_WORK(&data->svc_arrive, wda_svc_config); rc = qmi_handle_init(&data->handle, Loading @@ -404,7 +411,7 @@ int wda_qmi_client_init(void *port, uint32_t instance) } rc = qmi_add_lookup(&data->handle, WDA_SERVICE_ID_V01, WDA_SERVICE_VERS_V01, instance); WDA_SERVICE_VERS_V01, psvc->instance); if (rc < 0) { pr_err("%s(): Failed qmi_add_lookup, err: %d\n", __func__, rc); qmi_handle_release(&data->handle); Loading