H A D | c67x00-sched.c | 2 * c67x00-sched.c: Cypress C67X00 USB Host Controller Driver - TD scheduling 27 #include "c67x00.h" 28 #include "c67x00-hcd.h" 150 static void dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg) dbg_td() argument 152 struct device *dev = c67x00_hcd_dev(c67x00); dbg_td() 173 static inline u16 c67x00_get_current_frame_number(struct c67x00_hcd *c67x00) c67x00_get_current_frame_number() argument 175 return c67x00_ll_husb_get_frame(c67x00->sie) & HOST_FRAME_MASK; c67x00_get_current_frame_number() 212 static void c67x00_release_urb(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_release_urb() argument 219 c67x00->urb_count--; c67x00_release_urb() 222 c67x00->urb_iso_count--; c67x00_release_urb() 223 if (c67x00->urb_iso_count == 0) c67x00_release_urb() 224 c67x00->max_frame_bw = MAX_FRAME_BW_STD; c67x00_release_urb() 232 list_for_each_entry(td, &c67x00->td_list, td_list) c67x00_release_urb() 245 c67x00_ep_data_alloc(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_ep_data_alloc() argument 251 c67x00->current_frame = c67x00_get_current_frame_number(c67x00); c67x00_ep_data_alloc() 256 if (frame_after(c67x00->current_frame, ep_data->next_frame)) c67x00_ep_data_alloc() 258 frame_add(c67x00->current_frame, 1); c67x00_ep_data_alloc() 262 /* Allocate and initialize a new c67x00 endpoint data structure */ c67x00_ep_data_alloc() 277 ep_data->next_frame = frame_add(c67x00->current_frame, 1); c67x00_ep_data_alloc() 283 list_add(&ep_data->node, &c67x00->list[type]); c67x00_ep_data_alloc() 287 list_for_each_entry(prev, &c67x00->list[type], node) { c67x00_ep_data_alloc() 321 struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd); c67x00_endpoint_disable() local 325 dev_warn(c67x00_hcd_dev(c67x00), "error: urb list not empty\n"); c67x00_endpoint_disable() 327 spin_lock_irqsave(&c67x00->lock, flags); c67x00_endpoint_disable() 332 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_endpoint_disable() 337 reinit_completion(&c67x00->endpoint_disable); c67x00_endpoint_disable() 338 c67x00_sched_kick(c67x00); c67x00_endpoint_disable() 339 wait_for_completion_timeout(&c67x00->endpoint_disable, 1 * HZ); c67x00_endpoint_disable() 341 spin_lock_irqsave(&c67x00->lock, flags); c67x00_endpoint_disable() 344 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_endpoint_disable() 362 struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd); c67x00_urb_enqueue() local 372 spin_lock_irqsave(&c67x00->lock, flags); c67x00_urb_enqueue() 388 urbp->ep_data = c67x00_ep_data_alloc(c67x00, urb); c67x00_urb_enqueue() 411 if (c67x00->urb_iso_count == 0) c67x00_urb_enqueue() 412 c67x00->max_frame_bw = MAX_FRAME_BW_ISO; c67x00_urb_enqueue() 413 c67x00->urb_iso_count++; c67x00_urb_enqueue() 437 if (!c67x00->urb_count++) c67x00_urb_enqueue() 438 c67x00_ll_hpi_enable_sofeop(c67x00->sie); c67x00_urb_enqueue() 440 c67x00_sched_kick(c67x00); c67x00_urb_enqueue() 441 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_urb_enqueue() 448 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_urb_enqueue() 457 struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd); c67x00_urb_dequeue() local 461 spin_lock_irqsave(&c67x00->lock, flags); c67x00_urb_dequeue() 466 c67x00_release_urb(c67x00, urb); c67x00_urb_dequeue() 469 spin_unlock(&c67x00->lock); c67x00_urb_dequeue() 471 spin_lock(&c67x00->lock); c67x00_urb_dequeue() 473 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_urb_dequeue() 478 spin_unlock_irqrestore(&c67x00->lock, flags); c67x00_urb_dequeue() 485 * pre: c67x00 locked, urb unlocked 488 c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status) c67x00_giveback_urb() argument 500 c67x00_release_urb(c67x00, urb); c67x00_giveback_urb() 501 usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb); c67x00_giveback_urb() 502 spin_unlock(&c67x00->lock); c67x00_giveback_urb() 503 usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, urbp->status); c67x00_giveback_urb() 504 spin_lock(&c67x00->lock); c67x00_giveback_urb() 509 static int c67x00_claim_frame_bw(struct c67x00_hcd *c67x00, struct urb *urb, c67x00_claim_frame_bw() argument 549 if (unlikely(bit_time + c67x00->bandwidth_allocated >= c67x00_claim_frame_bw() 550 c67x00->max_frame_bw)) c67x00_claim_frame_bw() 553 if (unlikely(c67x00->next_td_addr + CY_TD_SIZE >= c67x00_claim_frame_bw() 554 c67x00->td_base_addr + SIE_TD_SIZE)) c67x00_claim_frame_bw() 557 if (unlikely(c67x00->next_buf_addr + len >= c67x00_claim_frame_bw() 558 c67x00->buf_base_addr + SIE_TD_BUF_SIZE)) c67x00_claim_frame_bw() 562 if (unlikely(bit_time + c67x00->periodic_bw_allocated >= c67x00_claim_frame_bw() 563 MAX_PERIODIC_BW(c67x00->max_frame_bw))) c67x00_claim_frame_bw() 565 c67x00->periodic_bw_allocated += bit_time; c67x00_claim_frame_bw() 568 c67x00->bandwidth_allocated += bit_time; c67x00_claim_frame_bw() 577 static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb, c67x00_create_td() argument 587 if (c67x00_claim_frame_bw(c67x00, urb, len, usb_pipeisoc(urb->pipe) c67x00_create_td() 599 !(c67x00->low_speed_ports & (1 << urbp->port))) c67x00_create_td() 624 td->td_addr = c67x00->next_td_addr; c67x00_create_td() 625 c67x00->next_td_addr = c67x00->next_td_addr + CY_TD_SIZE; c67x00_create_td() 628 td->ly_base_addr = __cpu_to_le16(c67x00->next_buf_addr); c67x00_create_td() 629 td->port_length = __cpu_to_le16((c67x00->sie->sie_num << 15) | c67x00_create_td() 638 td->next_td_addr = __cpu_to_le16(c67x00->next_td_addr); c67x00_create_td() 645 c67x00->next_buf_addr += (len + 1) & ~0x01; /* properly align */ c67x00_create_td() 647 list_add_tail(&td->td_list, &c67x00->td_list); c67x00_create_td() 659 static int c67x00_add_data_urb(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_add_data_urb() argument 688 ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, toggle, c67x00_add_data_urb() 705 static int c67x00_add_ctrl_urb(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_add_ctrl_urb() argument 713 ret = c67x00_create_td(c67x00, urb, urb->setup_packet, c67x00_add_ctrl_urb() 723 ret = c67x00_add_data_urb(c67x00, urb); c67x00_add_ctrl_urb() 730 ret = c67x00_create_td(c67x00, urb, NULL, 0, pid, 1, c67x00_add_ctrl_urb() 743 static int c67x00_add_int_urb(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_add_int_urb() argument 747 if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) { c67x00_add_int_urb() 750 return c67x00_add_data_urb(c67x00, urb); c67x00_add_int_urb() 755 static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb) c67x00_add_iso_urb() argument 759 if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) { c67x00_add_iso_urb() 770 ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, 0, c67x00_add_iso_urb() 773 dev_dbg(c67x00_hcd_dev(c67x00), "create failed: %d\n", c67x00_add_iso_urb() 778 c67x00_giveback_urb(c67x00, urb, 0); c67x00_add_iso_urb() 790 static void c67x00_fill_from_list(struct c67x00_hcd *c67x00, int type, c67x00_fill_from_list() argument 797 list_for_each_entry(ep_data, &c67x00->list[type], node) { c67x00_fill_from_list() 804 add(c67x00, urb); c67x00_fill_from_list() 809 static void c67x00_fill_frame(struct c67x00_hcd *c67x00) c67x00_fill_frame() argument 814 if (!list_empty(&c67x00->td_list)) { c67x00_fill_frame() 815 dev_warn(c67x00_hcd_dev(c67x00), c67x00_fill_frame() 817 list_for_each_entry_safe(td, ttd, &c67x00->td_list, td_list) { c67x00_fill_frame() 818 dbg_td(c67x00, td, "Unprocessed td"); c67x00_fill_frame() 824 c67x00->bandwidth_allocated = 0; c67x00_fill_frame() 825 c67x00->periodic_bw_allocated = 0; c67x00_fill_frame() 827 c67x00->next_td_addr = c67x00->td_base_addr; c67x00_fill_frame() 828 c67x00->next_buf_addr = c67x00->buf_base_addr; c67x00_fill_frame() 831 c67x00_fill_from_list(c67x00, PIPE_ISOCHRONOUS, c67x00_add_iso_urb); c67x00_fill_frame() 832 c67x00_fill_from_list(c67x00, PIPE_INTERRUPT, c67x00_add_int_urb); c67x00_fill_frame() 833 c67x00_fill_from_list(c67x00, PIPE_CONTROL, c67x00_add_ctrl_urb); c67x00_fill_frame() 834 c67x00_fill_from_list(c67x00, PIPE_BULK, c67x00_add_data_urb); c67x00_fill_frame() 843 c67x00_parse_td(struct c67x00_hcd *c67x00, struct c67x00_td *td) c67x00_parse_td() argument 845 c67x00_ll_read_mem_le16(c67x00->sie->dev, c67x00_parse_td() 849 c67x00_ll_read_mem_le16(c67x00->sie->dev, td_ly_base_addr(td), c67x00_parse_td() 853 static int c67x00_td_to_error(struct c67x00_hcd *c67x00, struct c67x00_td *td) c67x00_td_to_error() argument 856 dbg_td(c67x00, td, "ERROR_FLAG"); c67x00_td_to_error() 860 /* dbg_td(c67x00, td, "STALL"); */ c67x00_td_to_error() 864 dbg_td(c67x00, td, "TIMEOUT"); c67x00_td_to_error() 902 static inline void c67x00_clear_pipe(struct c67x00_hcd *c67x00, c67x00_clear_pipe() argument 908 while (td->td_list.next != &c67x00->td_list) { c67x00_clear_pipe() 920 static void c67x00_handle_successful_td(struct c67x00_hcd *c67x00, c67x00_handle_successful_td() argument 945 c67x00_clear_pipe(c67x00, td); c67x00_handle_successful_td() 951 c67x00_giveback_urb(c67x00, urb, 0); c67x00_handle_successful_td() 959 c67x00_clear_pipe(c67x00, td); c67x00_handle_successful_td() 960 c67x00_giveback_urb(c67x00, urb, 0); c67x00_handle_successful_td() 966 static void c67x00_handle_isoc(struct c67x00_hcd *c67x00, struct c67x00_td *td) c67x00_handle_isoc() argument 982 urb->iso_frame_desc[cnt].status = c67x00_td_to_error(c67x00, td); c67x00_handle_isoc() 984 c67x00_giveback_urb(c67x00, urb, 0); c67x00_handle_isoc() 990 * c67x00_check_td_list - handle tds which have been processed by the c67x00 993 static inline void c67x00_check_td_list(struct c67x00_hcd *c67x00) c67x00_check_td_list() argument 1000 list_for_each_entry_safe(td, tmp, &c67x00->td_list, td_list) { c67x00_check_td_list() 1002 c67x00_parse_td(c67x00, td); c67x00_check_td_list() 1010 c67x00_handle_isoc(c67x00, td); c67x00_check_td_list() 1018 c67x00_giveback_urb(c67x00, urb, c67x00_check_td_list() 1019 c67x00_td_to_error(c67x00, td)); c67x00_check_td_list() 1033 c67x00_giveback_urb(c67x00, urb, -EOVERFLOW); c67x00_check_td_list() 1039 c67x00_handle_successful_td(c67x00, td); c67x00_check_td_list() 1043 c67x00_clear_pipe(c67x00, td); c67x00_check_td_list() 1056 static inline int c67x00_all_tds_processed(struct c67x00_hcd *c67x00) c67x00_all_tds_processed() argument 1061 return !c67x00_ll_husb_get_current_td(c67x00->sie); c67x00_all_tds_processed() 1067 static void c67x00_send_td(struct c67x00_hcd *c67x00, struct c67x00_td *td) c67x00_send_td() argument 1072 c67x00_ll_write_mem_le16(c67x00->sie->dev, td_ly_base_addr(td), c67x00_send_td() 1075 c67x00_ll_write_mem_le16(c67x00->sie->dev, c67x00_send_td() 1079 static void c67x00_send_frame(struct c67x00_hcd *c67x00) c67x00_send_frame() argument 1083 if (list_empty(&c67x00->td_list)) c67x00_send_frame() 1084 dev_warn(c67x00_hcd_dev(c67x00), c67x00_send_frame() 1088 list_for_each_entry(td, &c67x00->td_list, td_list) { c67x00_send_frame() 1089 if (td->td_list.next == &c67x00->td_list) c67x00_send_frame() 1092 c67x00_send_td(c67x00, td); c67x00_send_frame() 1095 c67x00_ll_husb_set_current_td(c67x00->sie, c67x00->td_base_addr); c67x00_send_frame() 1103 static void c67x00_do_work(struct c67x00_hcd *c67x00) c67x00_do_work() argument 1105 spin_lock(&c67x00->lock); c67x00_do_work() 1107 if (!c67x00_all_tds_processed(c67x00)) c67x00_do_work() 1110 c67x00_check_td_list(c67x00); c67x00_do_work() 1114 complete(&c67x00->endpoint_disable); c67x00_do_work() 1116 if (!list_empty(&c67x00->td_list)) c67x00_do_work() 1119 c67x00->current_frame = c67x00_get_current_frame_number(c67x00); c67x00_do_work() 1120 if (c67x00->current_frame == c67x00->last_frame) c67x00_do_work() 1122 c67x00->last_frame = c67x00->current_frame; c67x00_do_work() 1125 if (!c67x00->urb_count) { c67x00_do_work() 1126 c67x00_ll_hpi_disable_sofeop(c67x00->sie); c67x00_do_work() 1130 c67x00_fill_frame(c67x00); c67x00_do_work() 1131 if (!list_empty(&c67x00->td_list)) c67x00_do_work() 1133 c67x00_send_frame(c67x00); c67x00_do_work() 1136 spin_unlock(&c67x00->lock); c67x00_do_work() 1143 struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00; c67x00_sched_tasklet() local 1144 c67x00_do_work(c67x00); c67x00_sched_tasklet() 1147 void c67x00_sched_kick(struct c67x00_hcd *c67x00) c67x00_sched_kick() argument 1149 tasklet_hi_schedule(&c67x00->tasklet); c67x00_sched_kick() 1152 int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00) c67x00_sched_start_scheduler() argument 1154 tasklet_init(&c67x00->tasklet, c67x00_sched_tasklet, c67x00_sched_start_scheduler() 1155 (unsigned long)c67x00); c67x00_sched_start_scheduler() 1159 void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00) c67x00_sched_stop_scheduler() argument 1161 tasklet_kill(&c67x00->tasklet); c67x00_sched_stop_scheduler()
|