aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHenrik Kurelid <henrik@kurelid.se>2008-08-24 09:20:07 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-02-24 08:51:26 -0500
commit81c67b7f82769292a86b802590be5879413f9278 (patch)
treeeebc9d27ecda8f14a48a8195e84057717fcfd89e /drivers
parentdf4846c35247a0d038c5359d502cddd59d04bc40 (diff)
firesat: avc resend
- Add resending of AVC message to the card if no answer is received - Replace the homebrewed event_wait function with a standard wait queue - Clean up of log/error messages - Increase debug level of avc communication Signed-off-by: Henrik Kurelid <henrik@kurelid.se> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/firesat/avc_api.c173
-rw-r--r--drivers/media/dvb/firesat/firesat.h1
-rw-r--r--drivers/media/dvb/firesat/firesat_1394.c1
3 files changed, 95 insertions, 80 deletions
diff --git a/drivers/media/dvb/firesat/avc_api.c b/drivers/media/dvb/firesat/avc_api.c
index 273c7235dd90..3c8e7e3dacc2 100644
--- a/drivers/media/dvb/firesat/avc_api.c
+++ b/drivers/media/dvb/firesat/avc_api.c
@@ -26,7 +26,7 @@
26 26
27static unsigned int avc_comm_debug = 0; 27static unsigned int avc_comm_debug = 0;
28module_param(avc_comm_debug, int, 0644); 28module_param(avc_comm_debug, int, 0644);
29MODULE_PARM_DESC(avc_comm_debug, "debug logging of AV/C communication, default is 0 (no)"); 29MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)");
30 30
31static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal); 31static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal);
32 32
@@ -37,22 +37,6 @@ static void avc_free_packet(struct hpsb_packet *packet)
37 hpsb_free_packet(packet); 37 hpsb_free_packet(packet);
38} 38}
39 39
40/*
41 * Goofy routine that basically does a down_timeout function.
42 * Stolen from sbp2.c
43 */
44static int avc_down_timeout(atomic_t *done, int timeout)
45{
46 int i;
47
48 for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
49 set_current_state(TASK_INTERRUPTIBLE);
50 if (schedule_timeout(HZ/10)) /* 100ms */
51 return(1);
52 }
53 return ((i > 0) ? 0:1);
54}
55
56static const char* get_ctype_string(__u8 ctype) 40static const char* get_ctype_string(__u8 ctype)
57{ 41{
58 switch(ctype) 42 switch(ctype)
@@ -135,97 +119,115 @@ static void log_command_frame(const AVCCmdFrm *CmdFrm)
135{ 119{
136 int k; 120 int k;
137 printk(KERN_INFO "AV/C Command Frame:\n"); 121 printk(KERN_INFO "AV/C Command Frame:\n");
138 printk("CommandType=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " 122 printk(KERN_INFO "CommandType=%s, Address=%s(0x%02X,0x%02X), "
139 "length=%d\n", get_ctype_string(CmdFrm->ctype), 123 "opcode=%s(0x%02X), length=%d\n",
124 get_ctype_string(CmdFrm->ctype),
140 get_subunit_address(CmdFrm->suid, CmdFrm->sutyp), 125 get_subunit_address(CmdFrm->suid, CmdFrm->sutyp),
141 CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode), 126 CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode),
142 CmdFrm->opcode, CmdFrm->length); 127 CmdFrm->opcode, CmdFrm->length);
143 for(k = 0; k < CmdFrm->length - 3; k++) { 128 if (avc_comm_debug > 1) {
144 if (k % 5 != 0) 129 for(k = 0; k < CmdFrm->length - 3; k++) {
145 printk(", "); 130 if (k % 5 != 0)
146 else if (k != 0) 131 printk(", ");
147 printk("\n"); 132 else if (k != 0)
148 printk("operand[%d] = %02X", k, CmdFrm->operand[k]); 133 printk("\n");
134 printk(KERN_INFO "operand[%d] = %02X", k,
135 CmdFrm->operand[k]);
136 }
137 printk(KERN_INFO "\n");
149 } 138 }
150 printk("\n");
151} 139}
152 140
153static void log_response_frame(const AVCRspFrm *RspFrm) 141static void log_response_frame(const AVCRspFrm *RspFrm)
154{ 142{
155 int k; 143 int k;
156 printk(KERN_INFO "AV/C Response Frame:\n"); 144 printk(KERN_INFO "AV/C Response Frame:\n");
157 printk("Response=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " 145 printk(KERN_INFO "Response=%s, Address=%s(0x%02X,0x%02X), "
158 "length=%d\n", get_resp_string(RspFrm->resp), 146 "opcode=%s(0x%02X), length=%d\n", get_resp_string(RspFrm->resp),
159 get_subunit_address(RspFrm->suid, RspFrm->sutyp), 147 get_subunit_address(RspFrm->suid, RspFrm->sutyp),
160 RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode), 148 RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode),
161 RspFrm->opcode, RspFrm->length); 149 RspFrm->opcode, RspFrm->length);
162 for(k = 0; k < RspFrm->length - 3; k++) { 150 if (avc_comm_debug > 1) {
163 if (k % 5 != 0) 151 for(k = 0; k < RspFrm->length - 3; k++) {
164 printk(", "); 152 if (k % 5 != 0)
165 else if (k != 0) 153 printk(KERN_INFO ", ");
166 printk("\n"); 154 else if (k != 0)
167 printk("operand[%d] = %02X", k, RspFrm->operand[k]); 155 printk(KERN_INFO "\n");
156 printk(KERN_INFO "operand[%d] = %02X", k,
157 RspFrm->operand[k]);
158 }
159 printk(KERN_INFO "\n");
168 } 160 }
169 printk("\n");
170} 161}
171 162
172static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, 163static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm,
173 AVCRspFrm *RspFrm) { 164 AVCRspFrm *RspFrm) {
174 struct hpsb_packet *packet; 165 struct hpsb_packet *packet;
175 struct node_entry *ne; 166 struct node_entry *ne;
167 int num_tries = 0;
168 int packet_ok = 0;
176 169
177 ne = firesat->nodeentry; 170 ne = firesat->nodeentry;
178 if(!ne) { 171 if(!ne) {
179 printk("%s: lost node!\n",__func__); 172 printk(KERN_ERR "%s: lost node!\n",__func__);
180 return -EIO; 173 return -EIO;
181 } 174 }
182 175
183 /* need all input data */ 176 /* need all input data */
184 if(!firesat || !ne || !CmdFrm) { 177 if(!firesat || !ne || !CmdFrm) {
185 printk("%s: missing input data!\n",__func__); 178 printk(KERN_ERR "%s: missing input data!\n",__func__);
186 return -EINVAL; 179 return -EINVAL;
187 } 180 }
188 181
189 if (avc_comm_debug == 1) { 182 if (avc_comm_debug > 0) {
190 log_command_frame(CmdFrm); 183 log_command_frame(CmdFrm);
191 } 184 }
192 185
193 if(RspFrm) 186 if(RspFrm)
194 atomic_set(&firesat->avc_reply_received, 0); 187 atomic_set(&firesat->avc_reply_received, 0);
195 188
196 packet=hpsb_make_writepacket(ne->host, ne->nodeid, 189 while (packet_ok == 0 && num_tries < 6) {
197 COMMAND_REGISTER, 190 num_tries++;
198 (quadlet_t*)CmdFrm, 191 packet_ok = 1;
199 CmdFrm->length); 192 packet = hpsb_make_writepacket(ne->host, ne->nodeid,
200 hpsb_set_packet_complete_task(packet, 193 COMMAND_REGISTER,
201 (void (*)(void*))avc_free_packet, 194 (quadlet_t*)CmdFrm,
202 packet); 195 CmdFrm->length);
203 hpsb_node_fill_packet(ne, packet); 196 hpsb_set_packet_complete_task(packet,
204 197 (void (*)(void*))avc_free_packet,
205 if (hpsb_send_packet(packet) < 0) { 198 packet);
206 avc_free_packet(packet); 199 hpsb_node_fill_packet(ne, packet);
207 atomic_set(&firesat->avc_reply_received, 1); 200
208 printk("%s: send failed!\n",__func__); 201 if (hpsb_send_packet(packet) < 0) {
209 return -EIO; 202 avc_free_packet(packet);
210 }
211
212 if(RspFrm) {
213 // AV/C specs say that answers should be send within
214 // 150 ms so let's time out after 200 ms
215 if(avc_down_timeout(&firesat->avc_reply_received,
216 HZ / 5)) {
217 printk("%s: timeout waiting for avc response\n",
218 __func__);
219 atomic_set(&firesat->avc_reply_received, 1); 203 atomic_set(&firesat->avc_reply_received, 1);
220 return -ETIMEDOUT; 204 printk(KERN_ERR "%s: send failed!\n",__func__);
205 return -EIO;
221 } 206 }
222 memcpy(RspFrm, firesat->respfrm, 207
223 firesat->resp_length); 208 if(RspFrm) {
224 RspFrm->length = firesat->resp_length; 209 // AV/C specs say that answers should be send within
225 if (avc_comm_debug == 1) { 210 // 150 ms so let's time out after 200 ms
226 log_response_frame(RspFrm); 211 if (wait_event_timeout(firesat->avc_wait,
212 atomic_read(&firesat->avc_reply_received) == 1,
213 HZ / 5) == 0) {
214 packet_ok = 0;
215 }
216 else {
217 memcpy(RspFrm, firesat->respfrm,
218 firesat->resp_length);
219 RspFrm->length = firesat->resp_length;
220 if (avc_comm_debug > 0) {
221 log_response_frame(RspFrm);
222 }
223 }
227 } 224 }
228 } 225 }
226 if (packet_ok == 0) {
227 printk(KERN_ERR "%s: AV/C response timed out 6 times.\n",
228 __func__);
229 return -ETIMEDOUT;
230 }
229 231
230 return 0; 232 return 0;
231} 233}
@@ -292,7 +294,8 @@ int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
292 } 294 }
293#endif 295#endif
294 if(atomic_read(&firesat->avc_reply_received) == 1) { 296 if(atomic_read(&firesat->avc_reply_received) == 1) {
295 printk("%s: received out-of-order AVC response, ignored\n",__func__); 297 printk(KERN_ERR "%s: received out-of-order AVC response, "
298 "ignored\n",__func__);
296 return -EINVAL; 299 return -EINVAL;
297 } 300 }
298// AVCRspFrm *resp=(AVCRspFrm *)data; 301// AVCRspFrm *resp=(AVCRspFrm *)data;
@@ -312,6 +315,7 @@ int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
312 firesat->resp_length=length; 315 firesat->resp_length=length;
313 316
314 atomic_set(&firesat->avc_reply_received, 1); 317 atomic_set(&firesat->avc_reply_received, 1);
318 wake_up(&firesat->avc_wait);
315 319
316 return 0; 320 return 0;
317} 321}
@@ -740,11 +744,12 @@ int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *tr
740 return -EIO; 744 return -EIO;
741 745
742 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { 746 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
743 printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp); 747 printk(KERN_ERR "%s: AVCWrite returned error code %d\n",
748 __func__, RspFrm.resp);
744 return -EINVAL; 749 return -EINVAL;
745 } 750 }
746 if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) { 751 if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) {
747 printk("%s: Invalid response length\n",__func__); 752 printk(KERN_ERR "%s: Invalid response length\n", __func__);
748 return -EINVAL; 753 return -EINVAL;
749 } 754 }
750 if(systemId) 755 if(systemId)
@@ -777,7 +782,8 @@ int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_in
777 return -EIO; 782 return -EIO;
778 783
779 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { 784 if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
780 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); 785 printk(KERN_ERR "%s: AVCWrite returned code %d\n",
786 __func__, RspFrm.resp);
781 return -EINVAL; 787 return -EINVAL;
782 } 788 }
783 789
@@ -788,7 +794,8 @@ int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_in
788 sizeof(ANTENNA_INPUT_INFO)); 794 sizeof(ANTENNA_INPUT_INFO));
789 return 0; 795 return 0;
790 } 796 }
791 printk("%s: invalid info returned from AVC\n",__func__); 797 printk(KERN_ERR "%s: invalid tuner status (op=%d,length=%d) returned "
798 "from AVC\n", __func__, RspFrm.operand[1], length);
792 return -EINVAL; 799 return -EINVAL;
793} 800}
794 801
@@ -800,7 +807,8 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
800 AVCRspFrm RspFrm; 807 AVCRspFrm RspFrm;
801 int i,j; 808 int i,j;
802 809
803 printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone); 810 printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",
811 __func__, voltage, burst, conttone);
804 812
805 memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); 813 memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
806 814
@@ -822,11 +830,13 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
822 830
823 for(j=0;j<nrdiseq;j++) { 831 for(j=0;j<nrdiseq;j++) {
824 int k; 832 int k;
825 printk(KERN_INFO "%s: diseq %d len %x\n",__func__,j,diseqcmd[j].msg_len); 833 printk(KERN_INFO "%s: diseq %d len %x\n",
834 __func__, j, diseqcmd[j].msg_len);
826 CmdFrm.operand[i++]=diseqcmd[j].msg_len; 835 CmdFrm.operand[i++]=diseqcmd[j].msg_len;
827 836
828 for(k=0;k<diseqcmd[j].msg_len;k++) { 837 for(k=0;k<diseqcmd[j].msg_len;k++) {
829 printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",__func__,j,k,diseqcmd[j].msg[k]); 838 printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",
839 __func__, j, k, diseqcmd[j].msg[k]);
830 CmdFrm.operand[i++]=diseqcmd[j].msg[k]; 840 CmdFrm.operand[i++]=diseqcmd[j].msg[k];
831 } 841 }
832 } 842 }
@@ -847,7 +857,8 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
847 return -EIO; 857 return -EIO;
848 858
849 if(RspFrm.resp != ACCEPTED) { 859 if(RspFrm.resp != ACCEPTED) {
850 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); 860 printk(KERN_ERR "%s: AVCWrite returned code %d\n",
861 __func__, RspFrm.resp);
851 return -EINVAL; 862 return -EINVAL;
852 } 863 }
853 864
@@ -879,7 +890,8 @@ int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount)
879 return -EIO; 890 return -EIO;
880 891
881 if(RspFrm.resp != STABLE) { 892 if(RspFrm.resp != STABLE) {
882 printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); 893 printk(KERN_ERR "%s: AVCWrite returned code %d\n",
894 __func__, RspFrm.resp);
883 return -EINVAL; 895 return -EINVAL;
884 } 896 }
885 897
@@ -1100,9 +1112,10 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length)
1100 CmdFrm.opcode = VENDOR; 1112 CmdFrm.opcode = VENDOR;
1101 1113
1102 if (msg[0] != LIST_MANAGEMENT_ONLY) { 1114 if (msg[0] != LIST_MANAGEMENT_ONLY) {
1103 printk(KERN_ERR "The only list_manasgement parameter that is " 1115 printk(KERN_INFO "%s: list_management %d not support. "
1104 "supported by the firesat driver is \"only\" (3)."); 1116 "Forcing list_management to \"only\" (3). \n",
1105 return -EFAULT; 1117 __func__, msg[0]);
1118 msg[0] = LIST_MANAGEMENT_ONLY;
1106 } 1119 }
1107 // We take the cmd_id from the programme level only! 1120 // We take the cmd_id from the programme level only!
1108 list_management = msg[0]; 1121 list_management = msg[0];
diff --git a/drivers/media/dvb/firesat/firesat.h b/drivers/media/dvb/firesat/firesat.h
index 1beed177d98b..f0bac244783a 100644
--- a/drivers/media/dvb/firesat/firesat.h
+++ b/drivers/media/dvb/firesat/firesat.h
@@ -140,6 +140,7 @@ struct firesat {
140 int ca_time_interval; 140 int ca_time_interval;
141 141
142 struct semaphore avc_sem; 142 struct semaphore avc_sem;
143 wait_queue_head_t avc_wait;
143 atomic_t avc_reply_received; 144 atomic_t avc_reply_received;
144 145
145 atomic_t reschedule_remotecontrol; 146 atomic_t reschedule_remotecontrol;
diff --git a/drivers/media/dvb/firesat/firesat_1394.c b/drivers/media/dvb/firesat/firesat_1394.c
index 04ad31666fb9..b19e59416b59 100644
--- a/drivers/media/dvb/firesat/firesat_1394.c
+++ b/drivers/media/dvb/firesat/firesat_1394.c
@@ -208,6 +208,7 @@ static int firesat_probe(struct device *dev)
208 } 208 }
209 209
210 sema_init(&firesat->avc_sem, 1); 210 sema_init(&firesat->avc_sem, 1);
211 init_waitqueue_head(&firesat->avc_wait);
211 atomic_set(&firesat->avc_reply_received, 1); 212 atomic_set(&firesat->avc_reply_received, 1);
212 sema_init(&firesat->demux_sem, 1); 213 sema_init(&firesat->demux_sem, 1);
213 atomic_set(&firesat->reschedule_remotecontrol, 0); 214 atomic_set(&firesat->reschedule_remotecontrol, 0);