Date: Sun, 24 Aug 2008 15:20:07 +0200 From: Henrik Kurelid Subject: 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 Signed-off-by: Stefan Richter --- drivers/media/dvb/firesat/avc_api.c | 171 ++++++++++++----------- drivers/media/dvb/firesat/firesat.h | 1 drivers/media/dvb/firesat/firesat_1394.c | 1 3 files changed, 94 insertions(+), 79 deletions(-) Index: linux/drivers/media/dvb/firesat/avc_api.c =================================================================== --- linux.orig/drivers/media/dvb/firesat/avc_api.c +++ linux/drivers/media/dvb/firesat/avc_api.c @@ -26,7 +26,7 @@ static unsigned int avc_comm_debug = 0; module_param(avc_comm_debug, int, 0644); -MODULE_PARM_DESC(avc_comm_debug, "debug logging of AV/C communication, default is 0 (no)"); +MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)"); static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal); @@ -37,22 +37,6 @@ static void avc_free_packet(struct hpsb_ hpsb_free_packet(packet); } -/* - * Goofy routine that basically does a down_timeout function. - * Stolen from sbp2.c - */ -static int avc_down_timeout(atomic_t *done, int timeout) -{ - int i; - - for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) { - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(HZ/10)) /* 100ms */ - return(1); - } - return ((i > 0) ? 0:1); -} - static const char* get_ctype_string(__u8 ctype) { switch(ctype) @@ -135,97 +119,115 @@ static void log_command_frame(const AVCC { int k; printk(KERN_INFO "AV/C Command Frame:\n"); - printk("CommandType=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " - "length=%d\n", get_ctype_string(CmdFrm->ctype), + printk(KERN_INFO "CommandType=%s, Address=%s(0x%02X,0x%02X), " + "opcode=%s(0x%02X), length=%d\n", + get_ctype_string(CmdFrm->ctype), get_subunit_address(CmdFrm->suid, CmdFrm->sutyp), CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode), CmdFrm->opcode, CmdFrm->length); - for(k = 0; k < CmdFrm->length - 3; k++) { - if (k % 5 != 0) - printk(", "); - else if (k != 0) - printk("\n"); - printk("operand[%d] = %02X", k, CmdFrm->operand[k]); + if (avc_comm_debug > 1) { + for(k = 0; k < CmdFrm->length - 3; k++) { + if (k % 5 != 0) + printk(", "); + else if (k != 0) + printk("\n"); + printk(KERN_INFO "operand[%d] = %02X", k, + CmdFrm->operand[k]); + } + printk(KERN_INFO "\n"); } - printk("\n"); } static void log_response_frame(const AVCRspFrm *RspFrm) { int k; printk(KERN_INFO "AV/C Response Frame:\n"); - printk("Response=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " - "length=%d\n", get_resp_string(RspFrm->resp), + printk(KERN_INFO "Response=%s, Address=%s(0x%02X,0x%02X), " + "opcode=%s(0x%02X), length=%d\n", get_resp_string(RspFrm->resp), get_subunit_address(RspFrm->suid, RspFrm->sutyp), RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode), RspFrm->opcode, RspFrm->length); - for(k = 0; k < RspFrm->length - 3; k++) { - if (k % 5 != 0) - printk(", "); - else if (k != 0) - printk("\n"); - printk("operand[%d] = %02X", k, RspFrm->operand[k]); + if (avc_comm_debug > 1) { + for(k = 0; k < RspFrm->length - 3; k++) { + if (k % 5 != 0) + printk(KERN_INFO ", "); + else if (k != 0) + printk(KERN_INFO "\n"); + printk(KERN_INFO "operand[%d] = %02X", k, + RspFrm->operand[k]); + } + printk(KERN_INFO "\n"); } - printk("\n"); } static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) { struct hpsb_packet *packet; struct node_entry *ne; + int num_tries = 0; + int packet_ok = 0; ne = firesat->nodeentry; if(!ne) { - printk("%s: lost node!\n",__func__); + printk(KERN_ERR "%s: lost node!\n",__func__); return -EIO; } /* need all input data */ if(!firesat || !ne || !CmdFrm) { - printk("%s: missing input data!\n",__func__); + printk(KERN_ERR "%s: missing input data!\n",__func__); return -EINVAL; } - if (avc_comm_debug == 1) { + if (avc_comm_debug > 0) { log_command_frame(CmdFrm); } if(RspFrm) atomic_set(&firesat->avc_reply_received, 0); - packet=hpsb_make_writepacket(ne->host, ne->nodeid, - COMMAND_REGISTER, - (quadlet_t*)CmdFrm, - CmdFrm->length); - hpsb_set_packet_complete_task(packet, - (void (*)(void*))avc_free_packet, - packet); - hpsb_node_fill_packet(ne, packet); - - if (hpsb_send_packet(packet) < 0) { - avc_free_packet(packet); - atomic_set(&firesat->avc_reply_received, 1); - printk("%s: send failed!\n",__func__); - return -EIO; - } + while (packet_ok == 0 && num_tries < 6) { + num_tries++; + packet_ok = 1; + packet = hpsb_make_writepacket(ne->host, ne->nodeid, + COMMAND_REGISTER, + (quadlet_t*)CmdFrm, + CmdFrm->length); + hpsb_set_packet_complete_task(packet, + (void (*)(void*))avc_free_packet, + packet); + hpsb_node_fill_packet(ne, packet); - if(RspFrm) { - // AV/C specs say that answers should be send within - // 150 ms so let's time out after 200 ms - if(avc_down_timeout(&firesat->avc_reply_received, - HZ / 5)) { - printk("%s: timeout waiting for avc response\n", - __func__); + if (hpsb_send_packet(packet) < 0) { + avc_free_packet(packet); atomic_set(&firesat->avc_reply_received, 1); - return -ETIMEDOUT; + printk(KERN_ERR "%s: send failed!\n",__func__); + return -EIO; } - memcpy(RspFrm, firesat->respfrm, - firesat->resp_length); - RspFrm->length = firesat->resp_length; - if (avc_comm_debug == 1) { - log_response_frame(RspFrm); + + if(RspFrm) { + // AV/C specs say that answers should be send within + // 150 ms so let's time out after 200 ms + if (wait_event_timeout(firesat->avc_wait, + atomic_read(&firesat->avc_reply_received) == 1, + HZ / 5) == 0) { + packet_ok = 0; + } + else { + memcpy(RspFrm, firesat->respfrm, + firesat->resp_length); + RspFrm->length = firesat->resp_length; + if (avc_comm_debug > 0) { + log_response_frame(RspFrm); + } + } } } + if (packet_ok == 0) { + printk(KERN_ERR "%s: AV/C response timed out 6 times.\n", + __func__); + return -ETIMEDOUT; + } return 0; } @@ -292,7 +294,8 @@ int AVCRecv(struct firesat *firesat, u8 } #endif if(atomic_read(&firesat->avc_reply_received) == 1) { - printk("%s: received out-of-order AVC response, ignored\n",__func__); + printk(KERN_ERR "%s: received out-of-order AVC response, " + "ignored\n",__func__); return -EINVAL; } // AVCRspFrm *resp=(AVCRspFrm *)data; @@ -312,6 +315,7 @@ int AVCRecv(struct firesat *firesat, u8 firesat->resp_length=length; atomic_set(&firesat->avc_reply_received, 1); + wake_up(&firesat->avc_wait); return 0; } @@ -740,11 +744,12 @@ int AVCIdentifySubunit(struct firesat *f return -EIO; if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { - printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp); + printk(KERN_ERR "%s: AVCWrite returned error code %d\n", + __func__, RspFrm.resp); return -EINVAL; } if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) { - printk("%s: Invalid response length\n",__func__); + printk(KERN_ERR "%s: Invalid response length\n", __func__); return -EINVAL; } if(systemId) @@ -777,7 +782,8 @@ int AVCTunerStatus(struct firesat *fires return -EIO; if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { - printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); + printk(KERN_ERR "%s: AVCWrite returned code %d\n", + __func__, RspFrm.resp); return -EINVAL; } @@ -788,7 +794,8 @@ int AVCTunerStatus(struct firesat *fires sizeof(ANTENNA_INPUT_INFO)); return 0; } - printk("%s: invalid info returned from AVC\n",__func__); + printk(KERN_ERR "%s: invalid tuner status (op=%d,length=%d) returned " + "from AVC\n", __func__, RspFrm.operand[1], length); return -EINVAL; } @@ -800,7 +807,8 @@ int AVCLNBControl(struct firesat *firesa AVCRspFrm RspFrm; int i,j; - printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone); + printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n", + __func__, voltage, burst, conttone); memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); @@ -822,11 +830,13 @@ int AVCLNBControl(struct firesat *firesa for(j=0;javc_sem, 1); + init_waitqueue_head(&firesat->avc_wait); atomic_set(&firesat->avc_reply_received, 1); sema_init(&firesat->demux_sem, 1); atomic_set(&firesat->reschedule_remotecontrol, 0);