return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
 }
 
+/*
+ * find slot id based on port number.
+ */
+static int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
+{
+       int slot_id;
+       int i;
+
+       slot_id = 0;
+       for (i = 0; i < MAX_HC_SLOTS; i++) {
+               if (!xhci->devs[i])
+                       continue;
+               if (xhci->devs[i]->port == port) {
+                       slot_id = i;
+                       break;
+               }
+       }
+
+       return slot_id;
+}
+
+/*
+ * Stop device
+ * It issues stop endpoint command for EP 0 to 30. And wait the last command
+ * to complete.
+ * suspend will set to 1, if suspend bit need to set in command.
+ */
+static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
+{
+       struct xhci_virt_device *virt_dev;
+       struct xhci_command *cmd;
+       unsigned long flags;
+       int timeleft;
+       int ret;
+       int i;
+
+       ret = 0;
+       virt_dev = xhci->devs[slot_id];
+       cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+       if (!cmd) {
+               xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&xhci->lock, flags);
+       for (i = LAST_EP_INDEX; i > 0; i--) {
+               if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
+                       xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
+       }
+       cmd->command_trb = xhci->cmd_ring->enqueue;
+       list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
+       xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
+       xhci_ring_cmd_db(xhci);
+       spin_unlock_irqrestore(&xhci->lock, flags);
+
+       /* Wait for last stop endpoint command to finish */
+       timeleft = wait_for_completion_interruptible_timeout(
+                       cmd->completion,
+                       USB_CTRL_SET_TIMEOUT);
+       if (timeleft <= 0) {
+               xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
+                               timeleft == 0 ? "Timeout" : "Signal");
+               spin_lock_irqsave(&xhci->lock, flags);
+               /* The timeout might have raced with the event ring handler, so
+                * only delete from the list if the item isn't poisoned.
+                */
+               if (cmd->cmd_list.next != LIST_POISON1)
+                       list_del(&cmd->cmd_list);
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               ret = -ETIME;
+               goto command_cleanup;
+       }
+
+command_cleanup:
+       xhci_free_command(xhci, cmd);
+       return ret;
+}
+
+/*
+ * Ring device, it rings the all doorbells unconditionally.
+ */
+static void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
+{
+       int i;
+
+       for (i = 0; i < LAST_EP_INDEX + 1; i++)
+               if (xhci->devs[slot_id]->eps[i].ring &&
+                   xhci->devs[slot_id]->eps[i].ring->dequeue)
+                       xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
+
+       return;
+}
+
 static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
                u32 __iomem *addr, u32 port_status)
 {
                status = PORT_PEC;
                port_change_bit = "enable/disable";
                break;
+       case USB_PORT_FEAT_C_SUSPEND:
+               status = PORT_PLC;
+               port_change_bit = "suspend/resume";
+               break;
        default:
                /* Should never happen */
                return;
        u32 temp, status;
        int retval = 0;
        u32 __iomem *addr;
+       int slot_id;
 
        ports = HCS_MAX_PORTS(xhci->hcs_params1);
 
                if ((temp & PORT_OCC))
                        status |= USB_PORT_STAT_C_OVERCURRENT << 16;
                /*
-                * FIXME ignoring suspend, reset, and USB 2.1/3.0 specific
+                * FIXME ignoring reset and USB 2.1/3.0 specific
                 * changes
                 */
+               if ((temp & PORT_PLS_MASK) == XDEV_U3
+                       && (temp & PORT_POWER))
+                       status |= 1 << USB_PORT_FEAT_SUSPEND;
+               if ((temp & PORT_PLS_MASK) == XDEV_U0
+                       && (temp & PORT_POWER)
+                       && (xhci->suspended_ports[wIndex >> 5] &
+                           (1 << (wIndex & 31)))) {
+                       xhci->suspended_ports[wIndex >> 5] &=
+                                       ~(1 << (wIndex & 31));
+                       xhci->port_c_suspend[wIndex >> 5] |=
+                                       1 << (wIndex & 31);
+               }
                if (temp & PORT_CONNECT) {
                        status |= USB_PORT_STAT_CONNECTION;
                        status |= xhci_port_speed(temp);
                        status |= USB_PORT_STAT_RESET;
                if (temp & PORT_POWER)
                        status |= USB_PORT_STAT_POWER;
+               if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+                       status |= 1 << USB_PORT_FEAT_C_SUSPEND;
                xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
                put_unaligned(cpu_to_le32(status), (__le32 *) buf);
                break;
                temp = xhci_readl(xhci, addr);
                temp = xhci_port_state_to_neutral(temp);
                switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       temp = xhci_readl(xhci, addr);
+                       /* In spec software should not attempt to suspend
+                        * a port unless the port reports that it is in the
+                        * enabled (PED = ‘1’,PLS < ‘3’) state.
+                        */
+                       if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
+                               || (temp & PORT_PLS_MASK) >= XDEV_U3) {
+                               xhci_warn(xhci, "USB core suspending device "
+                                         "not in U0/U1/U2.\n");
+                               goto error;
+                       }
+
+                       slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+                       if (!slot_id) {
+                               xhci_warn(xhci, "slot_id is zero\n");
+                               goto error;
+                       }
+                       /* unlock to execute stop endpoint commands */
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       xhci_stop_device(xhci, slot_id, 1);
+                       spin_lock_irqsave(&xhci->lock, flags);
+
+                       temp = xhci_port_state_to_neutral(temp);
+                       temp &= ~PORT_PLS_MASK;
+                       temp |= PORT_LINK_STROBE | XDEV_U3;
+                       xhci_writel(xhci, temp, addr);
+
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       msleep(10); /* wait device to enter */
+                       spin_lock_irqsave(&xhci->lock, flags);
+
+                       temp = xhci_readl(xhci, addr);
+                       xhci->suspended_ports[wIndex >> 5] |=
+                                       1 << (wIndex & (31));
+                       break;
                case USB_PORT_FEAT_POWER:
                        /*
                         * Turn on ports, even if there isn't per-port switching.
                temp = xhci_readl(xhci, addr);
                temp = xhci_port_state_to_neutral(temp);
                switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       temp = xhci_readl(xhci, addr);
+                       xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
+                       xhci_dbg(xhci, "PORTSC %04x\n", temp);
+                       if (temp & PORT_RESET)
+                               goto error;
+                       if (temp & XDEV_U3) {
+                               if ((temp & PORT_PE) == 0)
+                                       goto error;
+                               if (DEV_SUPERSPEED(temp)) {
+                                       temp = xhci_port_state_to_neutral(temp);
+                                       temp &= ~PORT_PLS_MASK;
+                                       temp |= PORT_LINK_STROBE | XDEV_U0;
+                                       xhci_writel(xhci, temp, addr);
+                                       xhci_readl(xhci, addr);
+                               } else {
+                                       temp = xhci_port_state_to_neutral(temp);
+                                       temp &= ~PORT_PLS_MASK;
+                                       temp |= PORT_LINK_STROBE | XDEV_RESUME;
+                                       xhci_writel(xhci, temp, addr);
+
+                                       spin_unlock_irqrestore(&xhci->lock,
+                                                              flags);
+                                       msleep(20);
+                                       spin_lock_irqsave(&xhci->lock, flags);
+
+                                       temp = xhci_readl(xhci, addr);
+                                       temp = xhci_port_state_to_neutral(temp);
+                                       temp &= ~PORT_PLS_MASK;
+                                       temp |= PORT_LINK_STROBE | XDEV_U0;
+                                       xhci_writel(xhci, temp, addr);
+                               }
+                               xhci->port_c_suspend[wIndex >> 5] |=
+                                               1 << (wIndex & 31);
+                       }
+
+                       slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+                       if (!slot_id) {
+                               xhci_dbg(xhci, "slot_id is zero\n");
+                               goto error;
+                       }
+                       xhci_ring_device(xhci, slot_id);
+                       break;
+               case USB_PORT_FEAT_C_SUSPEND:
+                       xhci->port_c_suspend[wIndex >> 5] &=
+                                       ~(1 << (wIndex & 31));
                case USB_PORT_FEAT_C_RESET:
                case USB_PORT_FEAT_C_CONNECTION:
                case USB_PORT_FEAT_C_OVER_CURRENT:
 
 #include <linux/slab.h>
 #include "xhci.h"
 
+static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
+               struct xhci_virt_device *virt_dev,
+               struct xhci_event_cmd *event);
+
 /*
  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
  * address of the TRB.
        xhci_readl(xhci, &xhci->dba->doorbell[0]);
 }
 
-static void ring_ep_doorbell(struct xhci_hcd *xhci,
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
                unsigned int slot_id,
                unsigned int ep_index,
                unsigned int stream_id)
        /* A ring has pending URBs if its TD list is not empty */
        if (!(ep->ep_state & EP_HAS_STREAMS)) {
                if (!(list_empty(&ep->ring->td_list)))
-                       ring_ep_doorbell(xhci, slot_id, ep_index, 0);
+                       xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0);
                return;
        }
 
                        stream_id++) {
                struct xhci_stream_info *stream_info = ep->stream_info;
                if (!list_empty(&stream_info->stream_rings[stream_id]->td_list))
-                       ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+                       xhci_ring_ep_doorbell(xhci, slot_id, ep_index,
+                                               stream_id);
        }
 }
 
  *     bit cleared) so that the HW will skip over them.
  */
 static void handle_stopped_endpoint(struct xhci_hcd *xhci,
-               union xhci_trb *trb)
+               union xhci_trb *trb, struct xhci_event_cmd *event)
 {
        unsigned int slot_id;
        unsigned int ep_index;
+       struct xhci_virt_device *virt_dev;
        struct xhci_ring *ep_ring;
        struct xhci_virt_ep *ep;
        struct list_head *entry;
 
        struct xhci_dequeue_state deq_state;
 
+       if (unlikely(TRB_TO_SUSPEND_PORT(
+                       xhci->cmd_ring->dequeue->generic.field[3]))) {
+               slot_id = TRB_TO_SLOT_ID(
+                       xhci->cmd_ring->dequeue->generic.field[3]);
+               virt_dev = xhci->devs[slot_id];
+               if (virt_dev)
+                       handle_cmd_in_cmd_wait_list(xhci, virt_dev,
+                               event);
+               else
+                       xhci_warn(xhci, "Stop endpoint command "
+                               "completion for disabled slot %u\n",
+                               slot_id);
+               return;
+       }
+
        memset(&deq_state, 0, sizeof(deq_state));
        slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
        ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
                complete(&xhci->addr_dev);
                break;
        case TRB_TYPE(TRB_STOP_RING):
-               handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue);
+               handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event);
                break;
        case TRB_TYPE(TRB_SET_DEQ):
                handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
         */
        wmb();
        start_trb->field[3] |= start_cycle;
-       ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+       xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
 }
 
 /*
        wmb();
        start_trb->field[3] |= start_cycle;
 
-       ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
+       xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
        return 0;
 }
 
                        false);
 }
 
+/*
+ * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop
+ * activity on an endpoint that is about to be suspended.
+ */
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-               unsigned int ep_index)
+               unsigned int ep_index, int suspend)
 {
        u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
        u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
        u32 type = TRB_TYPE(TRB_STOP_RING);
+       u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend);
 
        return queue_command(xhci, 0, 0, 0,
-                       trb_slot_id | trb_ep_index | type, false);
+                       trb_slot_id | trb_ep_index | type | trb_suspend, false);
 }
 
 /* Set Transfer Ring Dequeue Pointer command.
 
  * A read gives the current link PM state of the port,
  * a write with Link State Write Strobe set sets the link state.
  */
+#define PORT_PLS_MASK  (0xf << 5)
+#define XDEV_U0                (0x0 << 5)
+#define XDEV_U3                (0x3 << 5)
+#define XDEV_RESUME    (0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER     (1 << 9)
 /* bits 10:13 indicate device speed:
 #define MAX_EXIT       (0xffff)
 /* Root hub port number that is needed to access the USB device */
 #define ROOT_HUB_PORT(p)       (((p) & 0xff) << 16)
+#define DEVINFO_TO_ROOT_HUB_PORT(p)    (((p) >> 16) & 0xff)
 /* Maximum number of ports under a hub device */
 #define XHCI_MAX_PORTS(p)      (((p) & 0xff) << 24)
 
        /* Status of the last command issued for this device */
        u32                             cmd_status;
        struct list_head                cmd_list;
+       u8                              port;
 };
 
 
 #define TRB_TO_EP_INDEX(p)             ((((p) & (0x1f << 16)) >> 16) - 1)
 #define        EP_ID_FOR_TRB(p)                ((((p) + 1) & 0x1f) << 16)
 
+#define SUSPEND_PORT_FOR_TRB(p)                (((p) & 1) << 23)
+#define TRB_TO_SUSPEND_PORT(p)         (((p) & (1 << 23)) >> 23)
+#define LAST_EP_INDEX                  30
+
 /* Set TR Dequeue Pointer command TRB fields */
 #define TRB_TO_STREAM_ID(p)            ((((p) & (0xffff << 16)) >> 16))
 #define STREAM_ID_FOR_TRB(p)           ((((p)) & 0xffff) << 16)
 #define        XHCI_LINK_TRB_QUIRK     (1 << 0)
 #define XHCI_RESET_EP_QUIRK    (1 << 1)
 #define XHCI_NEC_HOST          (1 << 2)
+       u32                     port_c_suspend[8];      /* port suspend change*/
+       u32                     suspended_ports[8];     /* which ports are
+                                                          suspended */
 };
 
 /* For testing purposes */
 int xhci_queue_vendor_command(struct xhci_hcd *xhci,
                u32 field1, u32 field2, u32 field3, u32 field4);
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-               unsigned int ep_index);
+               unsigned int ep_index, int suspend);
 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
                int slot_id, unsigned int ep_index);
 int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
                unsigned int slot_id, unsigned int ep_index,
                struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
+               unsigned int ep_index, unsigned int stream_id);
 
 /* xHCI roothub code */
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,