12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592 |
- /*
- * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <net/pkt_sched.h>
- #include "rmnet_qmi.h"
- #include "qmi_rmnet.h"
- #include "dfc_defs.h"
- #define CREATE_TRACE_POINTS
- #include "dfc.h"
- struct dfc_qmap_header {
- u8 pad_len:6;
- u8 reserved_bit:1;
- u8 cd_bit:1;
- u8 mux_id;
- __be16 pkt_len;
- } __aligned(1);
- struct dfc_ack_cmd {
- struct dfc_qmap_header header;
- u8 command_name;
- u8 cmd_type:2;
- u8 reserved:6;
- u16 reserved2;
- u32 transaction_id;
- u8 ver:2;
- u8 reserved3:6;
- u8 type:2;
- u8 reserved4:6;
- u16 dfc_seq;
- u8 reserved5[3];
- u8 bearer_id;
- } __aligned(1);
- static void dfc_svc_init(struct work_struct *work);
- extern int dfc_ps_ext;
- /* **************************************************** */
- #define DFC_SERVICE_ID_V01 0x4E
- #define DFC_SERVICE_VERS_V01 0x01
- #define DFC_TIMEOUT_JF msecs_to_jiffies(1000)
- #define QMI_DFC_BIND_CLIENT_REQ_V01 0x0020
- #define QMI_DFC_BIND_CLIENT_RESP_V01 0x0020
- #define QMI_DFC_BIND_CLIENT_REQ_V01_MAX_MSG_LEN 11
- #define QMI_DFC_BIND_CLIENT_RESP_V01_MAX_MSG_LEN 7
- #define QMI_DFC_INDICATION_REGISTER_REQ_V01 0x0001
- #define QMI_DFC_INDICATION_REGISTER_RESP_V01 0x0001
- #define QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN 8
- #define QMI_DFC_INDICATION_REGISTER_RESP_V01_MAX_MSG_LEN 7
- #define QMI_DFC_FLOW_STATUS_IND_V01 0x0022
- #define QMI_DFC_TX_LINK_STATUS_IND_V01 0x0024
- #define QMI_DFC_GET_FLOW_STATUS_REQ_V01 0x0023
- #define QMI_DFC_GET_FLOW_STATUS_RESP_V01 0x0023
- #define QMI_DFC_GET_FLOW_STATUS_REQ_V01_MAX_MSG_LEN 20
- #define QMI_DFC_GET_FLOW_STATUS_RESP_V01_MAX_MSG_LEN 543
- struct dfc_bind_client_req_msg_v01 {
- u8 ep_id_valid;
- struct data_ep_id_type_v01 ep_id;
- };
- struct dfc_bind_client_resp_msg_v01 {
- struct qmi_response_type_v01 resp;
- };
- struct dfc_indication_register_req_msg_v01 {
- u8 report_flow_status_valid;
- u8 report_flow_status;
- u8 report_tx_link_status_valid;
- u8 report_tx_link_status;
- };
- struct dfc_indication_register_resp_msg_v01 {
- struct qmi_response_type_v01 resp;
- };
- static struct qmi_elem_info dfc_qos_id_type_v01_ei[] = {
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct dfc_qos_id_type_v01,
- qos_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(enum dfc_ip_type_enum_v01),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct dfc_qos_id_type_v01,
- ip_type),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- subs_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- mux_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- bearer_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- num_bytes),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- seq_num),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- qos_ids_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = DFC_MAX_QOS_ID_V01,
- .elem_size = sizeof(struct dfc_qos_id_type_v01),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_flow_status_info_type_v01,
- qos_ids),
- .ei_array = dfc_qos_id_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_ancillary_info_type_v01_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_ancillary_info_type_v01,
- subs_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_ancillary_info_type_v01,
- mux_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_ancillary_info_type_v01,
- bearer_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_ancillary_info_type_v01,
- reserved),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- struct dfc_get_flow_status_req_msg_v01 {
- u8 bearer_id_list_valid;
- u8 bearer_id_list_len;
- u8 bearer_id_list[DFC_MAX_BEARERS_V01];
- };
- struct dfc_get_flow_status_resp_msg_v01 {
- struct qmi_response_type_v01 resp;
- u8 flow_status_valid;
- u8 flow_status_len;
- struct dfc_flow_status_info_type_v01 flow_status[DFC_MAX_BEARERS_V01];
- };
- struct dfc_svc_ind {
- struct list_head list;
- u16 msg_id;
- union {
- struct dfc_flow_status_ind_msg_v01 dfc_info;
- struct dfc_tx_link_status_ind_msg_v01 tx_status;
- } d;
- };
- static struct qmi_elem_info dfc_bind_client_req_msg_v01_ei[] = {
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct dfc_bind_client_req_msg_v01,
- ep_id_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct data_ep_id_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct dfc_bind_client_req_msg_v01,
- ep_id),
- .ei_array = data_ep_id_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_bind_client_resp_msg_v01_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct dfc_bind_client_resp_msg_v01,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_indication_register_req_msg_v01_ei[] = {
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_indication_register_req_msg_v01,
- report_flow_status_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_indication_register_req_msg_v01,
- report_flow_status),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct
- dfc_indication_register_req_msg_v01,
- report_tx_link_status_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct
- dfc_indication_register_req_msg_v01,
- report_tx_link_status),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_indication_register_resp_msg_v01_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct
- dfc_indication_register_resp_msg_v01,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_flow_status_ind_v01_ei[] = {
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- flow_status_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- flow_status_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = DFC_MAX_BEARERS_V01,
- .elem_size = sizeof(struct
- dfc_flow_status_info_type_v01),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- flow_status),
- .ei_array = dfc_flow_status_info_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- eod_ack_reqd_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- eod_ack_reqd),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- ancillary_info_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- ancillary_info_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = DFC_MAX_BEARERS_V01,
- .elem_size = sizeof(struct
- dfc_ancillary_info_type_v01),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct
- dfc_flow_status_ind_msg_v01,
- ancillary_info),
- .ei_array = dfc_ancillary_info_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_get_flow_status_req_msg_v01_ei[] = {
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_req_msg_v01,
- bearer_id_list_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_req_msg_v01,
- bearer_id_list_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = DFC_MAX_BEARERS_V01,
- .elem_size = sizeof(u8),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_req_msg_v01,
- bearer_id_list),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_get_flow_status_resp_msg_v01_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct
- dfc_get_flow_status_resp_msg_v01,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_resp_msg_v01,
- flow_status_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_resp_msg_v01,
- flow_status_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = DFC_MAX_BEARERS_V01,
- .elem_size = sizeof(struct
- dfc_flow_status_info_type_v01),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_get_flow_status_resp_msg_v01,
- flow_status),
- .ei_array = dfc_flow_status_info_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_bearer_info_type_v01_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_bearer_info_type_v01,
- subs_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_bearer_info_type_v01,
- mux_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_bearer_info_type_v01,
- bearer_id),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(enum dfc_ip_type_enum_v01),
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- .offset = offsetof(struct
- dfc_bearer_info_type_v01,
- ip_type),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static struct qmi_elem_info dfc_tx_link_status_ind_v01_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct
- dfc_tx_link_status_ind_msg_v01,
- tx_status),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_tx_link_status_ind_msg_v01,
- bearer_info_valid),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_tx_link_status_ind_msg_v01,
- bearer_info_len),
- .ei_array = NULL,
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = DFC_MAX_BEARERS_V01,
- .elem_size = sizeof(struct
- dfc_bearer_info_type_v01),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct
- dfc_tx_link_status_ind_msg_v01,
- bearer_info),
- .ei_array = dfc_bearer_info_type_v01_ei,
- },
- {
- .data_type = QMI_EOTI,
- .array_type = NO_ARRAY,
- .tlv_type = QMI_COMMON_TLV_TYPE,
- },
- };
- static int
- dfc_bind_client_req(struct qmi_handle *dfc_handle,
- struct sockaddr_qrtr *ssctl, struct svc_info *svc)
- {
- struct dfc_bind_client_resp_msg_v01 *resp;
- struct dfc_bind_client_req_msg_v01 *req;
- struct qmi_txn txn;
- int ret;
- req = kzalloc(sizeof(*req), GFP_ATOMIC);
- if (!req)
- return -ENOMEM;
- resp = kzalloc(sizeof(*resp), GFP_ATOMIC);
- if (!resp) {
- kfree(req);
- return -ENOMEM;
- }
- ret = qmi_txn_init(dfc_handle, &txn,
- dfc_bind_client_resp_msg_v01_ei, resp);
- if (ret < 0) {
- pr_err("%s() Failed init for response, err: %d\n",
- __func__, ret);
- goto out;
- }
- req->ep_id_valid = 1;
- req->ep_id.ep_type = svc->ep_type;
- req->ep_id.iface_id = svc->iface_id;
- ret = qmi_send_request(dfc_handle, ssctl, &txn,
- QMI_DFC_BIND_CLIENT_REQ_V01,
- QMI_DFC_BIND_CLIENT_REQ_V01_MAX_MSG_LEN,
- dfc_bind_client_req_msg_v01_ei, req);
- if (ret < 0) {
- qmi_txn_cancel(&txn);
- pr_err("%s() Failed sending request, err: %d\n",
- __func__, ret);
- goto out;
- }
- ret = qmi_txn_wait(&txn, DFC_TIMEOUT_JF);
- if (ret < 0) {
- pr_err("%s() Response waiting failed, err: %d\n",
- __func__, ret);
- } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
- pr_err("%s() Request rejected, result: %d, err: %d\n",
- __func__, resp->resp.result, resp->resp.error);
- ret = -resp->resp.result;
- }
- out:
- kfree(resp);
- kfree(req);
- return ret;
- }
- static int
- dfc_indication_register_req(struct qmi_handle *dfc_handle,
- struct sockaddr_qrtr *ssctl, u8 reg)
- {
- struct dfc_indication_register_resp_msg_v01 *resp;
- struct dfc_indication_register_req_msg_v01 *req;
- struct qmi_txn txn;
- int ret;
- req = kzalloc(sizeof(*req), GFP_ATOMIC);
- if (!req)
- return -ENOMEM;
- resp = kzalloc(sizeof(*resp), GFP_ATOMIC);
- if (!resp) {
- kfree(req);
- return -ENOMEM;
- }
- ret = qmi_txn_init(dfc_handle, &txn,
- dfc_indication_register_resp_msg_v01_ei, resp);
- if (ret < 0) {
- pr_err("%s() Failed init for response, err: %d\n",
- __func__, ret);
- goto out;
- }
- req->report_flow_status_valid = 1;
- req->report_flow_status = reg;
- if (!dfc_ps_ext) {
- req->report_tx_link_status_valid = 1;
- req->report_tx_link_status = reg;
- }
- ret = qmi_send_request(dfc_handle, ssctl, &txn,
- QMI_DFC_INDICATION_REGISTER_REQ_V01,
- QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN,
- dfc_indication_register_req_msg_v01_ei, req);
- if (ret < 0) {
- qmi_txn_cancel(&txn);
- pr_err("%s() Failed sending request, err: %d\n",
- __func__, ret);
- goto out;
- }
- ret = qmi_txn_wait(&txn, DFC_TIMEOUT_JF);
- if (ret < 0) {
- pr_err("%s() Response waiting failed, err: %d\n",
- __func__, ret);
- } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
- pr_err("%s() Request rejected, result: %d, err: %d\n",
- __func__, resp->resp.result, resp->resp.error);
- ret = -resp->resp.result;
- }
- out:
- kfree(resp);
- kfree(req);
- return ret;
- }
- static int
- dfc_get_flow_status_req(struct qmi_handle *dfc_handle,
- struct sockaddr_qrtr *ssctl,
- struct dfc_get_flow_status_resp_msg_v01 *resp)
- {
- struct dfc_get_flow_status_req_msg_v01 *req;
- struct qmi_txn *txn;
- int ret;
- req = kzalloc(sizeof(*req), GFP_ATOMIC);
- if (!req)
- return -ENOMEM;
- txn = kzalloc(sizeof(*txn), GFP_ATOMIC);
- if (!txn) {
- kfree(req);
- return -ENOMEM;
- }
- ret = qmi_txn_init(dfc_handle, txn,
- dfc_get_flow_status_resp_msg_v01_ei, resp);
- if (ret < 0) {
- pr_err("%s() Failed init for response, err: %d\n",
- __func__, ret);
- goto out;
- }
- ret = qmi_send_request(dfc_handle, ssctl, txn,
- QMI_DFC_GET_FLOW_STATUS_REQ_V01,
- QMI_DFC_GET_FLOW_STATUS_REQ_V01_MAX_MSG_LEN,
- dfc_get_flow_status_req_msg_v01_ei, req);
- if (ret < 0) {
- qmi_txn_cancel(txn);
- pr_err("%s() Failed sending request, err: %d\n",
- __func__, ret);
- goto out;
- }
- ret = qmi_txn_wait(txn, DFC_TIMEOUT_JF);
- if (ret < 0) {
- pr_err("%s() Response waiting failed, err: %d\n",
- __func__, ret);
- } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
- pr_err("%s() Request rejected, result: %d, err: %d\n",
- __func__, resp->resp.result, resp->resp.error);
- ret = -resp->resp.result;
- }
- out:
- kfree(txn);
- kfree(req);
- return ret;
- }
- static int dfc_init_service(struct dfc_qmi_data *data)
- {
- int rc;
- rc = dfc_bind_client_req(&data->handle, &data->ssctl, &data->svc);
- if (rc < 0)
- return rc;
- return dfc_indication_register_req(&data->handle, &data->ssctl, 1);
- }
- static void
- dfc_send_ack(struct net_device *dev, u8 bearer_id, u16 seq, u8 mux_id, u8 type)
- {
- struct qos_info *qos = rmnet_get_qos_pt(dev);
- struct sk_buff *skb;
- struct dfc_ack_cmd *msg;
- int data_size = sizeof(struct dfc_ack_cmd);
- int header_size = sizeof(struct dfc_qmap_header);
- if (!qos)
- return;
- if (dfc_qmap) {
- dfc_qmap_send_ack(qos, bearer_id, seq, type);
- return;
- }
- skb = alloc_skb(data_size, GFP_ATOMIC);
- if (!skb)
- return;
- msg = (struct dfc_ack_cmd *)skb_put(skb, data_size);
- memset(msg, 0, data_size);
- msg->header.cd_bit = 1;
- msg->header.mux_id = mux_id;
- msg->header.pkt_len = htons(data_size - header_size);
- msg->bearer_id = bearer_id;
- msg->command_name = 4;
- msg->cmd_type = 0;
- msg->dfc_seq = htons(seq);
- msg->type = type;
- msg->ver = 2;
- msg->transaction_id = htonl(qos->tran_num);
- skb->dev = qos->real_dev;
- skb->protocol = htons(ETH_P_MAP);
- trace_dfc_qmap_cmd(mux_id, bearer_id, seq, type, qos->tran_num);
- qos->tran_num++;
- rmnet_map_tx_qmap_cmd(skb, RMNET_CH_DEFAULT, true);
- }
- int dfc_bearer_flow_ctl(struct net_device *dev,
- struct rmnet_bearer_map *bearer,
- struct qos_info *qos)
- {
- bool enable;
- enable = bearer->grant_size ? true : false;
- /* Do not flow disable tcp ack q in tcp bidir
- * ACK queue opened first to drain ACKs faster
- * Although since tcp ancillary is true most of the time,
- * this shouldn't really make a difference
- * If there is non zero grant but tcp ancillary is false,
- * send out ACKs anyway
- */
- if (bearer->ack_mq_idx != INVALID_MQ)
- qmi_rmnet_flow_control(dev, bearer->ack_mq_idx,
- enable || bearer->tcp_bidir);
- qmi_rmnet_flow_control(dev, bearer->mq_idx, enable);
- if (!enable && bearer->ack_req)
- dfc_send_ack(dev, bearer->bearer_id,
- bearer->seq, qos->mux_id,
- DFC_ACK_TYPE_DISABLE);
- return 0;
- }
- 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 rmnet_bearer_map *bearer;
- list_for_each_entry(bearer, &qos->bearer_head, list) {
- bearer->grant_size = fc_info->num_bytes;
- bearer->grant_thresh =
- qmi_rmnet_grant_per(bearer->grant_size);
- bearer->seq = fc_info->seq_num;
- bearer->ack_req = ack_req;
- bearer->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
- bearer->last_grant = fc_info->num_bytes;
- bearer->last_seq = fc_info->seq_num;
- bearer->last_adjusted_grant = fc_info->num_bytes;
- dfc_bearer_flow_ctl(dev, bearer, qos);
- }
- return 0;
- }
- static u32 dfc_adjust_grant(struct rmnet_bearer_map *bearer,
- struct dfc_flow_status_info_type_v01 *fc_info)
- {
- u32 grant;
- if (!fc_info->rx_bytes_valid)
- return fc_info->num_bytes;
- if (bearer->bytes_in_flight > fc_info->rx_bytes)
- bearer->bytes_in_flight -= fc_info->rx_bytes;
- else
- bearer->bytes_in_flight = 0;
- /* Adjusted grant = grant - bytes_in_flight */
- if (fc_info->num_bytes > bearer->bytes_in_flight)
- grant = fc_info->num_bytes - bearer->bytes_in_flight;
- else
- grant = 0;
- trace_dfc_adjust_grant(fc_info->mux_id, fc_info->bearer_id,
- fc_info->num_bytes, fc_info->rx_bytes,
- bearer->bytes_in_flight, grant);
- return grant;
- }
- static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
- u8 ack_req, u32 ancillary,
- struct dfc_flow_status_info_type_v01 *fc_info,
- bool is_query)
- {
- struct rmnet_bearer_map *itm = NULL;
- int rc = 0;
- bool action = false;
- u32 adjusted_grant;
- itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
- /* cache the bearer assuming it is a new bearer */
- if (unlikely(!itm && !is_query && fc_info->num_bytes))
- itm = qmi_rmnet_get_bearer_noref(qos, fc_info->bearer_id);
- if (itm) {
- /* The RAT switch flag indicates the start and end of
- * the switch. Ignore indications in between.
- */
- if (DFC_IS_RAT_SWITCH(ancillary))
- itm->rat_switch = !fc_info->num_bytes;
- else
- if (itm->rat_switch)
- return 0;
- /* If TX is OFF but we received grant, ignore it */
- if (itm->tx_off && fc_info->num_bytes > 0)
- return 0;
- if (fc_info->ll_status &&
- itm->ch_switch.current_ch != RMNET_CH_LL) {
- itm->ch_switch.current_ch = RMNET_CH_LL;
- itm->ch_switch.auto_switched = true;
- if (itm->mq_idx < MAX_MQ_NUM)
- qos->mq[itm->mq_idx].is_ll_ch = RMNET_CH_LL;
- }
- /* Adjuste grant for query */
- if (dfc_qmap && is_query) {
- adjusted_grant = dfc_adjust_grant(itm, fc_info);
- } else {
- adjusted_grant = fc_info->num_bytes;
- itm->bytes_in_flight = 0;
- }
- /* update queue state only if there is a change in grant
- * or change in ancillary tcp state
- */
- if ((itm->grant_size == 0 && adjusted_grant > 0) ||
- (itm->grant_size > 0 && adjusted_grant == 0) ||
- (itm->tcp_bidir ^ DFC_IS_TCP_BIDIR(ancillary)))
- action = true;
- /* This is needed by qmap */
- if (dfc_qmap && itm->ack_req && !ack_req && itm->grant_size)
- dfc_qmap_send_ack(qos, itm->bearer_id,
- itm->seq, DFC_ACK_TYPE_DISABLE);
- itm->grant_size = adjusted_grant;
- /* No further query if the adjusted grant is less
- * than 20% of the original grant. Add to watch to
- * recover if no indication is received.
- */
- if (dfc_qmap && is_query &&
- itm->grant_size < (fc_info->num_bytes / 5)) {
- itm->grant_thresh = itm->grant_size;
- qmi_rmnet_watchdog_add(itm);
- } else {
- itm->grant_thresh =
- qmi_rmnet_grant_per(itm->grant_size);
- qmi_rmnet_watchdog_remove(itm);
- }
- itm->seq = fc_info->seq_num;
- itm->ack_req = ack_req;
- itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
- itm->last_grant = fc_info->num_bytes;
- itm->last_seq = fc_info->seq_num;
- itm->last_adjusted_grant = adjusted_grant;
- if (action)
- rc = dfc_bearer_flow_ctl(dev, itm, qos);
- }
- return rc;
- }
- void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
- struct dfc_flow_status_ind_msg_v01 *ind,
- bool is_query)
- {
- struct net_device *dev;
- struct qos_info *qos;
- struct dfc_flow_status_info_type_v01 *flow_status;
- struct dfc_ancillary_info_type_v01 *ai;
- u8 ack_req = ind->eod_ack_reqd_valid ? ind->eod_ack_reqd : 0;
- u32 ancillary;
- int i, j;
- rcu_read_lock();
- for (i = 0; i < ind->flow_status_len; i++) {
- flow_status = &ind->flow_status[i];
- ancillary = 0;
- if (ind->ancillary_info_valid) {
- for (j = 0; j < ind->ancillary_info_len; j++) {
- ai = &ind->ancillary_info[j];
- if (ai->mux_id == flow_status->mux_id &&
- ai->bearer_id == flow_status->bearer_id) {
- ancillary = ai->reserved;
- break;
- }
- }
- }
- trace_dfc_flow_ind(dfc->index,
- i, flow_status->mux_id,
- flow_status->bearer_id,
- flow_status->num_bytes,
- flow_status->seq_num,
- ack_req,
- ancillary);
- dev = rmnet_get_rmnet_dev(dfc->rmnet_port,
- flow_status->mux_id);
- if (!dev)
- goto clean_out;
- qos = (struct qos_info *)rmnet_get_qos_pt(dev);
- if (!qos)
- continue;
- spin_lock_bh(&qos->qos_lock);
- /* In powersave, change grant to 1 if it is a enable */
- if (qmi_rmnet_ignore_grant(dfc->rmnet_port)) {
- if (flow_status->num_bytes) {
- flow_status->num_bytes = DEFAULT_GRANT;
- flow_status->seq_num = 0;
- /* below is to reset bytes-in-flight */
- flow_status->rx_bytes_valid = 1;
- flow_status->rx_bytes = 0xFFFFFFFF;
- } else {
- spin_unlock_bh(&qos->qos_lock);
- continue;
- }
- }
- if (unlikely(flow_status->bearer_id == 0xFF))
- dfc_all_bearer_flow_ctl(
- dev, qos, ack_req, ancillary, flow_status);
- else
- dfc_update_fc_map(
- dev, qos, ack_req, ancillary, flow_status,
- is_query);
- spin_unlock_bh(&qos->qos_lock);
- }
- clean_out:
- rcu_read_unlock();
- }
- static void dfc_update_tx_link_status(struct net_device *dev,
- struct qos_info *qos, u8 tx_status,
- struct dfc_bearer_info_type_v01 *binfo)
- {
- struct rmnet_bearer_map *itm = NULL;
- itm = qmi_rmnet_get_bearer_map(qos, binfo->bearer_id);
- if (!itm)
- return;
- /* If no change in tx status, ignore */
- if (itm->tx_off == !tx_status)
- return;
- if (itm->grant_size && !tx_status) {
- itm->grant_size = 0;
- itm->tcp_bidir = false;
- itm->bytes_in_flight = 0;
- qmi_rmnet_watchdog_remove(itm);
- dfc_bearer_flow_ctl(dev, itm, qos);
- } else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) {
- itm->grant_size = DEFAULT_GRANT;
- itm->grant_thresh = qmi_rmnet_grant_per(DEFAULT_GRANT);
- itm->seq = 0;
- itm->ack_req = 0;
- dfc_bearer_flow_ctl(dev, itm, qos);
- }
- itm->tx_off = !tx_status;
- }
- void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
- struct dfc_tx_link_status_ind_msg_v01 *ind)
- {
- struct net_device *dev;
- struct qos_info *qos;
- struct dfc_bearer_info_type_v01 *bearer_info;
- int i;
- rcu_read_lock();
- for (i = 0; i < ind->bearer_info_len; i++) {
- bearer_info = &ind->bearer_info[i];
- trace_dfc_tx_link_status_ind(dfc->index, i,
- ind->tx_status,
- bearer_info->mux_id,
- bearer_info->bearer_id);
- dev = rmnet_get_rmnet_dev(dfc->rmnet_port,
- bearer_info->mux_id);
- if (!dev)
- goto clean_out;
- qos = (struct qos_info *)rmnet_get_qos_pt(dev);
- if (!qos)
- continue;
- spin_lock_bh(&qos->qos_lock);
- dfc_update_tx_link_status(
- dev, qos, ind->tx_status, bearer_info);
- spin_unlock_bh(&qos->qos_lock);
- }
- 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)
- break;
- if (!dfc->restart_state) {
- if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01)
- dfc_do_burst_flow_control(
- dfc, &svc_ind->d.dfc_info,
- false);
- else if (svc_ind->msg_id ==
- QMI_DFC_TX_LINK_STATUS_IND_V01)
- dfc_handle_tx_link_status_ind(
- dfc, &svc_ind->d.tx_status);
- }
- kfree(svc_ind);
- } while (1);
- local_bh_enable();
- qmi_rmnet_set_dl_msg_active(dfc->rmnet_port);
- }
- static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
- struct qmi_txn *txn, const void *data)
- {
- struct dfc_qmi_data *dfc = container_of(qmi, struct dfc_qmi_data,
- handle);
- struct dfc_flow_status_ind_msg_v01 *ind_msg;
- struct dfc_svc_ind *svc_ind;
- unsigned long flags;
- if (qmi != &dfc->handle)
- return;
- ind_msg = (struct dfc_flow_status_ind_msg_v01 *)data;
- if (ind_msg->flow_status_valid) {
- if (ind_msg->flow_status_len > DFC_MAX_BEARERS_V01) {
- pr_err("%s() Invalid fc info len: %d\n",
- __func__, ind_msg->flow_status_len);
- return;
- }
- svc_ind = kzalloc(sizeof(struct dfc_svc_ind), GFP_ATOMIC);
- if (!svc_ind)
- return;
- svc_ind->msg_id = QMI_DFC_FLOW_STATUS_IND_V01;
- memcpy(&svc_ind->d.dfc_info, ind_msg, sizeof(*ind_msg));
- 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);
- }
- }
- static void dfc_tx_link_status_ind_cb(struct qmi_handle *qmi,
- struct sockaddr_qrtr *sq,
- struct qmi_txn *txn, const void *data)
- {
- struct dfc_qmi_data *dfc = container_of(qmi, struct dfc_qmi_data,
- handle);
- struct dfc_tx_link_status_ind_msg_v01 *ind_msg;
- struct dfc_svc_ind *svc_ind;
- unsigned long flags;
- if (qmi != &dfc->handle)
- return;
- ind_msg = (struct dfc_tx_link_status_ind_msg_v01 *)data;
- if (ind_msg->bearer_info_valid) {
- if (ind_msg->bearer_info_len > DFC_MAX_BEARERS_V01) {
- pr_err("%s() Invalid bearer info len: %d\n",
- __func__, ind_msg->bearer_info_len);
- return;
- }
- svc_ind = kzalloc(sizeof(struct dfc_svc_ind), GFP_ATOMIC);
- if (!svc_ind)
- return;
- svc_ind->msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01;
- memcpy(&svc_ind->d.tx_status, ind_msg, sizeof(*ind_msg));
- 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);
- }
- }
- static void dfc_svc_init(struct work_struct *work)
- {
- int rc = 0;
- struct dfc_qmi_data *data = container_of(work, struct dfc_qmi_data,
- svc_arrive);
- struct qmi_info *qmi;
- if (data->restart_state == 1)
- return;
- rc = dfc_init_service(data);
- if (rc < 0) {
- pr_err("%s Failed to init service, err[%d]\n", __func__, rc);
- return;
- }
- if (data->restart_state == 1)
- return;
- while (!rtnl_trylock()) {
- if (!data->restart_state)
- cond_resched();
- else
- return;
- }
- qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port);
- if (!qmi) {
- rtnl_unlock();
- return;
- }
- qmi->dfc_pending[data->index] = NULL;
- qmi->dfc_clients[data->index] = (void *)data;
- trace_dfc_client_state_up(data->index,
- data->svc.instance,
- data->svc.ep_type,
- data->svc.iface_id);
- rtnl_unlock();
- pr_info("Connection established with the DFC Service\n");
- }
- static int dfc_svc_arrive(struct qmi_handle *qmi, struct qmi_service *svc)
- {
- struct dfc_qmi_data *data = container_of(qmi, struct dfc_qmi_data,
- handle);
- data->ssctl.sq_family = AF_QIPCRTR;
- data->ssctl.sq_node = svc->node;
- data->ssctl.sq_port = svc->port;
- queue_work(data->dfc_wq, &data->svc_arrive);
- return 0;
- }
- static void dfc_svc_exit(struct qmi_handle *qmi, struct qmi_service *svc)
- {
- struct dfc_qmi_data *data = container_of(qmi, struct dfc_qmi_data,
- handle);
- if (!data)
- pr_debug("%s() data is null\n", __func__);
- }
- static struct qmi_ops server_ops = {
- .new_server = dfc_svc_arrive,
- .del_server = dfc_svc_exit,
- };
- static struct qmi_msg_handler qmi_indication_handler[] = {
- {
- .type = QMI_INDICATION,
- .msg_id = QMI_DFC_FLOW_STATUS_IND_V01,
- .ei = dfc_flow_status_ind_v01_ei,
- .decoded_size = sizeof(struct dfc_flow_status_ind_msg_v01),
- .fn = dfc_clnt_ind_cb,
- },
- {
- .type = QMI_INDICATION,
- .msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01,
- .ei = dfc_tx_link_status_ind_v01_ei,
- .decoded_size = sizeof(struct dfc_tx_link_status_ind_msg_v01),
- .fn = dfc_tx_link_status_ind_cb,
- },
- {},
- };
- int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc,
- struct qmi_info *qmi)
- {
- struct dfc_qmi_data *data;
- int rc = -ENOMEM;
- if (!port || !qmi)
- return -EINVAL;
- data = kzalloc(sizeof(struct dfc_qmi_data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- 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) {
- pr_err("%s Could not create workqueue\n", __func__);
- goto err0;
- }
- INIT_WORK(&data->svc_arrive, dfc_svc_init);
- rc = qmi_handle_init(&data->handle,
- QMI_DFC_GET_FLOW_STATUS_RESP_V01_MAX_MSG_LEN,
- &server_ops, qmi_indication_handler);
- if (rc < 0) {
- pr_err("%s: failed qmi_handle_init - rc[%d]\n", __func__, rc);
- goto err1;
- }
- rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01,
- DFC_SERVICE_VERS_V01,
- psvc->instance);
- if (rc < 0) {
- pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc);
- goto err2;
- }
- qmi->dfc_pending[index] = (void *)data;
- return 0;
- err2:
- qmi_handle_release(&data->handle);
- err1:
- destroy_workqueue(data->dfc_wq);
- err0:
- kfree(data);
- return rc;
- }
- void dfc_qmi_client_exit(void *dfc_data)
- {
- struct dfc_qmi_data *data = (struct dfc_qmi_data *)dfc_data;
- if (!data) {
- pr_err("%s() data is null\n", __func__);
- return;
- }
- data->restart_state = 1;
- trace_dfc_client_state_down(data->index, 0);
- qmi_handle_release(&data->handle);
- drain_workqueue(data->dfc_wq);
- destroy_workqueue(data->dfc_wq);
- kfree(data);
- }
- void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos,
- int ip_type, u32 mark, unsigned int len)
- {
- struct rmnet_bearer_map *bearer = NULL;
- struct rmnet_flow_map *itm;
- u32 start_grant;
- spin_lock_bh(&qos->qos_lock);
- /* Mark is flow_id */
- itm = qmi_rmnet_get_flow_map(qos, mark, ip_type);
- if (likely(itm))
- bearer = itm->bearer;
- if (unlikely(!bearer))
- goto out;
- trace_dfc_flow_check(dev->name, bearer->bearer_id,
- len, mark, bearer->grant_size);
- bearer->bytes_in_flight += len;
- if (!bearer->grant_size)
- goto out;
- start_grant = bearer->grant_size;
- if (len >= bearer->grant_size)
- bearer->grant_size = 0;
- else
- bearer->grant_size -= len;
- if (start_grant > bearer->grant_thresh &&
- bearer->grant_size <= bearer->grant_thresh) {
- dfc_send_ack(dev, bearer->bearer_id,
- bearer->seq, qos->mux_id,
- DFC_ACK_TYPE_THRESHOLD);
- }
- if (!bearer->grant_size)
- dfc_bearer_flow_ctl(dev, bearer, qos);
- out:
- spin_unlock_bh(&qos->qos_lock);
- }
- void dfc_qmi_query_flow(void *dfc_data)
- {
- struct dfc_qmi_data *data = (struct dfc_qmi_data *)dfc_data;
- struct dfc_get_flow_status_resp_msg_v01 *resp;
- struct dfc_svc_ind *svc_ind;
- int rc;
- resp = kzalloc(sizeof(*resp), GFP_ATOMIC);
- if (!resp)
- return;
- svc_ind = kzalloc(sizeof(*svc_ind), GFP_ATOMIC);
- if (!svc_ind) {
- kfree(resp);
- return;
- }
- if (!data)
- goto done;
- rc = dfc_get_flow_status_req(&data->handle, &data->ssctl, resp);
- if (rc < 0 || !resp->flow_status_valid || resp->flow_status_len < 1 ||
- resp->flow_status_len > DFC_MAX_BEARERS_V01)
- goto done;
- svc_ind->d.dfc_info.flow_status_valid = resp->flow_status_valid;
- svc_ind->d.dfc_info.flow_status_len = resp->flow_status_len;
- memcpy(&svc_ind->d.dfc_info.flow_status, resp->flow_status,
- sizeof(resp->flow_status[0]) * resp->flow_status_len);
- dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info, true);
- done:
- kfree(svc_ind);
- kfree(resp);
- }
|