rmnetctl: add library API and CLI option for new DFC messages
As part of the DFC driver porting process to the 4.19 kernel, the module
parameters for the QMI ACK scaling and the WDA powersave polling frequency
were removed and replaced with new Netlink messages. This patch adds the
support for creating and sending the new messages to alter these values.
Change-Id: I31796b0c8e4b520384e9f50e6d173d8e2d2d0456
Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
diff --git a/rmnetctl/cli/rmnetcli.c b/rmnetctl/cli/rmnetcli.c
index 1b1c938..0f496a6 100644
--- a/rmnetctl/cli/rmnetcli.c
+++ b/rmnetctl/cli/rmnetcli.c
@@ -247,7 +247,12 @@
printf(_2TABS" <iface_id> int - iface id\n\n");
printf(_2TABS" <flags> int - flags\n\n");
printf("rmnetcli -n systemdown <real dev> <vnd name> <instance>\n\n ");
-
+ printf("rmnetcli -n qmiscale <real dev> set ACK scale factor\n\n");
+ printf(_2TABS" <vnd_name> string - vnd device name\n\n");
+ printf(_2TABS" <scale> int - scale factor\n\n");
+ printf("rmnetcli -n wdafreq <real dev> set powersave poll freq\n\n");
+ printf(_2TABS" <vnd_name> string - vnd device name\n\n");
+ printf(_2TABS" <freq> int - frequency\n\n");
}
@@ -447,6 +452,22 @@
return_code = rtrmnet_flow_state_down(handle, argv[1], argv[2],
_STRTOUI32(argv[3]),
&error_number);
+ } else if (!strcmp(*argv, "qmiscale")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ _RMNETCLI_CHECKNULL(argv[2]);
+ _RMNETCLI_CHECKNULL(argv[3]);
+
+ return_code = rtrmnet_set_qmi_scale(handle, argv[1], argv[2],
+ _STRTOUI32(argv[3]),
+ &error_number);
+ } else if (!strcmp(*argv, "wdafreq")) {
+ _RMNETCLI_CHECKNULL(argv[1]);
+ _RMNETCLI_CHECKNULL(argv[2]);
+ _RMNETCLI_CHECKNULL(argv[3]);
+
+ return_code = rtrmnet_set_wda_freq(handle, argv[1], argv[2],
+ _STRTOUI32(argv[3]),
+ &error_number);
}
diff --git a/rmnetctl/inc/librmnetctl.h b/rmnetctl/inc/librmnetctl.h
index 4651fda..3dc8237 100644
--- a/rmnetctl/inc/librmnetctl.h
+++ b/rmnetctl/inc/librmnetctl.h
@@ -668,5 +668,17 @@
int flags,
uint16_t *error_code);
+int rtrmnet_set_qmi_scale(rmnetctl_hndl_t *hndl,
+ char *devname,
+ char *vndname,
+ uint32_t scale,
+ uint16_t *error_code);
+
+int rtrmnet_set_wda_freq(rmnetctl_hndl_t *hndl,
+ char *devname,
+ char *vndname,
+ uint32_t freq,
+ uint16_t *error_code);
+
#endif /* not defined LIBRMNETCTL_H */
diff --git a/rmnetctl/src/librmnetctl.c b/rmnetctl/src/librmnetctl.c
index abfa704..8e60aef 100644
--- a/rmnetctl/src/librmnetctl.c
+++ b/rmnetctl/src/librmnetctl.c
@@ -108,6 +108,10 @@
RMNET_FLOW_MSG_UP = 4,
/* Flow down */
RMNET_FLOW_MSG_DOWN = 5,
+ /* Change ACK scaling */
+ RMNET_FLOW_MSG_QMI_SCALE = 6,
+ /* Change powersave workqueue polling freq */
+ RMNET_FLOW_MSG_WDA_FREQ = 7,
};
#define RMNETCTL_NUM_TX_QUEUES 10
@@ -1905,3 +1909,103 @@
return rmnet_get_ack(hndl, error_code);
}
+
+int rtrmnet_set_qmi_scale(rmnetctl_hndl_t *hndl,
+ char *devname,
+ char *vndname,
+ uint32_t scale,
+ uint16_t *error_code)
+{
+ struct tcmsg flowinfo;
+ struct nlmsg req;
+ unsigned int devindex = 0;
+ size_t reqsize;
+ int rc;
+
+ memset(&req, 0, sizeof(req));
+ memset(&flowinfo, 0, sizeof(flowinfo));
+
+ if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+ _rmnetctl_check_dev_name(vndname) || !scale)
+ return RMNETCTL_INVALID_ARG;
+
+ reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+ req.nl_addr.nlmsg_type = RTM_NEWLINK;
+ req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.nl_addr.nlmsg_seq = hndl->transaction_id;
+ hndl->transaction_id++;
+
+ /* Get index of devname*/
+ devindex = if_nametoindex(devname);
+ if (devindex == 0) {
+ *error_code = errno;
+ return RMNETCTL_KERNEL_ERR;
+ }
+
+ flowinfo.tcm_ifindex = scale;
+ flowinfo.tcm_family = RMNET_FLOW_MSG_QMI_SCALE;
+
+ rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
+ if (rc != RMNETCTL_SUCCESS) {
+ *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+ return rc;
+ }
+
+ if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+ *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+ return RMNETCTL_LIB_ERR;
+ }
+
+ return rmnet_get_ack(hndl, error_code);
+}
+
+int rtrmnet_set_wda_freq(rmnetctl_hndl_t *hndl,
+ char *devname,
+ char *vndname,
+ uint32_t freq,
+ uint16_t *error_code)
+{
+ struct tcmsg flowinfo;
+ struct nlmsg req;
+ unsigned int devindex = 0;
+ size_t reqsize;
+ int rc;
+
+ memset(&req, 0, sizeof(req));
+ memset(&flowinfo, 0, sizeof(flowinfo));
+
+ if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+ _rmnetctl_check_dev_name(vndname))
+ return RMNETCTL_INVALID_ARG;
+
+ reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+ req.nl_addr.nlmsg_type = RTM_NEWLINK;
+ req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.nl_addr.nlmsg_seq = hndl->transaction_id;
+ hndl->transaction_id++;
+
+ /* Get index of devname*/
+ devindex = if_nametoindex(devname);
+ if (devindex == 0) {
+ *error_code = errno;
+ return RMNETCTL_KERNEL_ERR;
+ }
+
+ flowinfo.tcm_ifindex = freq;
+ flowinfo.tcm_family = RMNET_FLOW_MSG_WDA_FREQ;
+
+ rc = rmnet_fill_flow_msg(&req, &reqsize, devindex, vndname, &flowinfo);
+ if (rc != RMNETCTL_SUCCESS) {
+ *error_code = RMNETCTL_API_ERR_RTA_FAILURE;
+ return rc;
+ }
+
+ if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+ *error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+ return RMNETCTL_LIB_ERR;
+ }
+
+ return rmnet_get_ack(hndl, error_code);
+}