54 #endif |
54 #endif |
55 #include "master.h" |
55 #include "master.h" |
56 |
56 |
57 /*****************************************************************************/ |
57 /*****************************************************************************/ |
58 |
58 |
59 /** Set to 1 to enable external datagram injection debugging. |
59 /** Set to 1 to enable fsm datagram injection debugging. |
60 */ |
60 */ |
|
61 #ifdef USE_TRACE_PRINTK |
|
62 #define DEBUG_INJECT 1 |
|
63 #else |
61 #define DEBUG_INJECT 0 |
64 #define DEBUG_INJECT 0 |
|
65 #endif |
62 |
66 |
63 #ifdef EC_HAVE_CYCLES |
67 #ifdef EC_HAVE_CYCLES |
64 |
68 |
65 /** Frame timeout in cycles. |
69 /** Frame timeout in cycles. |
66 */ |
70 */ |
67 static cycles_t timeout_cycles; |
71 static cycles_t timeout_cycles; |
68 |
72 |
69 /** Timeout for external datagram injection [cycles]. |
73 /** Timeout for fsm datagram injection [cycles]. |
70 */ |
74 */ |
71 static cycles_t ext_injection_timeout_cycles; |
75 static cycles_t fsm_injection_timeout_cycles; |
72 |
76 |
73 #else |
77 #else |
74 |
78 |
75 /** Frame timeout in jiffies. |
79 /** Frame timeout in jiffies. |
76 */ |
80 */ |
77 static unsigned long timeout_jiffies; |
81 static unsigned long timeout_jiffies; |
78 |
82 |
79 /** Timeout for external datagram injection [jiffies]. |
83 /** Timeout for fsm datagram injection [jiffies]. |
80 */ |
84 */ |
81 static unsigned long ext_injection_timeout_jiffies; |
85 static unsigned long fsm_injection_timeout_jiffies; |
82 |
86 |
83 #endif |
87 #endif |
84 |
88 |
85 /*****************************************************************************/ |
89 /*****************************************************************************/ |
86 |
90 |
87 void ec_master_clear_slave_configs(ec_master_t *); |
91 void ec_master_clear_slave_configs(ec_master_t *); |
88 void ec_master_clear_domains(ec_master_t *); |
92 void ec_master_clear_domains(ec_master_t *); |
89 static int ec_master_idle_thread(void *); |
93 static int ec_master_idle_thread(void *); |
90 static int ec_master_operation_thread(void *); |
94 static int ec_master_operation_thread(void *); |
91 #ifdef EC_EOE |
95 #ifdef EC_EOE |
92 static int ec_master_eoe_thread(void *); |
96 static int ec_master_eoe_processing(ec_master_t *); |
93 #endif |
97 #endif |
94 void ec_master_find_dc_ref_clock(ec_master_t *); |
98 void ec_master_find_dc_ref_clock(ec_master_t *); |
95 |
99 |
96 /*****************************************************************************/ |
100 /*****************************************************************************/ |
97 |
101 |
128 int ret; |
132 int ret; |
129 |
133 |
130 master->index = index; |
134 master->index = index; |
131 master->reserved = 0; |
135 master->reserved = 0; |
132 |
136 |
133 sema_init(&master->master_sem, 1); |
137 ec_mutex_init(&master->master_mutex); |
134 |
138 |
135 master->main_mac = main_mac; |
139 master->main_mac = main_mac; |
136 master->backup_mac = backup_mac; |
140 master->backup_mac = backup_mac; |
137 |
141 |
138 sema_init(&master->device_sem, 1); |
142 ec_mutex_init(&master->device_mutex); |
139 |
143 |
140 master->phase = EC_ORPHANED; |
144 master->phase = EC_ORPHANED; |
141 master->active = 0; |
145 master->active = 0; |
142 master->config_changed = 0; |
146 master->config_changed = 0; |
143 master->injection_seq_fsm = 0; |
147 master->injection_seq_fsm = 0; |
144 master->injection_seq_rt = 0; |
148 master->injection_seq_rt = 0; |
145 |
149 |
146 master->slaves = NULL; |
150 master->slaves = NULL; |
147 master->slave_count = 0; |
151 master->slave_count = 0; |
148 |
152 |
149 INIT_LIST_HEAD(&master->configs); |
153 INIT_LIST_HEAD(&master->configs); |
150 |
154 |
151 master->app_time = 0ULL; |
155 master->app_time = 0ULL; |
|
156 #ifdef EC_HAVE_CYCLES |
|
157 master->dc_cycles_app_start_time = 0; |
|
158 #endif |
|
159 master->dc_jiffies_app_start_time = 0; |
152 master->app_start_time = 0ULL; |
160 master->app_start_time = 0ULL; |
153 master->has_app_time = 0; |
161 master->has_app_time = 0; |
154 |
162 |
155 master->scan_busy = 0; |
163 master->scan_busy = 0; |
156 master->allow_scan = 1; |
164 master->allow_scan = 1; |
157 sema_init(&master->scan_sem, 1); |
165 ec_mutex_init(&master->scan_mutex); |
158 init_waitqueue_head(&master->scan_queue); |
166 init_waitqueue_head(&master->scan_queue); |
159 |
167 |
160 master->config_busy = 0; |
168 master->config_busy = 0; |
161 master->allow_config = 1; |
169 master->allow_config = 1; |
162 sema_init(&master->config_sem, 1); |
170 ec_mutex_init(&master->config_mutex); |
163 init_waitqueue_head(&master->config_queue); |
171 init_waitqueue_head(&master->config_queue); |
164 |
172 |
165 INIT_LIST_HEAD(&master->datagram_queue); |
173 INIT_LIST_HEAD(&master->datagram_queue); |
166 master->datagram_index = 0; |
174 master->datagram_index = 0; |
167 |
175 |
168 INIT_LIST_HEAD(&master->ext_datagram_queue); |
176 ec_mutex_init(&master->fsm_queue_mutex); |
169 sema_init(&master->ext_queue_sem, 1); |
177 INIT_LIST_HEAD(&master->fsm_datagram_queue); |
170 |
|
171 INIT_LIST_HEAD(&master->external_datagram_queue); |
|
172 |
178 |
173 // send interval in IDLE phase |
179 // send interval in IDLE phase |
174 ec_master_set_send_interval(master, 1000000 / HZ); |
180 ec_master_set_send_interval(master, 1000000 / HZ); |
175 |
181 |
176 INIT_LIST_HEAD(&master->domains); |
182 INIT_LIST_HEAD(&master->domains); |
393 ec_sii_write_request_t, list); |
401 ec_sii_write_request_t, list); |
394 list_del_init(&request->list); // dequeue |
402 list_del_init(&request->list); // dequeue |
395 EC_MASTER_WARN(master, "Discarding SII request, slave %u about" |
403 EC_MASTER_WARN(master, "Discarding SII request, slave %u about" |
396 " to be deleted.\n", request->slave->ring_position); |
404 " to be deleted.\n", request->slave->ring_position); |
397 request->state = EC_INT_REQUEST_FAILURE; |
405 request->state = EC_INT_REQUEST_FAILURE; |
|
406 kref_put(&request->refcount,ec_master_sii_write_request_release); |
398 wake_up(&master->sii_queue); |
407 wake_up(&master->sii_queue); |
399 } |
408 } |
400 |
409 |
401 while (!list_empty(&master->reg_requests)) { |
410 while (!list_empty(&master->reg_requests)) { |
402 ec_reg_request_t *request = |
411 ec_reg_request_t *request = |
403 list_entry(master->reg_requests.next, ec_reg_request_t, list); |
412 list_entry(master->reg_requests.next, ec_reg_request_t, list); |
404 list_del_init(&request->list); // dequeue |
413 list_del_init(&request->list); // dequeue |
405 EC_MASTER_WARN(master, "Discarding register request, slave %u" |
414 EC_MASTER_WARN(master, "Discarding register request, slave %u" |
406 " about to be deleted.\n", request->slave->ring_position); |
415 " about to be deleted.\n", request->slave->ring_position); |
407 request->state = EC_INT_REQUEST_FAILURE; |
416 request->state = EC_INT_REQUEST_FAILURE; |
|
417 kref_put(&request->refcount,ec_master_reg_request_release); |
408 wake_up(&master->reg_queue); |
418 wake_up(&master->reg_queue); |
409 } |
419 } |
410 |
420 |
|
421 // we must lock the io_mutex here because the slave's fsm_datagram will be unqueued |
|
422 ec_mutex_lock(&master->io_mutex); |
411 for (slave = master->slaves; |
423 for (slave = master->slaves; |
412 slave < master->slaves + master->slave_count; |
424 slave < master->slaves + master->slave_count; |
413 slave++) { |
425 slave++) { |
414 ec_slave_clear(slave); |
426 ec_slave_clear(slave); |
415 } |
427 } |
|
428 ec_mutex_unlock(&master->io_mutex); |
416 |
429 |
417 if (master->slaves) { |
430 if (master->slaves) { |
418 kfree(master->slaves); |
431 kfree(master->slaves); |
419 master->slaves = NULL; |
432 master->slaves = NULL; |
420 } |
433 } |
428 */ |
441 */ |
429 void ec_master_clear_domains(ec_master_t *master) |
442 void ec_master_clear_domains(ec_master_t *master) |
430 { |
443 { |
431 ec_domain_t *domain, *next; |
444 ec_domain_t *domain, *next; |
432 |
445 |
|
446 // we must lock the io_mutex here because the domains's datagram will be unqueued |
|
447 ec_mutex_lock(&master->io_mutex); |
433 list_for_each_entry_safe(domain, next, &master->domains, list) { |
448 list_for_each_entry_safe(domain, next, &master->domains, list) { |
434 list_del(&domain->list); |
449 list_del(&domain->list); |
435 ec_domain_clear(domain); |
450 ec_domain_clear(domain); |
436 kfree(domain); |
451 kfree(domain); |
437 } |
452 } |
|
453 ec_mutex_unlock(&master->io_mutex); |
438 } |
454 } |
439 |
455 |
440 /*****************************************************************************/ |
456 /*****************************************************************************/ |
441 |
457 |
442 /** Clear the configuration applied by the application. |
458 /** Clear the configuration applied by the application. |
443 */ |
459 */ |
444 void ec_master_clear_config( |
460 void ec_master_clear_config( |
445 ec_master_t *master /**< EtherCAT master. */ |
461 ec_master_t *master /**< EtherCAT master. */ |
446 ) |
462 ) |
447 { |
463 { |
448 down(&master->master_sem); |
464 ec_mutex_lock(&master->master_mutex); |
449 ec_master_clear_domains(master); |
465 ec_master_clear_domains(master); |
450 ec_master_clear_slave_configs(master); |
466 ec_master_clear_slave_configs(master); |
451 up(&master->master_sem); |
467 ec_mutex_unlock(&master->master_mutex); |
452 } |
|
453 |
|
454 /*****************************************************************************/ |
|
455 |
|
456 /** Internal sending callback. |
|
457 */ |
|
458 void ec_master_internal_send_cb( |
|
459 void *cb_data /**< Callback data. */ |
|
460 ) |
|
461 { |
|
462 ec_master_t *master = (ec_master_t *) cb_data; |
|
463 down(&master->io_sem); |
|
464 ecrt_master_send_ext(master); |
|
465 up(&master->io_sem); |
|
466 } |
|
467 |
|
468 /*****************************************************************************/ |
|
469 |
|
470 /** Internal receiving callback. |
|
471 */ |
|
472 void ec_master_internal_receive_cb( |
|
473 void *cb_data /**< Callback data. */ |
|
474 ) |
|
475 { |
|
476 ec_master_t *master = (ec_master_t *) cb_data; |
|
477 down(&master->io_sem); |
|
478 ecrt_master_receive(master); |
|
479 up(&master->io_sem); |
|
480 } |
468 } |
481 |
469 |
482 /*****************************************************************************/ |
470 /*****************************************************************************/ |
483 |
471 |
484 /** Starts the master thread. |
472 /** Starts the master thread. |
678 master->phase = EC_IDLE; |
663 master->phase = EC_IDLE; |
679 } |
664 } |
680 |
665 |
681 /*****************************************************************************/ |
666 /*****************************************************************************/ |
682 |
667 |
683 /** Injects external datagrams that fit into the datagram queue. |
668 /** Injects fsm datagrams that fit into the datagram queue. |
684 */ |
669 */ |
685 void ec_master_inject_external_datagrams( |
670 void ec_master_inject_fsm_datagrams( |
686 ec_master_t *master /**< EtherCAT master */ |
671 ec_master_t *master /**< EtherCAT master */ |
687 ) |
672 ) |
688 { |
673 { |
689 ec_datagram_t *datagram, *n; |
674 ec_datagram_t *datagram, *next; |
690 size_t queue_size = 0; |
675 size_t queue_size = 0; |
691 |
676 |
|
677 if (master->fsm_queue_lock_cb) |
|
678 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
|
679 if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0) { |
|
680 if (master->fsm_queue_unlock_cb) |
|
681 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
|
682 return; |
|
683 } |
|
684 if (list_empty(&master->fsm_datagram_queue)) { |
|
685 ec_mutex_unlock(&master->fsm_queue_mutex); |
|
686 if (master->fsm_queue_unlock_cb) |
|
687 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
|
688 return; |
|
689 } |
692 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
690 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
693 queue_size += datagram->data_size; |
691 queue_size += datagram->data_size; |
694 } |
692 } |
695 |
693 |
696 list_for_each_entry_safe(datagram, n, &master->external_datagram_queue, |
694 list_for_each_entry_safe(datagram, next, &master->fsm_datagram_queue, |
697 queue) { |
695 fsm_queue) { |
698 queue_size += datagram->data_size; |
696 queue_size += datagram->data_size; |
699 if (queue_size <= master->max_queue_size) { |
697 if (queue_size <= master->max_queue_size) { |
700 list_del_init(&datagram->queue); |
698 list_del_init(&datagram->fsm_queue); |
701 #if DEBUG_INJECT |
699 #if DEBUG_INJECT |
702 EC_MASTER_DBG(master, 0, "Injecting external datagram %08x" |
700 EC_MASTER_DBG(master, 2, "Injecting fsm datagram %p" |
703 " size=%u, queue_size=%u\n", (unsigned int) datagram, |
701 " size=%zu, queue_size=%zu\n", datagram, |
704 datagram->data_size, queue_size); |
702 datagram->data_size, queue_size); |
705 #endif |
703 #endif |
706 #ifdef EC_HAVE_CYCLES |
704 #ifdef EC_HAVE_CYCLES |
707 datagram->cycles_sent = 0; |
705 datagram->cycles_sent = 0; |
708 #endif |
706 #endif |
709 datagram->jiffies_sent = 0; |
707 datagram->jiffies_sent = 0; |
710 ec_master_queue_datagram(master, datagram); |
708 ec_master_queue_datagram(master, datagram); |
711 } |
709 } |
712 else { |
710 else { |
713 if (datagram->data_size > master->max_queue_size) { |
711 if (datagram->data_size > master->max_queue_size) { |
714 list_del_init(&datagram->queue); |
712 list_del_init(&datagram->fsm_queue); |
715 datagram->state = EC_DATAGRAM_ERROR; |
713 datagram->state = EC_DATAGRAM_ERROR; |
716 EC_MASTER_ERR(master, "External datagram %p is too large," |
714 EC_MASTER_ERR(master, "Fsm datagram %p is too large," |
717 " size=%zu, max_queue_size=%zu\n", |
715 " size=%zu, max_queue_size=%zu\n", |
718 datagram, datagram->data_size, |
716 datagram, datagram->data_size, |
719 master->max_queue_size); |
717 master->max_queue_size); |
720 } else { |
718 } else { |
721 #ifdef EC_HAVE_CYCLES |
719 #ifdef EC_HAVE_CYCLES |
722 cycles_t cycles_now = get_cycles(); |
720 cycles_t cycles_now = get_cycles(); |
723 |
721 |
724 if (cycles_now - datagram->cycles_sent |
722 if (cycles_now - datagram->cycles_sent |
725 > ext_injection_timeout_cycles) |
723 > fsm_injection_timeout_cycles) |
726 #else |
724 #else |
727 if (jiffies - datagram->jiffies_sent |
725 if (jiffies - datagram->jiffies_sent |
728 > ext_injection_timeout_jiffies) |
726 > fsm_injection_timeout_jiffies) |
729 #endif |
727 #endif |
730 { |
728 { |
731 unsigned int time_us; |
729 unsigned int time_us; |
732 |
730 |
733 list_del_init(&datagram->queue); |
731 list_del_init(&datagram->fsm_queue); |
734 datagram->state = EC_DATAGRAM_ERROR; |
732 datagram->state = EC_DATAGRAM_ERROR; |
735 #ifdef EC_HAVE_CYCLES |
733 #ifdef EC_HAVE_CYCLES |
736 time_us = (unsigned int) |
734 time_us = (unsigned int) |
737 ((cycles_now - datagram->cycles_sent) * 1000LL) |
735 ((cycles_now - datagram->cycles_sent) * 1000LL) |
738 / cpu_khz; |
736 / cpu_khz; |
739 #else |
737 #else |
740 time_us = (unsigned int) |
738 time_us = (unsigned int) |
741 ((jiffies - datagram->jiffies_sent) * 1000000 / HZ); |
739 ((jiffies - datagram->jiffies_sent) * 1000000 / HZ); |
742 #endif |
740 #endif |
743 EC_MASTER_ERR(master, "Timeout %u us: Injecting" |
741 EC_MASTER_ERR(master, "Timeout %u us: Injecting" |
744 " external datagram %p size=%zu," |
742 " fsm datagram %p size=%zu," |
745 " max_queue_size=%zu\n", time_us, datagram, |
743 " max_queue_size=%zu\n", time_us, datagram, |
746 datagram->data_size, master->max_queue_size); |
744 datagram->data_size, master->max_queue_size); |
747 } |
745 } |
748 #if DEBUG_INJECT |
746 #if DEBUG_INJECT |
749 else { |
747 else { |
750 EC_MASTER_DBG(master, 0, "Deferred injecting" |
748 EC_MASTER_DBG(master, 2, "Deferred injecting" |
751 " of external datagram %p" |
749 " of fsm datagram %p" |
752 " size=%u, queue_size=%u\n", |
750 " size=%zu, queue_size=%zu\n", |
753 datagram, datagram->data_size, queue_size); |
751 datagram, datagram->data_size, queue_size); |
754 } |
752 } |
755 #endif |
753 #endif |
756 } |
754 } |
757 } |
755 } |
758 } |
756 } |
|
757 ec_mutex_unlock(&master->fsm_queue_mutex); |
|
758 if (master->fsm_queue_unlock_cb) |
|
759 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
759 } |
760 } |
760 |
761 |
761 /*****************************************************************************/ |
762 /*****************************************************************************/ |
762 |
763 |
763 /** Sets the expected interval between calls to ecrt_master_send |
764 /** Sets the expected interval between calls to ecrt_master_send |
774 master->max_queue_size -= master->max_queue_size / 10; |
775 master->max_queue_size -= master->max_queue_size / 10; |
775 } |
776 } |
776 |
777 |
777 /*****************************************************************************/ |
778 /*****************************************************************************/ |
778 |
779 |
779 /** Places an external datagram in the sdo datagram queue. |
780 /** Places an request (SDO/FoE/SoE/EoE) fsm datagram in the sdo datagram queue. |
780 */ |
781 */ |
781 void ec_master_queue_external_datagram( |
782 void ec_master_queue_request_fsm_datagram( |
782 ec_master_t *master, /**< EtherCAT master */ |
783 ec_master_t *master, /**< EtherCAT master */ |
783 ec_datagram_t *datagram /**< datagram */ |
784 ec_datagram_t *datagram /**< datagram */ |
784 ) |
785 ) |
785 { |
786 { |
|
787 ec_master_queue_fsm_datagram(master,datagram); |
|
788 master->fsm.idle = 0; // pump the bus as fast as possible |
|
789 } |
|
790 |
|
791 /*****************************************************************************/ |
|
792 |
|
793 /** Places an fsm datagram in the sdo datagram queue. |
|
794 */ |
|
795 void ec_master_queue_fsm_datagram( |
|
796 ec_master_t *master, /**< EtherCAT master */ |
|
797 ec_datagram_t *datagram /**< datagram */ |
|
798 ) |
|
799 { |
786 ec_datagram_t *queued_datagram; |
800 ec_datagram_t *queued_datagram; |
787 |
801 |
788 down(&master->io_sem); |
802 if (master->fsm_queue_lock_cb) |
|
803 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
|
804 ec_mutex_lock(&master->fsm_queue_mutex); |
789 |
805 |
790 // check, if the datagram is already queued |
806 // check, if the datagram is already queued |
791 list_for_each_entry(queued_datagram, &master->external_datagram_queue, |
807 list_for_each_entry(queued_datagram, &master->fsm_datagram_queue, |
792 queue) { |
808 fsm_queue) { |
793 if (queued_datagram == datagram) { |
809 if (queued_datagram == datagram) { |
794 datagram->state = EC_DATAGRAM_QUEUED; |
810 datagram->state = EC_DATAGRAM_QUEUED; |
|
811 ec_mutex_unlock(&master->fsm_queue_mutex); |
|
812 if (master->fsm_queue_unlock_cb) |
|
813 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
795 return; |
814 return; |
796 } |
815 } |
797 } |
816 } |
798 |
817 |
799 #if DEBUG_INJECT |
818 #if DEBUG_INJECT |
800 EC_MASTER_DBG(master, 0, "Requesting external datagram %p size=%u\n", |
819 EC_MASTER_DBG(master, 2, "Requesting fsm datagram %p size=%zu\n", |
801 datagram, datagram->data_size); |
820 datagram, datagram->data_size); |
802 #endif |
821 #endif |
803 |
822 |
804 list_add_tail(&datagram->queue, &master->external_datagram_queue); |
823 list_add_tail(&datagram->fsm_queue, &master->fsm_datagram_queue); |
805 datagram->state = EC_DATAGRAM_QUEUED; |
824 datagram->state = EC_DATAGRAM_QUEUED; |
806 #ifdef EC_HAVE_CYCLES |
825 #ifdef EC_HAVE_CYCLES |
807 datagram->cycles_sent = get_cycles(); |
826 datagram->cycles_sent = get_cycles(); |
808 #endif |
827 #endif |
809 datagram->jiffies_sent = jiffies; |
828 datagram->jiffies_sent = jiffies; |
810 |
829 |
811 master->fsm.idle = 0; |
830 ec_mutex_unlock(&master->fsm_queue_mutex); |
812 up(&master->io_sem); |
831 if (master->fsm_queue_unlock_cb) |
|
832 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
813 } |
833 } |
814 |
834 |
815 /*****************************************************************************/ |
835 /*****************************************************************************/ |
816 |
836 |
817 /** Places a datagram in the datagram queue. |
837 /** Places a datagram in the datagram queue. |
839 datagram->state = EC_DATAGRAM_QUEUED; |
859 datagram->state = EC_DATAGRAM_QUEUED; |
840 break; |
860 break; |
841 } |
861 } |
842 } |
862 } |
843 |
863 |
844 /*****************************************************************************/ |
|
845 |
|
846 /** Places a datagram in the non-application datagram queue. |
|
847 */ |
|
848 void ec_master_queue_datagram_ext( |
|
849 ec_master_t *master, /**< EtherCAT master */ |
|
850 ec_datagram_t *datagram /**< datagram */ |
|
851 ) |
|
852 { |
|
853 down(&master->ext_queue_sem); |
|
854 list_add_tail(&datagram->queue, &master->ext_datagram_queue); |
|
855 up(&master->ext_queue_sem); |
|
856 } |
|
857 |
864 |
858 /*****************************************************************************/ |
865 /*****************************************************************************/ |
859 |
866 |
860 /** Sends the datagrams in the queue. |
867 /** Sends the datagrams in the queue. |
861 * |
868 * |
862 */ |
869 */ |
863 void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) |
870 void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */) |
864 { |
871 { |
865 ec_datagram_t *datagram, *next; |
872 ec_datagram_t *datagram, *next; |
866 size_t datagram_size; |
873 size_t datagram_size; |
867 uint8_t *frame_data, *cur_data; |
874 uint8_t *frame_data, *cur_data, *frame_datagram_data; |
868 void *follows_word; |
875 void *follows_word; |
869 #ifdef EC_HAVE_CYCLES |
876 #ifdef EC_HAVE_CYCLES |
870 cycles_t cycles_start, cycles_sent, cycles_end; |
877 cycles_t cycles_start, cycles_sent, cycles_end; |
871 #endif |
878 #endif |
872 unsigned long jiffies_sent; |
879 unsigned long jiffies_sent; |
873 unsigned int frame_count, more_datagrams_waiting; |
880 unsigned int frame_count, more_datagrams_waiting; |
874 struct list_head sent_datagrams; |
881 struct list_head sent_datagrams; |
|
882 ec_fmmu_config_t* domain_fmmu; |
875 |
883 |
876 #ifdef EC_HAVE_CYCLES |
884 #ifdef EC_HAVE_CYCLES |
877 cycles_start = get_cycles(); |
885 cycles_start = get_cycles(); |
878 #endif |
886 #endif |
879 frame_count = 0; |
887 frame_count = 0; |
1222 |
1273 |
1223 while (!kthread_should_stop()) { |
1274 while (!kthread_should_stop()) { |
1224 ec_datagram_output_stats(&master->fsm_datagram); |
1275 ec_datagram_output_stats(&master->fsm_datagram); |
1225 |
1276 |
1226 // receive |
1277 // receive |
1227 down(&master->io_sem); |
1278 ec_mutex_lock(&master->io_mutex); |
1228 ecrt_master_receive(master); |
1279 ecrt_master_receive(master); |
1229 up(&master->io_sem); |
1280 ec_mutex_unlock(&master->io_mutex); |
1230 |
1281 |
1231 fsm_exec = 0; |
|
1232 // execute master & slave state machines |
1282 // execute master & slave state machines |
1233 if (down_interruptible(&master->master_sem)) |
1283 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
1234 break; |
1284 break; |
1235 fsm_exec = ec_fsm_master_exec(&master->fsm); |
1285 if (ec_fsm_master_exec(&master->fsm)) { |
|
1286 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
|
1287 } |
1236 for (slave = master->slaves; |
1288 for (slave = master->slaves; |
1237 slave < master->slaves + master->slave_count; |
1289 slave < master->slaves + master->slave_count; |
1238 slave++) { |
1290 slave++) { |
1239 ec_fsm_slave_exec(&slave->fsm); |
1291 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1240 } |
1292 } |
1241 up(&master->master_sem); |
1293 #if defined(EC_EOE) |
|
1294 if (!ec_master_eoe_processing(master)) |
|
1295 master->fsm.idle = 0; // pump the bus as fast as possible |
|
1296 #endif |
|
1297 ec_mutex_unlock(&master->master_mutex); |
1242 |
1298 |
1243 // queue and send |
1299 // queue and send |
1244 down(&master->io_sem); |
1300 ec_mutex_lock(&master->io_mutex); |
1245 if (fsm_exec) { |
|
1246 ec_master_queue_datagram(master, &master->fsm_datagram); |
|
1247 } |
|
1248 ec_master_inject_external_datagrams(master); |
|
1249 ecrt_master_send(master); |
1301 ecrt_master_send(master); |
1250 sent_bytes = master->main_device.tx_skb[ |
1302 sent_bytes = master->main_device.tx_skb[ |
1251 master->main_device.tx_ring_index]->len; |
1303 master->main_device.tx_ring_index]->len; |
1252 up(&master->io_sem); |
1304 ec_mutex_unlock(&master->io_mutex); |
1253 |
1305 |
1254 if (ec_fsm_master_idle(&master->fsm)) { |
1306 if (ec_fsm_master_idle(&master->fsm)) { |
1255 #ifdef EC_USE_HRTIMER |
1307 #ifdef EC_USE_HRTIMER |
1256 ec_master_nanosleep(master->send_interval * 1000); |
1308 ec_master_nanosleep(master->send_interval * 1000); |
1257 #else |
1309 #else |
1278 */ |
1330 */ |
1279 static int ec_master_operation_thread(void *priv_data) |
1331 static int ec_master_operation_thread(void *priv_data) |
1280 { |
1332 { |
1281 ec_master_t *master = (ec_master_t *) priv_data; |
1333 ec_master_t *master = (ec_master_t *) priv_data; |
1282 ec_slave_t *slave = NULL; |
1334 ec_slave_t *slave = NULL; |
1283 int fsm_exec; |
|
1284 |
1335 |
1285 EC_MASTER_DBG(master, 1, "Operation thread running" |
1336 EC_MASTER_DBG(master, 1, "Operation thread running" |
1286 " with fsm interval = %u us, max data size=%zu\n", |
1337 " with fsm interval = %u us, max data size=%zu\n", |
1287 master->send_interval, master->max_queue_size); |
1338 master->send_interval, master->max_queue_size); |
1288 |
1339 |
1289 while (!kthread_should_stop()) { |
1340 while (!kthread_should_stop()) { |
1290 ec_datagram_output_stats(&master->fsm_datagram); |
1341 ec_datagram_output_stats(&master->fsm_datagram); |
1291 |
1342 |
1292 if (master->injection_seq_rt == master->injection_seq_fsm) { |
1343 // output statistics |
1293 // output statistics |
1344 ec_master_output_stats(master); |
1294 ec_master_output_stats(master); |
1345 |
1295 |
1346 // execute master & slave state machines |
1296 fsm_exec = 0; |
1347 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
1297 // execute master & slave state machines |
1348 break; |
1298 if (down_interruptible(&master->master_sem)) |
1349 if (ec_fsm_master_exec(&master->fsm)) |
1299 break; |
1350 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
1300 fsm_exec += ec_fsm_master_exec(&master->fsm); |
1351 for (slave = master->slaves; |
1301 for (slave = master->slaves; |
1352 slave < master->slaves + master->slave_count; |
1302 slave < master->slaves + master->slave_count; |
1353 slave++) { |
1303 slave++) { |
1354 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1304 ec_fsm_slave_exec(&slave->fsm); |
1355 } |
1305 } |
1356 #if defined(EC_EOE) |
1306 up(&master->master_sem); |
1357 ec_master_eoe_processing(master); |
1307 |
1358 #endif |
1308 // inject datagrams (let the rt thread queue them, see |
1359 ec_mutex_unlock(&master->master_mutex); |
1309 // ecrt_master_send) |
|
1310 if (fsm_exec) |
|
1311 master->injection_seq_fsm++; |
|
1312 } |
|
1313 |
1360 |
1314 #ifdef EC_USE_HRTIMER |
1361 #ifdef EC_USE_HRTIMER |
1315 // the op thread should not work faster than the sending RT thread |
1362 // the op thread should not work faster than the sending RT thread |
1316 ec_master_nanosleep(master->send_interval * 1000); |
1363 ec_master_nanosleep(master->send_interval * 1000); |
1317 #else |
1364 #else |
1330 } |
1377 } |
1331 |
1378 |
1332 /*****************************************************************************/ |
1379 /*****************************************************************************/ |
1333 |
1380 |
1334 #ifdef EC_EOE |
1381 #ifdef EC_EOE |
1335 /** Starts Ethernet over EtherCAT processing on demand. |
|
1336 */ |
|
1337 void ec_master_eoe_start(ec_master_t *master /**< EtherCAT master */) |
|
1338 { |
|
1339 struct sched_param param = { .sched_priority = 0 }; |
|
1340 |
|
1341 if (master->eoe_thread) { |
|
1342 EC_MASTER_WARN(master, "EoE already running!\n"); |
|
1343 return; |
|
1344 } |
|
1345 |
|
1346 if (list_empty(&master->eoe_handlers)) |
|
1347 return; |
|
1348 |
|
1349 if (!master->send_cb || !master->receive_cb) { |
|
1350 EC_MASTER_WARN(master, "No EoE processing" |
|
1351 " because of missing callbacks!\n"); |
|
1352 return; |
|
1353 } |
|
1354 |
|
1355 EC_MASTER_INFO(master, "Starting EoE thread.\n"); |
|
1356 master->eoe_thread = kthread_run(ec_master_eoe_thread, master, |
|
1357 "EtherCAT-EoE"); |
|
1358 if (IS_ERR(master->eoe_thread)) { |
|
1359 int err = (int) PTR_ERR(master->eoe_thread); |
|
1360 EC_MASTER_ERR(master, "Failed to start EoE thread (error %i)!\n", |
|
1361 err); |
|
1362 master->eoe_thread = NULL; |
|
1363 return; |
|
1364 } |
|
1365 |
|
1366 sched_setscheduler(master->eoe_thread, SCHED_NORMAL, ¶m); |
|
1367 set_user_nice(master->eoe_thread, 0); |
|
1368 } |
|
1369 |
|
1370 /*****************************************************************************/ |
|
1371 |
|
1372 /** Stops the Ethernet over EtherCAT processing. |
|
1373 */ |
|
1374 void ec_master_eoe_stop(ec_master_t *master /**< EtherCAT master */) |
|
1375 { |
|
1376 if (master->eoe_thread) { |
|
1377 EC_MASTER_INFO(master, "Stopping EoE thread.\n"); |
|
1378 |
|
1379 kthread_stop(master->eoe_thread); |
|
1380 master->eoe_thread = NULL; |
|
1381 EC_MASTER_INFO(master, "EoE thread exited.\n"); |
|
1382 } |
|
1383 } |
|
1384 |
1382 |
1385 /*****************************************************************************/ |
1383 /*****************************************************************************/ |
1386 |
1384 |
1387 /** Does the Ethernet over EtherCAT processing. |
1385 /** Does the Ethernet over EtherCAT processing. |
1388 */ |
1386 */ |
1389 static int ec_master_eoe_thread(void *priv_data) |
1387 static int ec_master_eoe_processing(ec_master_t *master) |
1390 { |
1388 { |
1391 ec_master_t *master = (ec_master_t *) priv_data; |
|
1392 ec_eoe_t *eoe; |
1389 ec_eoe_t *eoe; |
1393 unsigned int none_open, sth_to_send, all_idle; |
1390 unsigned int none_open, sth_to_send, all_idle; |
1394 |
1391 none_open = 1; |
1395 EC_MASTER_DBG(master, 1, "EoE thread running.\n"); |
1392 all_idle = 1; |
1396 |
1393 |
1397 while (!kthread_should_stop()) { |
1394 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1398 none_open = 1; |
1395 if (ec_eoe_is_open(eoe)) { |
1399 all_idle = 1; |
1396 none_open = 0; |
1400 |
1397 break; |
|
1398 } |
|
1399 } |
|
1400 if (none_open) |
|
1401 return all_idle; |
|
1402 |
|
1403 // actual EoE processing |
|
1404 sth_to_send = 0; |
|
1405 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
1406 ec_eoe_run(eoe); |
|
1407 if (eoe->queue_datagram) { |
|
1408 sth_to_send = 1; |
|
1409 } |
|
1410 if (!ec_eoe_is_idle(eoe)) { |
|
1411 all_idle = 0; |
|
1412 } |
|
1413 } |
|
1414 |
|
1415 if (sth_to_send) { |
1401 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1416 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
1402 if (ec_eoe_is_open(eoe)) { |
1417 ec_eoe_queue(eoe); |
1403 none_open = 0; |
1418 } |
1404 break; |
1419 } |
1405 } |
1420 return all_idle; |
1406 } |
1421 } |
1407 if (none_open) |
1422 |
1408 goto schedule; |
1423 #endif // EC_EOE |
1409 |
|
1410 // receive datagrams |
|
1411 master->receive_cb(master->cb_data); |
|
1412 |
|
1413 // actual EoE processing |
|
1414 sth_to_send = 0; |
|
1415 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
1416 ec_eoe_run(eoe); |
|
1417 if (eoe->queue_datagram) { |
|
1418 sth_to_send = 1; |
|
1419 } |
|
1420 if (!ec_eoe_is_idle(eoe)) { |
|
1421 all_idle = 0; |
|
1422 } |
|
1423 } |
|
1424 |
|
1425 if (sth_to_send) { |
|
1426 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
1427 ec_eoe_queue(eoe); |
|
1428 } |
|
1429 // (try to) send datagrams |
|
1430 down(&master->ext_queue_sem); |
|
1431 master->send_cb(master->cb_data); |
|
1432 up(&master->ext_queue_sem); |
|
1433 } |
|
1434 |
|
1435 schedule: |
|
1436 if (all_idle) { |
|
1437 set_current_state(TASK_INTERRUPTIBLE); |
|
1438 schedule_timeout(1); |
|
1439 } else { |
|
1440 schedule(); |
|
1441 } |
|
1442 } |
|
1443 |
|
1444 EC_MASTER_DBG(master, 1, "EoE thread exiting...\n"); |
|
1445 return 0; |
|
1446 } |
|
1447 #endif |
|
1448 |
1424 |
1449 /*****************************************************************************/ |
1425 /*****************************************************************************/ |
1450 |
1426 |
1451 /** Detaches the slave configurations from the slaves. |
1427 /** Detaches the slave configurations from the slaves. |
1452 */ |
1428 */ |
1930 int ecrt_master_activate(ec_master_t *master) |
1929 int ecrt_master_activate(ec_master_t *master) |
1931 { |
1930 { |
1932 uint32_t domain_offset; |
1931 uint32_t domain_offset; |
1933 ec_domain_t *domain; |
1932 ec_domain_t *domain; |
1934 int ret; |
1933 int ret; |
1935 #ifdef EC_EOE |
|
1936 int eoe_was_running; |
|
1937 #endif |
|
1938 |
1934 |
1939 EC_MASTER_DBG(master, 1, "ecrt_master_activate(master = 0x%p)\n", master); |
1935 EC_MASTER_DBG(master, 1, "ecrt_master_activate(master = 0x%p)\n", master); |
1940 |
1936 |
1941 if (master->active) { |
1937 if (master->active) { |
1942 EC_MASTER_WARN(master, "%s: Master already active!\n", __func__); |
1938 EC_MASTER_WARN(master, "%s: Master already active!\n", __func__); |
1943 return 0; |
1939 return 0; |
1944 } |
1940 } |
1945 |
1941 |
1946 down(&master->master_sem); |
1942 ec_mutex_lock(&master->master_mutex); |
1947 |
1943 |
1948 // finish all domains |
1944 // finish all domains |
1949 domain_offset = 0; |
1945 domain_offset = 0; |
1950 list_for_each_entry(domain, &master->domains, list) { |
1946 list_for_each_entry(domain, &master->domains, list) { |
1951 ret = ec_domain_finish(domain, domain_offset); |
1947 ret = ec_domain_finish(domain, domain_offset); |
1952 if (ret < 0) { |
1948 if (ret < 0) { |
1953 up(&master->master_sem); |
1949 ec_mutex_unlock(&master->master_mutex); |
1954 EC_MASTER_ERR(master, "Failed to finish domain 0x%p!\n", domain); |
1950 EC_MASTER_ERR(master, "Failed to finish domain 0x%p!\n", domain); |
1955 return ret; |
1951 return ret; |
1956 } |
1952 } |
1957 domain_offset += domain->data_size; |
1953 domain_offset += domain->data_size; |
1958 } |
1954 } |
1959 |
1955 |
1960 up(&master->master_sem); |
1956 ec_mutex_unlock(&master->master_mutex); |
1961 |
1957 |
1962 // restart EoE process and master thread with new locking |
1958 // restart EoE process and master thread with new locking |
1963 |
1959 |
1964 ec_master_thread_stop(master); |
1960 ec_master_thread_stop(master); |
1965 #ifdef EC_EOE |
|
1966 eoe_was_running = master->eoe_thread != NULL; |
|
1967 ec_master_eoe_stop(master); |
|
1968 #endif |
|
1969 |
1961 |
1970 EC_MASTER_DBG(master, 1, "FSM datagram is %p.\n", &master->fsm_datagram); |
1962 EC_MASTER_DBG(master, 1, "FSM datagram is %p.\n", &master->fsm_datagram); |
1971 |
1963 |
1972 master->injection_seq_fsm = 0; |
1964 master->injection_seq_fsm = 0; |
1973 master->injection_seq_rt = 0; |
1965 master->injection_seq_rt = 0; |
1974 |
1966 |
1975 master->send_cb = master->app_send_cb; |
1967 master->fsm_queue_lock_cb = master->app_fsm_queue_lock_cb; |
1976 master->receive_cb = master->app_receive_cb; |
1968 master->fsm_queue_unlock_cb = master->app_fsm_queue_unlock_cb; |
1977 master->cb_data = master->app_cb_data; |
1969 master->fsm_queue_locking_data = master->app_fsm_queue_locking_data; |
1978 |
1970 |
1979 #ifdef EC_EOE |
|
1980 if (eoe_was_running) { |
|
1981 ec_master_eoe_start(master); |
|
1982 } |
|
1983 #endif |
|
1984 ret = ec_master_thread_start(master, ec_master_operation_thread, |
1971 ret = ec_master_thread_start(master, ec_master_operation_thread, |
1985 "EtherCAT-OP"); |
1972 "EtherCAT-OP"); |
1986 if (ret < 0) { |
1973 if (ret < 0) { |
1987 EC_MASTER_ERR(master, "Failed to start master thread!\n"); |
1974 EC_MASTER_ERR(master, "Failed to start master thread!\n"); |
1988 return ret; |
1975 return ret; |
2003 void ecrt_master_deactivate(ec_master_t *master) |
1990 void ecrt_master_deactivate(ec_master_t *master) |
2004 { |
1991 { |
2005 ec_slave_t *slave; |
1992 ec_slave_t *slave; |
2006 #ifdef EC_EOE |
1993 #ifdef EC_EOE |
2007 ec_eoe_t *eoe; |
1994 ec_eoe_t *eoe; |
2008 int eoe_was_running; |
1995 int is_eoe_slave; |
2009 #endif |
1996 #endif |
2010 |
1997 |
2011 EC_MASTER_DBG(master, 1, "%s(master = 0x%p)\n", __func__, master); |
1998 EC_MASTER_DBG(master, 1, "%s(master = 0x%p)\n", __func__, master); |
2012 |
1999 |
2013 if (!master->active) { |
2000 if (!master->active) { |
2014 EC_MASTER_WARN(master, "%s: Master not active.\n", __func__); |
2001 EC_MASTER_WARN(master, "%s: Master not active.\n", __func__); |
2015 return; |
2002 return; |
2016 } |
2003 } |
2017 |
2004 |
2018 ec_master_thread_stop(master); |
2005 ec_master_thread_stop(master); |
2019 #ifdef EC_EOE |
|
2020 eoe_was_running = master->eoe_thread != NULL; |
|
2021 ec_master_eoe_stop(master); |
|
2022 #endif |
|
2023 |
2006 |
2024 master->send_cb = ec_master_internal_send_cb; |
2007 master->fsm_queue_lock_cb = NULL; |
2025 master->receive_cb = ec_master_internal_receive_cb; |
2008 master->fsm_queue_unlock_cb= NULL; |
2026 master->cb_data = master; |
2009 master->fsm_queue_locking_data = NULL; |
2027 |
2010 |
2028 ec_master_clear_config(master); |
2011 ec_master_clear_config(master); |
2029 |
2012 |
2030 for (slave = master->slaves; |
2013 for (slave = master->slaves; |
2031 slave < master->slaves + master->slave_count; |
2014 slave < master->slaves + master->slave_count; |
2032 slave++) { |
2015 slave++) { |
2033 |
2016 |
2034 // set states for all slaves |
2017 // set state to PREOP for all but eoe slaves |
|
2018 #ifdef EC_EOE |
|
2019 is_eoe_slave = 0; |
|
2020 // ... but leave EoE slaves in OP |
|
2021 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
2022 if (slave == eoe->slave && ec_eoe_is_open(eoe)) |
|
2023 is_eoe_slave = 1; |
|
2024 } |
|
2025 if (!is_eoe_slave) { |
|
2026 ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); |
|
2027 // mark for reconfiguration, because the master could have no |
|
2028 // possibility for a reconfiguration between two sequential operation |
|
2029 // phases. |
|
2030 slave->force_config = 1; |
|
2031 } |
|
2032 #else |
2035 ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); |
2033 ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP); |
2036 |
|
2037 // mark for reconfiguration, because the master could have no |
2034 // mark for reconfiguration, because the master could have no |
2038 // possibility for a reconfiguration between two sequential operation |
2035 // possibility for a reconfiguration between two sequential operation |
2039 // phases. |
2036 // phases. |
2040 slave->force_config = 1; |
2037 slave->force_config = 1; |
2041 } |
2038 #endif |
2042 |
2039 |
2043 #ifdef EC_EOE |
2040 } |
2044 // ... but leave EoE slaves in OP |
|
2045 list_for_each_entry(eoe, &master->eoe_handlers, list) { |
|
2046 if (ec_eoe_is_open(eoe)) |
|
2047 ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP); |
|
2048 } |
|
2049 #endif |
|
2050 |
2041 |
2051 master->app_time = 0ULL; |
2042 master->app_time = 0ULL; |
2052 master->app_start_time = 0ULL; |
2043 master->app_start_time = 0ULL; |
2053 master->has_app_time = 0; |
2044 master->has_app_time = 0; |
2054 |
2045 |
2055 #ifdef EC_EOE |
|
2056 if (eoe_was_running) { |
|
2057 ec_master_eoe_start(master); |
|
2058 } |
|
2059 #endif |
|
2060 if (ec_master_thread_start(master, ec_master_idle_thread, |
2046 if (ec_master_thread_start(master, ec_master_idle_thread, |
2061 "EtherCAT-IDLE")) |
2047 "EtherCAT-IDLE")) |
2062 EC_MASTER_WARN(master, "Failed to restart master thread!\n"); |
2048 EC_MASTER_WARN(master, "Failed to restart master thread!\n"); |
2063 |
2049 |
2064 master->allow_scan = 1; |
2050 master->allow_scan = 1; |
2349 |
2342 |
2350 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
2343 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
2351 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
2344 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
2352 uint16_t *error_code) |
2345 uint16_t *error_code) |
2353 { |
2346 { |
2354 ec_master_soe_request_t request; |
2347 ec_master_soe_request_t* request; |
2355 int retval; |
2348 int retval; |
2356 |
2349 |
2357 if (drive_no > 7) { |
2350 if (drive_no > 7) { |
2358 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2351 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2359 return -EINVAL; |
2352 return -EINVAL; |
2360 } |
2353 } |
2361 |
2354 |
2362 INIT_LIST_HEAD(&request.list); |
2355 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2363 ec_soe_request_init(&request.req); |
2356 if (!request) |
2364 ec_soe_request_set_drive_no(&request.req, drive_no); |
|
2365 ec_soe_request_set_idn(&request.req, idn); |
|
2366 |
|
2367 if (ec_soe_request_alloc(&request.req, data_size)) { |
|
2368 ec_soe_request_clear(&request.req); |
|
2369 return -ENOMEM; |
2357 return -ENOMEM; |
2370 } |
2358 kref_init(&request->refcount); |
2371 |
2359 |
2372 memcpy(request.req.data, data, data_size); |
2360 INIT_LIST_HEAD(&request->list); |
2373 request.req.data_size = data_size; |
2361 ec_soe_request_init(&request->req); |
2374 ec_soe_request_write(&request.req); |
2362 ec_soe_request_set_drive_no(&request->req, drive_no); |
2375 |
2363 ec_soe_request_set_idn(&request->req, idn); |
2376 if (down_interruptible(&master->master_sem)) |
2364 |
|
2365 if (ec_soe_request_alloc(&request->req, data_size)) { |
|
2366 ec_soe_request_clear(&request->req); |
|
2367 kref_put(&request->refcount,ec_master_soe_request_release); |
|
2368 return -ENOMEM; |
|
2369 } |
|
2370 |
|
2371 memcpy(request->req.data, data, data_size); |
|
2372 request->req.data_size = data_size; |
|
2373 ec_soe_request_write(&request->req); |
|
2374 |
|
2375 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2376 kref_put(&request->refcount,ec_master_soe_request_release); |
2377 return -EINTR; |
2377 return -EINTR; |
2378 |
2378 } |
2379 if (!(request.slave = ec_master_find_slave( |
2379 |
|
2380 if (!(request->slave = ec_master_find_slave( |
2380 master, 0, slave_position))) { |
2381 master, 0, slave_position))) { |
2381 up(&master->master_sem); |
2382 ec_mutex_unlock(&master->master_mutex); |
2382 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
2383 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
2383 slave_position); |
2384 slave_position); |
2384 ec_soe_request_clear(&request.req); |
2385 kref_put(&request->refcount,ec_master_soe_request_release); |
2385 return -EINVAL; |
2386 return -EINVAL; |
2386 } |
2387 } |
2387 |
2388 |
2388 EC_SLAVE_DBG(request.slave, 1, "Scheduling SoE write request.\n"); |
2389 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE write request %p.\n",request); |
2389 |
2390 |
2390 // schedule SoE write request. |
2391 // schedule SoE write request. |
2391 list_add_tail(&request.list, &request.slave->soe_requests); |
2392 list_add_tail(&request->list, &request->slave->soe_requests); |
2392 |
2393 kref_get(&request->refcount); |
2393 up(&master->master_sem); |
2394 |
|
2395 ec_mutex_unlock(&master->master_mutex); |
2394 |
2396 |
2395 // wait for processing through FSM |
2397 // wait for processing through FSM |
2396 if (wait_event_interruptible(request.slave->soe_queue, |
2398 if (wait_event_interruptible(request->slave->soe_queue, |
2397 request.req.state != EC_INT_REQUEST_QUEUED)) { |
2399 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
2398 // interrupted by signal |
2400 // interrupted by signal |
2399 down(&master->master_sem); |
2401 kref_put(&request->refcount,ec_master_soe_request_release); |
2400 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
2402 return -EINTR; |
2401 // abort request |
2403 } |
2402 list_del(&request.list); |
|
2403 up(&master->master_sem); |
|
2404 ec_soe_request_clear(&request.req); |
|
2405 return -EINTR; |
|
2406 } |
|
2407 up(&master->master_sem); |
|
2408 } |
|
2409 |
|
2410 // wait until master FSM has finished processing |
|
2411 wait_event(request.slave->soe_queue, |
|
2412 request.req.state != EC_INT_REQUEST_BUSY); |
|
2413 |
2404 |
2414 if (error_code) { |
2405 if (error_code) { |
2415 *error_code = request.req.error_code; |
2406 *error_code = request->req.error_code; |
2416 } |
2407 } |
2417 retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
2408 retval = request->req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
2418 ec_soe_request_clear(&request.req); |
2409 kref_put(&request->refcount,ec_master_soe_request_release); |
2419 |
2410 |
2420 return retval; |
2411 return retval; |
2421 } |
2412 } |
2422 |
2413 |
2423 /*****************************************************************************/ |
2414 /*****************************************************************************/ |
2424 |
2415 |
2425 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
2416 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
2426 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
2417 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
2427 size_t *result_size, uint16_t *error_code) |
2418 size_t *result_size, uint16_t *error_code) |
2428 { |
2419 { |
2429 ec_master_soe_request_t request; |
2420 ec_master_soe_request_t* request; |
2430 |
2421 |
2431 if (drive_no > 7) { |
2422 if (drive_no > 7) { |
2432 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2423 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2433 return -EINVAL; |
2424 return -EINVAL; |
2434 } |
2425 } |
2435 |
2426 |
2436 INIT_LIST_HEAD(&request.list); |
2427 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2437 ec_soe_request_init(&request.req); |
2428 if (!request) |
2438 ec_soe_request_set_drive_no(&request.req, drive_no); |
2429 return -ENOMEM; |
2439 ec_soe_request_set_idn(&request.req, idn); |
2430 kref_init(&request->refcount); |
2440 ec_soe_request_read(&request.req); |
2431 |
2441 |
2432 INIT_LIST_HEAD(&request->list); |
2442 if (down_interruptible(&master->master_sem)) |
2433 ec_soe_request_init(&request->req); |
|
2434 ec_soe_request_set_drive_no(&request->req, drive_no); |
|
2435 ec_soe_request_set_idn(&request->req, idn); |
|
2436 ec_soe_request_read(&request->req); |
|
2437 |
|
2438 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2439 kref_put(&request->refcount,ec_master_soe_request_release); |
2443 return -EINTR; |
2440 return -EINTR; |
2444 |
2441 } |
2445 if (!(request.slave = ec_master_find_slave(master, 0, slave_position))) { |
2442 |
2446 up(&master->master_sem); |
2443 if (!(request->slave = ec_master_find_slave(master, 0, slave_position))) { |
2447 ec_soe_request_clear(&request.req); |
2444 ec_mutex_unlock(&master->master_mutex); |
|
2445 kref_put(&request->refcount,ec_master_soe_request_release); |
2448 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2446 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2449 return -EINVAL; |
2447 return -EINVAL; |
2450 } |
2448 } |
2451 |
2449 |
2452 // schedule request. |
2450 // schedule request. |
2453 list_add_tail(&request.list, &request.slave->soe_requests); |
2451 list_add_tail(&request->list, &request->slave->soe_requests); |
2454 |
2452 kref_get(&request->refcount); |
2455 up(&master->master_sem); |
2453 |
2456 |
2454 ec_mutex_unlock(&master->master_mutex); |
2457 EC_SLAVE_DBG(request.slave, 1, "Scheduled SoE read request.\n"); |
2455 |
|
2456 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE read request %p.\n",request); |
2458 |
2457 |
2459 // wait for processing through FSM |
2458 // wait for processing through FSM |
2460 if (wait_event_interruptible(request.slave->soe_queue, |
2459 if (wait_event_interruptible(request->slave->soe_queue, |
2461 request.req.state != EC_INT_REQUEST_QUEUED)) { |
2460 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
2462 // interrupted by signal |
2461 // interrupted by signal |
2463 down(&master->master_sem); |
2462 kref_put(&request->refcount,ec_master_soe_request_release); |
2464 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
2463 return -EINTR; |
2465 list_del(&request.list); |
2464 } |
2466 up(&master->master_sem); |
|
2467 ec_soe_request_clear(&request.req); |
|
2468 return -EINTR; |
|
2469 } |
|
2470 // request already processing: interrupt not possible. |
|
2471 up(&master->master_sem); |
|
2472 } |
|
2473 |
|
2474 // wait until master FSM has finished processing |
|
2475 wait_event(request.slave->soe_queue, |
|
2476 request.req.state != EC_INT_REQUEST_BUSY); |
|
2477 |
2465 |
2478 if (error_code) { |
2466 if (error_code) { |
2479 *error_code = request.req.error_code; |
2467 *error_code = request->req.error_code; |
2480 } |
2468 } |
2481 |
2469 |
2482 EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via SoE.\n", |
2470 EC_SLAVE_DBG(request->slave, 1, "SoE request %p read %zd bytes via SoE.\n", |
2483 request.req.data_size); |
2471 request,request->req.data_size); |
2484 |
2472 |
2485 if (request.req.state != EC_INT_REQUEST_SUCCESS) { |
2473 if (request->req.state != EC_INT_REQUEST_SUCCESS) { |
2486 if (result_size) { |
2474 if (result_size) { |
2487 *result_size = 0; |
2475 *result_size = 0; |
2488 } |
2476 } |
2489 ec_soe_request_clear(&request.req); |
2477 kref_put(&request->refcount,ec_master_soe_request_release); |
2490 return -EIO; |
2478 return -EIO; |
2491 } else { |
2479 } else { |
2492 if (request.req.data_size > target_size) { |
2480 if (request->req.data_size > target_size) { |
2493 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2481 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2494 ec_soe_request_clear(&request.req); |
2482 kref_put(&request->refcount,ec_master_soe_request_release); |
2495 return -EOVERFLOW; |
2483 return -EOVERFLOW; |
2496 } |
2484 } |
2497 if (result_size) { |
2485 if (result_size) { |
2498 *result_size = request.req.data_size; |
2486 *result_size = request->req.data_size; |
2499 } |
2487 } |
2500 memcpy(target, request.req.data, request.req.data_size); |
2488 memcpy(target, request->req.data, request->req.data_size); |
|
2489 kref_put(&request->refcount,ec_master_soe_request_release); |
2501 return 0; |
2490 return 0; |
2502 } |
2491 } |
2503 } |
2492 } |
2504 |
2493 |
2505 /*****************************************************************************/ |
2494 /*****************************************************************************/ |