net: rmnet_usb: Add sleep state extended IOCTL

By default HSIC autosuspend is enabled, however it may
introduce additional latency depending on client application
usecase. Add support for sleep state IOCTL to allow the client
to enable/disable the autosuspend as needed.

Change-Id: Ib4e2f9e83f86837e05339689c8735c843483bb3d
Signed-off-by: Azhar Shaikh <azhars@codeaurora.org>
This commit is contained in:
Azhar Shaikh 2014-07-01 17:54:56 -07:00
parent b2493d0531
commit ee337c6f35
2 changed files with 35 additions and 0 deletions

View File

@ -88,6 +88,9 @@ struct rmnet_ctrl_udev {
unsigned int zlp_cnt;
unsigned int invalid_mux_id_cnt;
unsigned int ignore_encap_work;
bool autosuspend_disabled;
unsigned int autosuspend_en_cnt;
unsigned int autosuspend_dis_cnt;
};
struct rmnet_ctrl_dev {

View File

@ -133,6 +133,7 @@ module_param_cb(rmnet_data_init, &rmnet_init_ops, &rmnet_data_init,
static void rmnet_usb_setup(struct net_device *);
static int rmnet_ioctl(struct net_device *, struct ifreq *, int);
static void rmnet_usb_disable_hsic_autosuspend(struct usbnet *, int);
static int rmnet_usb_suspend(struct usb_interface *iface, pm_message_t message)
{
@ -167,6 +168,26 @@ static int rmnet_usb_resume(struct usb_interface *iface)
return rmnet_usb_ctrl_start_rx(dev);
}
static void rmnet_usb_disable_hsic_autosuspend(struct usbnet *usbnet,
int enable_autosuspend)
{
struct usb_device *usb_dev = usbnet->udev;
struct rmnet_ctrl_udev *rmnet_udev =
(struct rmnet_ctrl_udev *)usbnet->data[1];
usb_get_dev(usb_dev);
if (!enable_autosuspend) {
usb_disable_autosuspend(usb_dev);
rmnet_udev->autosuspend_disabled = 1;
rmnet_udev->autosuspend_dis_cnt++;
} else {
usb_enable_autosuspend(usb_dev);
rmnet_udev->autosuspend_disabled = 0;
rmnet_udev->autosuspend_en_cnt++;
}
usb_put_dev(usb_dev);
}
static int rmnet_usb_bind(struct usbnet *usbnet, struct usb_interface *iface)
{
struct usb_host_endpoint *endpoint = NULL;
@ -362,6 +383,9 @@ static int rmnet_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
ext_cmd.u.data =
unet->intf->cur_altsetting->desc.bInterfaceNumber;
break;
case RMNET_IOCTL_SET_SLEEP_STATE:
rmnet_usb_disable_hsic_autosuspend(unet, ext_cmd.u.data);
break;
}
rc = copy_to_user(ifr->ifr_ifru.ifru_data, &ext_cmd,
@ -496,6 +520,8 @@ static void rmnet_usb_setup(struct net_device *dev)
static int rmnet_usb_data_status(struct seq_file *s, void *unused)
{
struct usbnet *unet = s->private;
struct rmnet_ctrl_udev *rmnet_udev =
(struct rmnet_ctrl_udev *)unet->data[1];
seq_printf(s, "RMNET_MODE_LLP_IP: %d\n",
test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
@ -528,6 +554,12 @@ static int rmnet_usb_data_status(struct seq_file *s, void *unused)
test_bit(EVENT_RX_MEMORY, &unet->flags));
seq_printf(s, "EVENT_DEV_ASLEEP: %d\n",
test_bit(EVENT_DEV_ASLEEP, &unet->flags));
seq_printf(s, "autosuspend_disabled: %d\n",
rmnet_udev->autosuspend_disabled);
seq_printf(s, "No. of times autosuspend enabled: %d\n",
rmnet_udev->autosuspend_en_cnt);
seq_printf(s, "No. of times autosuspend disabled: %d\n",
rmnet_udev->autosuspend_dis_cnt);
return 0;
}