From patchwork Sun Jul 12 17:42:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 6772881 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id F2C13C05AD for ; Sun, 12 Jul 2015 17:53:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9B3E2047D for ; Sun, 12 Jul 2015 17:53:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7C2BF204AF for ; Sun, 12 Jul 2015 17:53:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751258AbbGLRmg (ORCPT ); Sun, 12 Jul 2015 13:42:36 -0400 Received: from mout.gmx.net ([212.227.17.20]:61556 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750954AbbGLRmf (ORCPT ); Sun, 12 Jul 2015 13:42:35 -0400 Received: from localhost.localdomain ([80.187.111.32]) by mail.gmx.com (mrgmx102) with ESMTPSA (Nemesis) id 0LfHs4-1YcnVn1i4O-00om7u; Sun, 12 Jul 2015 19:42:24 +0200 From: Oleksij Rempel To: ath9k-devel@qca.qualcomm.com, kvalo@codeaurora.org, linux-wireless@vger.kernel.org Cc: Oleksij Rempel Subject: [PATCH v3] ath9k_htc: introduce support for different fw versions Date: Sun, 12 Jul 2015 19:42:06 +0200 Message-Id: <1436722926-17562-1-git-send-email-linux@rempel-privat.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <87oajhvaca.fsf@kamboji.qca.qualcomm.com> References: <87oajhvaca.fsf@kamboji.qca.qualcomm.com> MIME-Version: 1.0 X-Provags-ID: V03:K0:bgsVWrOlxqKRsibw2w1PyP2H+cS+lU3CRsTgBvYEajwAMUg9fXj q8Jynf6nQLK4GHjhZb/ymi6/v9io9hydhAUHL/1H1qfgiTjJWnyuqkViTjoH/V8Ym18KhRk 3KDJxK7K/KwVDmpbQsrD48Hm2UaerJKeYw0VGbwHvt4ic9lqBKnGqIx2XMeGDdZ5JTvEFV6 jBBqsLoI/eBDQHcADl/6g== X-UI-Out-Filterresults: notjunk:1; V01:K0:0uu/U/fwrOo=:5IoOLQeyuCOTNu8mdlbp2J sO1t7+MB3JLi8Odl6YyTm84ikrj7Tfok93EVBrVRuZqa/81XM5KQ7RremfRP0f1oCumyaU8hQ dRrr36snh2klYBQPHGSMlc+I3mZL45rzst3yZkTNq50mLjtZ7puIPwkqJCVN4T8pWqyteQfjG Ax/4nb+d+ycNI+4li7crdwdPvUs9js+PfE84djStuPkL38qbYs5PGHoeFPELImmVR2Sjw0bwZ ysBeqEyMHsAuwFomtnPebbPutwh10+j+/EHRidPmRxwCMoULVL3Gdbrl6Ngxe6RpMXUhjF6/p fFG8pJcs3lyBbhO8FVqrKr6qN9LvyMhg1ZEY6MmJyLf+UNNWbhPc6BShDbH09u7COg8VE/4CL 4UqEf+M+hSnqIIcdTqczTbu6KLBkyiXlZWftet+q7le5qkCuxCo43UIKDaQyjNI/002sNJlkI RXpPsiLViHU0IAaXinQz4TMiWOeFOC6O1LZrEJ2iAGc4inUFWlFDysDMCF97ww8Mwrt4jQRe4 WbQ0R5fAfuspwGQEVBnzmUleQkhOqsCyuzJp8c1qjln8xE/Gyq4tlckDp2mxTleqQFNzYmTYi y9mgBnTR/L4bwe+NjPS1fcvVO21h9/dSx6S6X7ack0FXgWXYECkJnWWvli6OOQAiGDKGX6D5g ne7Seg1/TzvL0/aJPs4ngson+YmX8eMZkhLXU6U7dJzMqU7SCkmp2jIi2sfOOUcG6XT0= Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current kernel support only one fw name with theoretically only one fw version located in “firmware/htc_[9271|7010].fw”. Which is ok so far we have only one fw version (1.3). After we realised new fw 1.4, we faced compatibility problem which was decided to solve by firmware name and location: - new firmware is located now in firmware/ath9k_htc/htc_[9271|7010]-1.4.0.fw - old version 1.3 should be on old place, so old kernel have no issues with it. - new kernels including this patch should be able to try different supported (min..max) fw version. - new kernel should be able to support old fw location too. At least for now. At same time this patch will add new module option which should allow user to play with development fw version without replacing stable one. If user will set “ath9k_htc use_dev_fw=1” module will try to find firmware/ath9k_htc/htc_[9271|7010]-1.dev.0.fw first and if it fails, use stable version: for example...1.4.0.fw. Signed-off-by: Oleksij Rempel --- drivers/net/wireless/ath/ath9k/hif_usb.c | 106 ++++++++++++++++++++------ drivers/net/wireless/ath/ath9k/hif_usb.h | 21 ++++- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 4 + 3 files changed, 105 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 10c02f5..165dd20 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,12 +17,8 @@ #include #include "htc.h" -/* identify firmware images */ -#define FIRMWARE_AR7010_1_1 "htc_7010.fw" -#define FIRMWARE_AR9271 "htc_9271.fw" - -MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); -MODULE_FIRMWARE(FIRMWARE_AR9271); +MODULE_FIRMWARE(HTC_7010_MODULE_FW); +MODULE_FIRMWARE(HTC_9271_MODULE_FW); static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ @@ -1080,12 +1076,88 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) device_unlock(parent); } +static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context); + +/* taken from iwlwifi */ +static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + bool first) +{ + char index[8], *chip; + int ret; + + if (first) { + if (htc_use_dev_fw) { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1; + sprintf(index, "%s", "dev"); + } else { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + } else { + hif_dev->fw_minor_index--; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + + /* test for FW 1.3 */ + if (MAJOR_VERSION_REQ == 1 && hif_dev->fw_minor_index == 3) { + const char *filename; + + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + filename = FIRMWARE_AR7010_1_1; + else + filename = FIRMWARE_AR9271; + + /* expected fw locations: + * - htc_9271.fw (stable version 1.3, depricated) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s", filename); + + } else if (hif_dev->fw_minor_index < FIRMWARE_MINOR_IDX_MIN) { + dev_err(&hif_dev->udev->dev, "no suitable firmware found!\n"); + + return -ENOENT; + } else { + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + chip = "7010"; + else + chip = "9271"; + + /* expected fw locations: + * - ath9k_htc/htc_9271-1.dev.0.fw (development version) + * - ath9k_htc/htc_9271-1.4.0.fw (stable version) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s/htc_%s-%d.%s.0.fw", HTC_FW_PATH, + chip, MAJOR_VERSION_REQ, index); + } + + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); + return ret; + } + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + + return ret; +} + static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) { struct hif_device_usb *hif_dev = context; int ret; if (!fw) { + ret = ath9k_hif_request_firmware(hif_dev, false); + if (!ret) + return; + dev_err(&hif_dev->udev->dev, "ath9k_htc: Failed to get firmware %s\n", hif_dev->fw_name); @@ -1215,27 +1287,11 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, init_completion(&hif_dev->fw_done); - /* Find out which firmware to load */ - - if (IS_AR7010_DEVICE(id->driver_info)) - hif_dev->fw_name = FIRMWARE_AR7010_1_1; - else - hif_dev->fw_name = FIRMWARE_AR9271; - - ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, - &hif_dev->udev->dev, GFP_KERNEL, - hif_dev, ath9k_hif_usb_firmware_cb); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Async request for firmware %s failed\n", - hif_dev->fw_name); + ret = ath9k_hif_request_firmware(hif_dev, true); + if (ret) goto err_fw_req; - } - dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", - hif_dev->fw_name); - - return 0; + return ret; err_fw_req: usb_set_intfdata(interface, NULL); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 51496e7..7c2ef7e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,8 +17,26 @@ #ifndef HTC_USB_H #define HTC_USB_H +/* old firmware images */ +#define FIRMWARE_AR7010_1_1 "htc_7010.fw" +#define FIRMWARE_AR9271 "htc_9271.fw" + +/* supported Major FW version */ #define MAJOR_VERSION_REQ 1 #define MINOR_VERSION_REQ 3 +/* minimal and maximal supported Minor FW version. */ +#define FIRMWARE_MINOR_IDX_MAX 4 +#define FIRMWARE_MINOR_IDX_MIN 3 +#define HTC_FW_PATH "ath9k_htc" + +#define HTC_9271_MODULE_FW HTC_FW_PATH "/htc_9271-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" +#define HTC_7010_MODULE_FW HTC_FW_PATH "/htc_7010-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" + +extern int htc_use_dev_fw; #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) @@ -101,7 +119,8 @@ struct hif_device_usb { struct usb_anchor reg_in_submitted; struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; - const char *fw_name; + char fw_name[32]; + int fw_minor_index; int rx_remain_len; int rx_pkt_len; int rx_transfer_len; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 7468562..57ca9b6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -38,6 +38,10 @@ static int ath9k_ps_enable; module_param_named(ps_enable, ath9k_ps_enable, int, 0444); MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); +int htc_use_dev_fw = 0; +module_param_named(use_dev_fw, htc_use_dev_fw, int, 0444); +MODULE_PARM_DESC(use_dev_fw, "Use development FW version"); + #ifdef CONFIG_MAC80211_LEDS int ath9k_htc_led_blink = 1; module_param_named(blink, ath9k_htc_led_blink, int, 0444);