aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/shost/shost_readyq.c
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/usb/host/shost/shost_readyq.c
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'drivers/usb/host/shost/shost_readyq.c')
-rw-r--r--drivers/usb/host/shost/shost_readyq.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/drivers/usb/host/shost/shost_readyq.c b/drivers/usb/host/shost/shost_readyq.c
new file mode 100644
index 0000000..9e41da5
--- /dev/null
+++ b/drivers/usb/host/shost/shost_readyq.c
@@ -0,0 +1,240 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : TransferReadyQ.c
+ * [Description] : The source file implements the internal
+ * functions of TransferReadyQ.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/04
+ * [Revision History]
+ * (1) 2008/06/04 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of TransferReadyQ.
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+static struct trans_ready_q periodic_trans_ready_q;
+static struct trans_ready_q nonperiodic_trans_ready_q;
+
+/******************************************************************************/
+/*!
+ * @name void init_transfer_ready_q(void)
+ *
+ * @brief this function initiates PeriodicTransferReadyQ
+ * and NonPeriodicTransferReadyQ.
+ *
+ *
+ * @param void
+ *
+ * @return void.
+ */
+/******************************************************************************/
+static void init_transfer_ready_q(void)
+{
+ otg_dbg(OTG_DBG_SCHEDULE, "start init_transfer_ready_q\n");
+
+ otg_list_init(&periodic_trans_ready_q.entity_list);
+ periodic_trans_ready_q.is_periodic = true;
+ periodic_trans_ready_q.entity_num = 0;
+ periodic_trans_ready_q.total_alloc_chnum = 0;
+ periodic_trans_ready_q.total_perio_bus_bandwidth = 0;
+
+ otg_list_init(&nonperiodic_trans_ready_q.entity_list);
+ nonperiodic_trans_ready_q.is_periodic = false;
+ nonperiodic_trans_ready_q.entity_num = 0;
+ nonperiodic_trans_ready_q.total_alloc_chnum = 0;
+ nonperiodic_trans_ready_q.total_perio_bus_bandwidth = 0;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int insert_ed_to_ready_q(struct ed *insert_ed,
+ * bool is_first)
+ *
+ * @brief this function inserts ed_t * to TransferReadyQ.
+ *
+ *
+ * @param [IN] insert_ed
+ * = indicates the ed_t to be inserted to TransferReadyQ.
+ * [IN] is_first
+ * = indicates whether the insert_ed is inserted
+ * as first entry of TransferReadyQ.
+ *
+ * @return
+ * USB_ERR_SUCCESS -if successes to insert the insert_ed to TransferReadyQ.
+ * USB_ERR_FAILl -if fails to insert the insert_ed to TransferReadyQ.
+ */
+/******************************************************************************/
+static int insert_ed_to_ready_q(struct ed *insert_ed, bool is_first)
+{
+ otg_dbg(OTG_DBG_SCHEDULE_ED, "ed_id %d, td_id %d, %d\n",
+ insert_ed->ed_id, insert_ed->num_td, is_first);
+
+ if (insert_ed->ed_desc.endpoint_type == BULK_TRANSFER ||
+ insert_ed->ed_desc.endpoint_type == CONTROL_TRANSFER) {
+
+ if (is_first) {
+ otg_list_push_next(&insert_ed->readyq_list,
+ &nonperiodic_trans_ready_q.entity_list);
+ } else {
+ otg_list_push_prev(&insert_ed->readyq_list,
+ &nonperiodic_trans_ready_q.entity_list);
+ }
+ nonperiodic_trans_ready_q.entity_num++;
+
+ } else {
+ if (is_first) {
+ otg_list_push_next(&insert_ed->readyq_list,
+ &periodic_trans_ready_q.entity_list);
+ } else {
+ otg_list_push_prev(&insert_ed->readyq_list,
+ &periodic_trans_ready_q.entity_list);
+ }
+ periodic_trans_ready_q.entity_num++;
+ }
+ return USB_ERR_SUCCESS;
+}
+
+
+static u32 get_periodic_ready_q_entity_num(void)
+{
+ return periodic_trans_ready_q.entity_num;
+}
+
+/******************************************************************************/
+/*!
+ * @name int remove_ed_from_ready_q(ed_t *remove_ed)
+ *
+ * @brief this function removes ed_t * from TransferReadyQ.
+ *
+ *
+ * @param [IN] remove_ed
+ * = indicate the ed_t to be removed from TransferReadyQ.
+ *
+ * @return
+ * USB_ERR_SUCCESS -if successes to remove the remove_ed from TransferReadyQ.
+ * USB_ERR_FAILl -if fails to remove the remove_ed from TransferReadyQ.
+ */
+/******************************************************************************/
+static int remove_ed_from_ready_q(struct ed *remove_ed)
+{
+ otg_dbg(OTG_DBG_SCHEDULE_ED, "ed_id %d, td_id %d\n",
+ remove_ed->ed_id, remove_ed->num_td);
+
+ otg_list_pop(&remove_ed->readyq_list);
+
+ if (remove_ed->ed_desc.endpoint_type == BULK_TRANSFER ||
+ remove_ed->ed_desc.endpoint_type == CONTROL_TRANSFER) {
+
+ nonperiodic_trans_ready_q.entity_num--;
+
+ } else
+ periodic_trans_ready_q.entity_num--;
+
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name int get_ed_from_ready_q(bool is_periodic,
+ * struct td **get_ed)
+ *
+ * @brief this function returns the first entity of TransferReadyQ.
+ * if there are some ed_t on TransferReadyQ,
+ * this function pops first ed_t from TransferReadyQ.
+ * So, the TransferReadyQ don's has the poped ed_t.
+ *
+ * @param [IN] is_periodic
+ * = indicate whether Periodic or not
+ * [OUT] get_ed
+ * = indicate the double pointer to store the address of first entity
+ * on TransferReadyQ.
+ *
+ * @return
+ * USB_ERR_SUCCESS -if successes to get frist ed_t from TransferReadyQ.
+ * USB_ERR_NO_ENTITY -if fails to get frist ed_t from TransferReadyQ
+ * because there is no entity on TransferReadyQ.
+ */
+/******************************************************************************/
+
+static int get_ed_from_ready_q(struct ed **get_ed, bool is_periodic)
+{
+ otg_list_head *qlist = NULL;
+
+ /* periodic transfer : control and bulk */
+ if (is_periodic) {
+
+ if (periodic_trans_ready_q.entity_num == 0)
+ return USB_ERR_NO_ENTITY;
+
+ qlist = periodic_trans_ready_q.entity_list.next;
+
+ if (!otg_list_empty(&periodic_trans_ready_q.entity_list)) {
+
+ *get_ed = otg_list_get_node(qlist,
+ struct ed, readyq_list);
+
+ if (qlist->prev == LIST_POISON2 ||
+ qlist->next == LIST_POISON1) {
+
+ printk(KERN_ERR "shost scheduler: get_ed_from_ready_q error\n");
+ periodic_trans_ready_q.entity_num = 0;
+
+ } else {
+ otg_list_pop(qlist);
+ periodic_trans_ready_q.entity_num--;
+ }
+ return USB_ERR_SUCCESS;
+
+ } else
+ return USB_ERR_NO_ENTITY;
+
+ /* non-periodic transfer : interrupt and ischo */
+ } else {
+
+ if (nonperiodic_trans_ready_q.entity_num == 0)
+ return USB_ERR_NO_ENTITY;
+
+ qlist = nonperiodic_trans_ready_q.entity_list.next;
+
+ if (!otg_list_empty(&nonperiodic_trans_ready_q.entity_list)) {
+
+ *get_ed = otg_list_get_node(qlist,
+ struct ed, readyq_list);
+
+ if (qlist->prev == LIST_POISON2 ||
+ qlist->next == LIST_POISON1) {
+
+ printk(KERN_ERR "s3c-otg-scheduler get_ed_from_ready_q error\n");
+ nonperiodic_trans_ready_q.entity_num = 0;
+
+ } else {
+ otg_list_pop(qlist);
+ nonperiodic_trans_ready_q.entity_num--;
+ }
+ return USB_ERR_SUCCESS;
+ } else
+ return USB_ERR_NO_ENTITY;
+ }
+}
+
+