From patchwork Fri Mar 21 11:09:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 3872921 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id EFF5EBF540 for ; Fri, 21 Mar 2014 11:21:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1EFC12025B for ; Fri, 21 Mar 2014 11:21:39 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id A2076201FD for ; Fri, 21 Mar 2014 11:21:33 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 7811526552B; Fri, 21 Mar 2014 12:21:32 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 225C3265531; Fri, 21 Mar 2014 12:14:29 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id C286E265479; Fri, 21 Mar 2014 12:14:27 +0100 (CET) Received: from smtp310.phy.lolipop.jp (smtp310.phy.lolipop.jp [210.157.22.78]) by alsa0.perex.cz (Postfix) with ESMTP id 88CAE265472 for ; Fri, 21 Mar 2014 12:11:09 +0100 (CET) Received: from smtp310.phy.lolipop.lan (HELO smtp310.phy.lolipop.jp) (172.17.1.10) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp310.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Fri, 21 Mar 2014 20:11:08 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp310.phy.lolipop.jp (LOLIPOP-Fsecure); Fri, 21 Mar 2014 20:10:36 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de, perex@perex.cz Date: Fri, 21 Mar 2014 20:09:59 +0900 Message-Id: <1395400229-22957-15-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395400229-22957-1-git-send-email-o-takashi@sakamocchi.jp> References: <1395400229-22957-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, linux1394-devel@lists.sourceforge.net, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 14/44] firewire-lib: Add support for deferred transaction X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Some devices based on BeBoB use this type of AV/C transaction. 'Deferred Transaction' is defined in 'AV/C Digital Interface Command Set General Specification' and is used by targets to make a response deferred during processing it. If a target may not be able to complete a command within 100msec since receiving the command, then the target shall return INTERIM response, to which final response will follow later. CONTROL/NOTIFY commands are allowed for deferred transaction. In the specification, devices allow to send INTERIM response just one time. But this commit allows to handle several INTERIM response with two reasons. One reason is to simplify codes, and another reason is to prepare for devices which is out of specification. There is an issue. In the specification, the interval between INTERIM response and final response is 'Unspecified interval'. The specification depends on each subunit specification for this interval. But we promise to finish this function for caller. In this reason, I use FCP_TIMEOUT_MS for this interval. Currently it's 125msec. When we find devices which needs more time for this interval, then let us add some codes to apply more interval for 'undefined interval'. Signed-off-by: Takashi Sakamoto --- sound/firewire/fcp.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c index 860c080..6876bfa 100644 --- a/sound/firewire/fcp.c +++ b/sound/firewire/fcp.c @@ -30,6 +30,7 @@ enum fcp_state { STATE_PENDING, STATE_BUS_RESET, STATE_COMPLETE, + STATE_DEFERRED, }; struct fcp_transaction { @@ -40,6 +41,7 @@ struct fcp_transaction { unsigned int response_match_bytes; enum fcp_state state; wait_queue_head_t wait; + bool deferrable; }; /** @@ -81,6 +83,9 @@ int fcp_avc_transaction(struct fw_unit *unit, t.state = STATE_PENDING; init_waitqueue_head(&t.wait); + if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03) + t.deferrable = true; + spin_lock_irq(&transactions_lock); list_add_tail(&t.list, &transactions); spin_unlock_irq(&transactions_lock); @@ -93,11 +98,21 @@ int fcp_avc_transaction(struct fw_unit *unit, (void *)command, command_size, 0); if (ret < 0) break; - +deferred: wait_event_timeout(t.wait, t.state != STATE_PENDING, msecs_to_jiffies(FCP_TIMEOUT_MS)); - if (t.state == STATE_COMPLETE) { + if (t.state == STATE_DEFERRED) { + /* + * 'AV/C General Specification' define no time limit + * on command completion once an INTERIM response has + * been sent. but we promise to finish this function + * for a caller. Here we use FCP_TIMEOUT_MS for next + * interval. This is not in the specification. + */ + t.state = STATE_PENDING; + goto deferred; + } else if (t.state == STATE_COMPLETE) { ret = t.response_size; break; } else if (t.state == STATE_BUS_RESET) { @@ -132,7 +147,8 @@ void fcp_bus_reset(struct fw_unit *unit) spin_lock_irq(&transactions_lock); list_for_each_entry(t, &transactions, list) { if (t->unit == unit && - t->state == STATE_PENDING) { + (t->state == STATE_PENDING || + t->state == STATE_DEFERRED)) { t->state = STATE_BUS_RESET; wake_up(&t->wait); } @@ -186,10 +202,15 @@ static void fcp_response(struct fw_card *card, struct fw_request *request, if (t->state == STATE_PENDING && is_matching_response(t, data, length)) { - t->state = STATE_COMPLETE; - t->response_size = min((unsigned int)length, - t->response_size); - memcpy(t->response_buffer, data, t->response_size); + if (t->deferrable && *(const u8 *)data == 0x0f) { + t->state = STATE_DEFERRED; + } else { + t->state = STATE_COMPLETE; + t->response_size = min_t(unsigned int, length, + t->response_size); + memcpy(t->response_buffer, data, + t->response_size); + } wake_up(&t->wait); } }