platform: msm_shared: Update G-Link with latest port

Add features related to G-Link QoS.

P4 Changelist: 8336849

Change-Id: Id9d95f9935f3d69e135d8dec32c5e8166ce5dffd
diff --git a/platform/msm_shared/glink/glink_api.c b/platform/msm_shared/glink/glink_api.c
index e693c8b..ab13442 100644
--- a/platform/msm_shared/glink/glink_api.c
+++ b/platform/msm_shared/glink/glink_api.c
@@ -131,6 +131,7 @@
       ASSERT( open_ch_ctx->local_state == GLINK_LOCAL_CH_CLOSED );
 
       glink_os_cs_init( &ch_ctx->tx_cs );
+      glink_os_cs_init(&ch_ctx->qos_cs);
       glink_os_cs_init( &ch_ctx->ch_state_cs );
 
       ch_ctx->rcid        = open_ch_ctx->rcid;
@@ -138,6 +139,11 @@
       ch_ctx->pintents    = open_ch_ctx->pintents;
       ch_ctx->if_ptr      = open_ch_ctx->if_ptr;
 
+      if (ch_ctx->pintents != NULL)
+      {
+        ch_ctx->pintents->ch_ctx = ch_ctx;
+      }
+
       ch_ctx->remote_state = open_ch_ctx->remote_state;
       ch_ctx->local_state  = GLINK_LOCAL_CH_OPENING;
 
@@ -161,7 +167,8 @@
     {
       /* REMOTE OPEN REQUEST */
 
-      if( open_ch_ctx->remote_state == GLINK_REMOTE_CH_SSR_RESET )
+      if( open_ch_ctx->remote_state == GLINK_REMOTE_CH_SSR_RESET ||
+          open_ch_ctx->remote_state == GLINK_REMOTE_CH_CLEANUP)
       {
         /* During SSR previous channel ctx needs to be destroyed 
         * new remote/local open request will create new context */
@@ -209,6 +216,14 @@
 
   ASSERT( open_ch_ctx == NULL );
 
+  /* check if a new channel can be added */
+  if ((uint32)smem_list_count(&if_ptr->glink_core_priv->open_list) >= xport_ctx->max_lcid)
+  {
+    glink_os_cs_release(&xport_ctx->channel_q_cs);
+    glink_os_free(ch_ctx);
+    return GLINK_STATUS_OUT_OF_RESOURCES;
+  }
+  
   /* Channel not in the list - it was not previously opened */
   ch_ctx->if_ptr = if_ptr;
   *allocated_ch_ctx = ch_ctx;
@@ -225,11 +240,33 @@
   }
 
   glink_os_cs_init(&ch_ctx->tx_cs);
+  glink_os_cs_init(&ch_ctx->qos_cs);
   glink_os_cs_init(&ch_ctx->ch_state_cs);
 
-  /* Append the channel to the transport interface's open_list */
-  ch_ctx->lcid = xport_ctx->free_lcid;
+  /* make sure next LCID is not used in currently open channels */
+  open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+
+  while (open_ch_ctx)
+  {
+    if (open_ch_ctx->lcid == xport_ctx->free_lcid)
+    {
   xport_ctx->free_lcid++;
+      
+      if (xport_ctx->free_lcid >= xport_ctx->max_lcid)
+      {
+        xport_ctx->free_lcid = 1;
+      }
+
+      open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+      continue;
+    }
+
+    open_ch_ctx = smem_list_next(open_ch_ctx);
+  }
+
+  ch_ctx->lcid = xport_ctx->free_lcid;
+
+  /* Append the channel to the transport interface's open_list */
   smem_list_append(&if_ptr->glink_core_priv->open_list, ch_ctx);
 
   /* release lock before context switch otherwise it is causing deadlock */
@@ -454,6 +491,7 @@
 {
   glink_channel_ctx_type     *open_ch_ctx, *dummy_open_ch_ctx;
   glink_core_xport_ctx_type  *xport_ctx;
+  glink_remote_state_type     remote_state;
 
   ASSERT(if_ptr != NULL);
 
@@ -489,9 +527,16 @@
 
       case GLINK_LOCAL_CH_CLOSED:
         /* Channel fully closed - local, remote */
+        glink_os_cs_acquire(&open_ch_ctx->ch_state_cs);
         xport_ctx->channel_cleanup(open_ch_ctx);
         smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+        remote_state = open_ch_ctx->remote_state;
+        glink_os_cs_release(&open_ch_ctx->ch_state_cs);
+
+        if (remote_state != GLINK_REMOTE_CH_CLEANUP)
+        {
         glink_os_free(open_ch_ctx);
+        }
         break;
 
       default:
@@ -621,7 +666,6 @@
      if_ptr->tx_cmd_ch_close == NULL            ||
      if_ptr->tx_cmd_ch_remote_open_ack == NULL  ||
      if_ptr->tx_cmd_ch_remote_close_ack == NULL ||
-     if_ptr->tx_cmd_set_sigs  == NULL           ||
      if_ptr->ssr  == NULL)
   {
     GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
@@ -658,6 +702,7 @@
     xport_ctx->xport = cfg->name;
     xport_ctx->remote_ss = cfg->remote_ss;
     xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
+    xport_ctx->max_lcid = cfg->max_cid; /* Max channel ID supported by transport */
     xport_ctx->version_array = cfg->version;
     xport_ctx->version_indx = cfg->version_count - 1;
 
diff --git a/platform/msm_shared/glink/glink_core_if.c b/platform/msm_shared/glink/glink_core_if.c
index 4631e66..3a71422 100644
--- a/platform/msm_shared/glink/glink_core_if.c
+++ b/platform/msm_shared/glink/glink_core_if.c
@@ -112,20 +112,19 @@
   glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_UP);
 }
 
-
 /*===========================================================================
   FUNCTION      glink_clean_channel_ctx
 ===========================================================================*/
 /**
 
-  This is called when channel is fully closed
-  Clean up the context and redeem channel id if possible
+  This is called when channel is fully closed.
+  Clean up the context and redeem channel id if possible.
 
   @param[in]    xport_ctx    transport context
   @param[in]    channel_ctx  channel context
 
 
-  @return        None
+  @return        None.
   @sideeffects   None.
   @dependencies  This function needs to be called in safe context
                  which is critical sections locked - channel_q_cs
@@ -137,7 +136,7 @@
   glink_channel_ctx_type    *channel_ctx
 )
 {
-  xport_ctx->channel_cleanup( channel_ctx );
+  smem_list_delete(&xport_ctx->open_list, channel_ctx);
 
   if( channel_ctx->lcid == ( xport_ctx->free_lcid - 1 ) )
   {
@@ -146,7 +145,7 @@
     xport_ctx->free_lcid--;
   }
 
-  smem_list_delete(&xport_ctx->open_list, channel_ctx);
+  xport_ctx->channel_cleanup(channel_ctx);
 }
 
 /*===========================================================================
@@ -517,7 +516,6 @@
       /* Found channel */
       glink_os_cs_acquire( &open_ch_ctx->ch_state_cs );
 
-
       GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE_ACK, open_ch_ctx->name,
           xport_ctx->xport, xport_ctx->remote_ss, lcid);
 
@@ -590,6 +588,8 @@
   {
     if( open_ch_ctx->rcid == rcid )
     {
+      glink_remote_state_type remote_state;
+
       GLINK_LOG_EVENT( GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
                        xport_ctx->xport, xport_ctx->remote_ss, rcid);
       /* Found channel, transition to appropriate state based on current state
@@ -607,6 +607,8 @@
         glink_clean_channel_ctx( xport_ctx, open_ch_ctx );
       }
 
+      remote_state = open_ch_ctx->remote_state;
+
       glink_os_cs_release(&open_ch_ctx->ch_state_cs);
       glink_os_cs_release(&xport_ctx->channel_q_cs);
 
@@ -615,8 +617,11 @@
 
       if( open_ch_ctx->local_state == GLINK_LOCAL_CH_CLOSED )
       {
+        if (remote_state != GLINK_REMOTE_CH_CLEANUP)
+        {
         glink_os_free(open_ch_ctx);
       }
+      }
       else
       {
         /* Inform the client */
diff --git a/platform/msm_shared/include/glink_core_if.h b/platform/msm_shared/include/glink_core_if.h
index dbd7853..4da917d 100644
--- a/platform/msm_shared/include/glink_core_if.h
+++ b/platform/msm_shared/include/glink_core_if.h
@@ -51,6 +51,14 @@
 /*===========================================================================
                       MACRO DECLARATIONS
 ===========================================================================*/
+/* Limit of the proportion of total QoS requests */
+#define GLINK_QOS_RATE_LIMIT_COEFF (0.7)
+
+/* Number of QoS tokens given at refill */
+#define GLINK_QOS_TOKENS (10) 
+
+/* Number of QoS buckets */
+#define GLINK_QOS_BUCKETS (1)
 
 /*===========================================================================
                       TYPE DECLARATIONS
@@ -88,6 +96,7 @@
   os_event_type event;   /* Event to signal Tx thread */
   os_cs_type tx_q_cs;    /* Lock to protect Tx queue */
   smem_list_type tx_q;   /* Tx channel queue */
+  uint32 qos_rate_sum;   /* Sum of rates of registered QoS requests */
 } glink_tx_xport_ctx_type;
 
 /** G-Link Local channel states */
@@ -117,7 +126,12 @@
   GLINK_REMOTE_CH_OPENED,
 
   /* Glink channel state when SSR is received from remote sub-system */
-  GLINK_REMOTE_CH_SSR_RESET
+  GLINK_REMOTE_CH_SSR_RESET,
+
+  /** G-Link channel is pending cleanup. 
+      This state is used for deferred channel cleanup in case 
+      it sits in Tx scheduler queue */
+  GLINK_REMOTE_CH_CLEANUP,
 
 }glink_remote_state_type;
 
@@ -311,6 +325,9 @@
   /* Transport's capabilities */
   uint32                        xport_capabilities;
 
+  /* Max lcid */
+  uint32                        max_lcid;
+
   /* Free lcid */
   uint32                        free_lcid;
 
diff --git a/platform/msm_shared/include/glink_internal.h b/platform/msm_shared/include/glink_internal.h
index 5d8cc21..d78fe34 100644
--- a/platform/msm_shared/include/glink_internal.h
+++ b/platform/msm_shared/include/glink_internal.h
@@ -95,7 +95,11 @@
   GLINK_EVENT_CH_MIGRATION_IN_PROGRESS,
   GLINK_EVENT_XPORT_INTERNAL,
   GLINK_EVENT_TRACER_PKT_FAILURE,
-  GLINK_EVENT_TXV_INVALID_BUFFER
+  GLINK_EVENT_TXV_INVALID_BUFFER,
+  GLINK_EVENT_CH_QOS_REG,
+  GLINK_EVENT_CH_QOS_CANCEL,
+  GLINK_EVENT_CH_QOS_START,
+  GLINK_EVENT_CH_QOS_STOP,
 }glink_log_event_type;
 
 typedef struct _glink_channel_intents_type {
@@ -103,6 +107,9 @@
   /* Link for a channel in Tx queue */
   struct _glink_channel_intents_type* next;
 
+  /* Pointer to channel context */
+  glink_channel_ctx_type        *ch_ctx;
+
   /* Critical section to protest access to intent queues */
   os_cs_type                    intent_q_cs;
 
@@ -137,6 +144,32 @@
 
 } glink_channel_intents_type;
 
+
+typedef struct _glink_channel_qos_type {
+  /* qos request count */
+  uint32                        qos_req_count;
+
+  /* qos request packet size */
+  size_t                        qos_pkt_size;
+
+  /* qos request latency */
+  uint32                        qos_latency_us;
+
+  /* qos request rate */
+  uint32                        qos_rate;
+
+  /* qos priority */
+  uint32                        qos_tokens;
+
+  /* qos transport context */
+  void                          *qos_transport_ctx;
+
+  /* qos start time for priority balancing */
+  os_timetick_type              qos_start_priority_time;
+
+} glink_channel_qos_type;
+
+
 struct glink_channel_ctx {
   /* Link needed for use with list APIs.  Must be at the head of the struct */
   smem_list_link_type                 link;
@@ -171,6 +204,15 @@
   /* channel intent collection */
   glink_channel_intents_type          *pintents;
 
+  /* Critical section to protest access to QoS context */
+  os_cs_type                          qos_cs;
+
+  /* qos priority */
+  uint32                              qos_priority;
+
+  /* channel QoS context */
+  glink_channel_qos_type              *qosctx;
+  
   /* Interface pointer with with this channel is registered */
   glink_transport_if_type             *if_ptr;
 
@@ -577,4 +619,37 @@
 /*=========================================================================*/
 void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr);
 
+/*===========================================================================
+  FUNCTION      glink_core_qos_get_priority
+===========================================================================*/
+/**
+
+  Calculates pinitial priority for QoS request.
+
+  @param[in]  if_ptr   The Pointer to the interface instance.
+  @param[in]  req_rate The requested rate.
+
+  @return     Priority.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+uint32 glink_core_qos_get_priority(glink_transport_if_type *if_ptr, uint32 req_rate);
+
+/*===========================================================================
+  FUNCTION      glink_core_qos_cancel
+===========================================================================*/
+/**
+
+  Releases QoS resources.
+
+  @param[in]  open_ch_ctx  Pointer to the channel context.
+
+  @return     None.
+
+  @sideeffects  None.
+*/
+/*=========================================================================*/
+void glink_core_qos_cancel(glink_channel_ctx_type *open_ch_ctx);
+
 #endif /* GLINK_INTERNAL_H */
diff --git a/platform/msm_shared/include/glink_os_type.h b/platform/msm_shared/include/glink_os_type.h
index a129372..634a2ef 100644
--- a/platform/msm_shared/include/glink_os_type.h
+++ b/platform/msm_shared/include/glink_os_type.h
@@ -49,7 +49,11 @@
 ===========================================================================*/
 
 #define OS_LOG_INIT( ) glink_os_log_init()
+#define GLINK_OS_SEC_TO_USEC (1000000ULL)
+#define GLINK_OS_SEC_TO_TICK (19200000ULL)
 
+#define GLINK_OS_TICK_TO_USEC(t) ((t)*10ULL/192ULL)
+#define GLINK_OS_USEC_TO_TICK(u) ((u)*192ULL/10ULL)
 /*===========================================================================
                         TYPE DEFINITIONS
 ===========================================================================*/
@@ -88,4 +92,6 @@
   uint32_t irq_out;
 } os_ipc_intr_type;
 
+typedef unsigned long long os_timetick_type;
+
 #endif /* OS_TYPE_H */
diff --git a/platform/msm_shared/include/glink_transport_if.h b/platform/msm_shared/include/glink_transport_if.h
index 14f0982..c0855e7 100644
--- a/platform/msm_shared/include/glink_transport_if.h
+++ b/platform/msm_shared/include/glink_transport_if.h
@@ -83,7 +83,8 @@
   GLINK_XPORT_RPM = 100,
   GLINK_XPORT_SMD = 200,
   GLINK_XPORT_CP_ENGINE = 300,
-  GLINK_MIN_PRIORITY = GLINK_XPORT_CP_ENGINE,
+  GLINK_XPORT_UART = 400,
+  GLINK_MIN_PRIORITY = GLINK_XPORT_UART,
   GLINK_INVALID_PRIORITY
 } glink_xport_priority;
 
@@ -93,7 +94,6 @@
 
   void       *data;      /* Pointer to the data buffer to be transmitted */
   const void *pkt_priv;  /* Per packet private data */
-  uint32     cid;        /* Local channel ID being used to transmit data */
   uint32     iid;        /* Remote intent ID being used to transmit data */
   size_t     size;       /* Size of data buffer */
   size_t     size_remaining; /* Size left to transmit */
@@ -264,6 +264,76 @@
   glink_transport_if_type *if_ptr   /* Pointer to the interface instance */
 );
 
+/** Provides data rate (tokens/sec) achievable by the transport for given 
+    packet size and latency. */
+typedef uint32 (*get_req_rate_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  latency_us, /* latency in us */
+  size_t                  pkt_size    /* Size of the packet */
+);
+
+/** Allocates context structure to use by transport servicing given QoS request. */
+typedef void* (*alloc_req_ctx_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  uint32                  latency_us, /* latency in us */
+  size_t                  pkt_size    /* Size of the packet */
+);
+
+/** Frees context structure used by transport servicing given QoS request. */
+typedef void (*free_req_ctx_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  void                    *qos_ctx    /* Pointer to the transport QoS context */
+);
+
+/** Starts QoS mode. */
+typedef void (*start_req_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  void                    *qos_ctx    /* Pointer to the transport QoS context */
+);
+
+/** Stops QoS mode. */
+typedef void (*stop_req_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  void                    *qos_ctx    /* Pointer to the transport QoS context */
+);
+
+/** Provides ramp up time in microseconds. */
+typedef uint32 (*get_ramp_time_fn)
+(
+  glink_transport_if_type *if_ptr,    /* Pointer to the interface instance */
+  void                    *qos_ctx    /* Pointer to the transport QoS context */
+);
+
+
+/**
+* Data Structure for GLink Core to call into transport QoS API
+*
+* This structure is used by the GLink core to operate transport
+* This set of function pointers to to be filled in by the transport
+* abstraction layer.
+*/
+typedef struct glink_transport_qos_if_s {
+  /** Provides maximum data rate (tokens/sec) associated with transport. */
+  uint32 max_rate;
+  /** Provides data rate achievable by the transport for given request. */
+  get_req_rate_fn  get_req_rate;
+  /** Allocates context structure to use by transport servicing given QoS request. */
+  alloc_req_ctx_fn alloc_req_ctx;
+  /** Frees context structure used by transport servicing given QoS request. */
+  free_req_ctx_fn  free_req_ctx;
+  /** Starts QoS mode. */
+  start_req_fn     start_req;
+  /** Stops QoS mode. */
+  stop_req_fn      stop_req;
+  /** Provides ramp up time in microseconds. */
+  get_ramp_time_fn get_ramp_time;
+
+} glink_transport_qos_if_type;
 
 /**
  * Data Structure for GLink Core to call into transport API
@@ -359,6 +429,9 @@
 
   /* glink transport priority */
   glink_xport_priority                glink_priority;
+
+  /* pointer to glink transport QoS interface */
+  glink_transport_qos_if_type        *qos_functbl;
 };
 
 #endif //GLINK_TRANSPORT_IF_H