diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/usb/host/shost/shost_readyq.c | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_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.c | 240 |
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; + } +} + + |