diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
index fb1dec3..8bb7e3c 100644
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -54,6 +54,8 @@ struct f_ecm {
 	u8				notify_state;
 	atomic_t			notify_count;
 	bool				is_open;
+	bool				func_wakeup_allowed;
+	bool				func_is_suspended;
 
 	/* FIXME is_open needs some irq-ish locking
 	 * ... possibly the same as port.ioport
@@ -631,6 +633,8 @@ static void ecm_disable(struct usb_function *f)
 		ecm->port.out_ep->desc = NULL;
 	}
 
+	ecm->func_wakeup_allowed = false;
+	ecm->func_is_suspended = false;
 	usb_ep_disable(ecm->notify);
 	ecm->notify->desc = NULL;
 }
@@ -894,9 +898,14 @@ static void ecm_suspend(struct usb_function *f)
 	struct f_ecm *ecm = func_to_ecm(f);
 	struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
 
+	if (ecm->func_is_suspended) {
+		DBG(cdev, "Function already suspended\n");
+		return;
+	}
+
 	DBG(cdev, "ECM Suspend\n");
 
-	gether_suspend(&ecm->port);
+	gether_suspend(&ecm->port, ecm->func_wakeup_allowed);
 }
 
 static void ecm_resume(struct usb_function *f)
@@ -906,7 +915,41 @@ static void ecm_resume(struct usb_function *f)
 
 	DBG(cdev, "ECM Resume\n");
 
-	gether_resume(&ecm->port);
+	gether_resume(&ecm->port, ecm->func_is_suspended);
+}
+
+static int ecm_get_status(struct usb_function *f)
+{
+	struct f_ecm *ecm = func_to_ecm(f);
+
+	return (ecm->func_wakeup_allowed ? USB_INTRF_STAT_FUNC_RW : 0) |
+		USB_INTRF_STAT_FUNC_RW_CAP;
+}
+
+static int ecm_func_suspend(struct usb_function *f, u8 options)
+{
+	bool func_wakeup_allowed;
+	struct f_ecm *ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
+
+	DBG(cdev, "func susp %u cmd\n", options);
+
+	func_wakeup_allowed = !!(options & (USB_INTRF_FUNC_SUSPEND_RW >> 8));
+	if (options & (USB_INTRF_FUNC_SUSPEND_LP >> 8)) {
+		ecm->func_wakeup_allowed = func_wakeup_allowed;
+		if (!ecm->func_is_suspended) {
+			ecm_suspend(f);
+			ecm->func_is_suspended = true;
+		}
+	} else {
+		if (ecm->func_is_suspended) {
+			ecm->func_is_suspended = false;
+			ecm_resume(f);
+		}
+		ecm->func_wakeup_allowed = func_wakeup_allowed;
+	}
+
+	return 0;
 }
 
 static void ecm_free(struct usb_function *f)
@@ -977,6 +1020,8 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
 	ecm->port.func.disable = ecm_disable;
 	ecm->port.func.free_func = ecm_free;
 	ecm->port.func.suspend = ecm_suspend;
+	ecm->port.func.get_status = ecm_get_status;
+	ecm->port.func.func_suspend = ecm_func_suspend;
 	ecm->port.func.resume = ecm_resume;
 
 	return &ecm->port.func;
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 78391de..f3e1c9b 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -477,8 +477,17 @@ static int ether_wakeup_host(struct gether *port)
 	struct usb_function *func = &port->func;
 	struct usb_gadget *gadget = func->config->cdev->gadget;
 
-	if (gadget->speed < USB_SPEED_SUPER)
+	if (gadget->speed >= USB_SPEED_SUPER) {
+		if (!port->func_wakeup_allowed) {
+			DBG(port->ioport, "Function wakeup not allowed\n");
+			return -EOPNOTSUPP;
+		}
+		ret = usb_func_wakeup(func);
+		if (ret)
+			port->is_wakeup_pending = true;
+	} else {
 		ret = usb_gadget_wakeup(gadget);
+	}
 
 	return ret;
 }
@@ -1081,7 +1090,7 @@ int gether_set_ifname(struct net_device *net, const char *name, int len)
 }
 EXPORT_SYMBOL_GPL(gether_set_ifname);
 
-void gether_suspend(struct gether *link)
+void gether_suspend(struct gether *link, bool wakeup_allowed)
 {
 	struct eth_dev *dev = link->ioport;
 	unsigned long flags;
@@ -1099,13 +1108,15 @@ void gether_suspend(struct gether *link)
 	}
 	spin_lock_irqsave(&dev->lock, flags);
 	link->is_suspend = true;
+	link->func_wakeup_allowed = wakeup_allowed;
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
 EXPORT_SYMBOL_GPL(gether_suspend);
 
-void gether_resume(struct gether *link)
+void gether_resume(struct gether *link, bool func_suspend)
 {
 	struct eth_dev *dev = link->ioport;
+	struct usb_function *func = &link->func;
 	unsigned long flags;
 
 	if (!dev)
@@ -1113,6 +1124,19 @@ void gether_resume(struct gether *link)
 
 	spin_lock_irqsave(&dev->lock, flags);
 
+	/*
+	 * If the function is in USB3 Function Suspend state, resume is
+	 * canceled. In this case resume is done by a Function Resume request.
+	 */
+	if (func_suspend) {
+		if (link->is_wakeup_pending) {
+			usb_func_wakeup(func);
+			link->is_wakeup_pending = false;
+		}
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return;
+	}
+
 	if (netif_queue_stopped(dev->net))
 		netif_start_queue(dev->net);
 
@@ -1284,6 +1308,8 @@ void gether_disconnect(struct gether *link)
 	spin_lock(&dev->lock);
 	dev->port_usb = NULL;
 	link->is_suspend = false;
+	link->is_wakeup_pending = false;
+	link->func_wakeup_allowed = false;
 	spin_unlock(&dev->lock);
 }
 EXPORT_SYMBOL_GPL(gether_disconnect);
diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 851ee10..4a6aa646 100644
--- a/drivers/usb/gadget/function/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -80,6 +80,8 @@ struct gether {
 	void				(*open)(struct gether *);
 	void				(*close)(struct gether *);
 	bool				is_suspend;
+	bool				is_wakeup_pending;
+	bool				func_wakeup_allowed;
 };
 
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
@@ -259,8 +261,8 @@ int gether_set_ifname(struct net_device *net, const char *name, int len);
 
 void gether_cleanup(struct eth_dev *dev);
 
-void gether_suspend(struct gether *link);
-void gether_resume(struct gether *link);
+void gether_suspend(struct gether *link, bool wakeup_allowed);
+void gether_resume(struct gether *link, bool func_suspend);
 
 /* connect/disconnect is handled by individual functions */
 struct net_device *gether_connect(struct gether *);
