Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: kbuild test robot @ 2017-01-14 21:37 UTC (permalink / raw)
  To: Matt Ranostay
  Cc: kbuild-all, linux-wireless, linux-kernel, linux-mmc, devicetree,
	tony, Matt Ranostay, Ulf Hansson
In-Reply-To: <20170113052218.10534-3-matt@ranostay.consulting>

[-- Attachment #1: Type: text/plain, Size: 895 bytes --]

Hi Matt,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc3 next-20170113]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Matt-Ranostay/mmc-pwrseq-add-support-for-Marvell-SD8787-chip/20170115-030459
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

>> make[4]: *** No rule to make target 'drivers/mmc/core/pwrseq_sd8787.c', needed by 'drivers/mmc/core/pwrseq_sd8787.o'.
   make[4]: Target '__build' not remade because of errors.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57927 bytes --]

^ permalink raw reply

* support for Ampak AP6255 (bcm43455c0 with SDIO device ID 0xa9bf)
From: Martin Blumenstingl @ 2017-01-14 23:18 UTC (permalink / raw)
  To: brcm80211-dev-list.pdl; +Cc: arend.vanspriel, hante.meuleman, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 2343 bytes --]

Hello,

I recently got a "Khadas VIM Pro" (see [0] for more information)
The "Pro" version comes with an AP6255 wifi chipset.
Looking at the vendor firmware this seems to be a bcm43455 device: [1]

To my surprise brcmfmac from a mainline 4.10-rc3 kernel did not pick
this device up.
So I started investigating:
$ grep "" /sys/class/mmc_host/mmc2/mmc2\:0001/mmc2\:0001\:*/{class,device,vendor}
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/class:0x00
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/class:0x00
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/class:0x02
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/vendor:0x02d0
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/vendor:0x02d0
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/vendor:0x02d0

I then went ahead and added the device ID to
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c (sample
patch attached)
as a result of that the device is now being detected.
it boots fine with the firmware found in linux-firmware: [2] (plus the
nvram.txt from the vendor repo [1] renamed to brcmfmac43455-sdio.txt)

$ cat /sys/kernel/debug/brcmfmac/mmc2\:0001\:1/revinfo
vendorid: 0x14e4
deviceid: 0x43ab
radiorev: 0.88.3.11
chipnum: 17221 (4345)
chiprev: 6
chippkg: 2
corerev: 54
boardid: 0x06e4
boardvendor: 0x14e4
boardrev: P304
driverrev: 7.45.18
ucoderev: 0
bus: 0
phytype: 11
phyrev: 20
anarev: 0
nvramrev: 00079ac5

downloading a random 100MB file from the internet using curl confirms this.
There are no hangs, connection drops, other devices are also working fine.

the problem I'm facing is very simply (but unfortunately a very common
development problem): naming things (the SDIO_DEVICE_ID_BROADCOM_TODO
constant)!
there's already a definition for SDIO_DEVICE_ID_BROADCOM_4345 with
value 0x4345, does that mean 0xa9bf should be
SDIO_DEVICE_ID_BROADCOM_43455?


Regards,
Martin


[0] http://khadas.com/vim/
[1] https://github.com/khadas/android_hardware_amlogic_wifi/tree/b6709758755568e4a0ff6e80993be0fc64c77fb9/bcm_ampak/config/6255
[2] https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/commit/brcm/brcmfmac43455-sdio.bin?id=b9a38d041d38ac6cf47274e9933f8083e12fc601

[-- Attachment #2: brmcfmac-sdio-0xa9bf.patch --]
[-- Type: text/x-patch, Size: 638 bytes --]

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 72139b579b18..7206bb1f9908 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -1106,6 +1106,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
+	BRCMF_SDIO_DEVICE(0xa9bf),
 	{ /* end: all zeroes */ }
 };
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);


^ permalink raw reply related

* Re: [PATCH 14/40] rt2x00: rt2800lib: add MAC register initialization for RT3883
From: kbuild test robot @ 2017-01-15  6:49 UTC (permalink / raw)
  To: Daniel Golle
  Cc: kbuild-all, linux-wireless, Johannes Berg, Stanislaw Gruszka,
	roman, michel.stempin, c.mignanti, evaxige, Kalle Valo,
	Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170113212510.GA3447@makrotopia.org>

[-- Attachment #1: Type: text/plain, Size: 14398 bytes --]

Hi Gabor,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on next-20170113]
[cannot apply to v4.10-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Daniel-Golle/rt2x00-patches-form-OpenWrt-org/20170115-102250
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: x86_64-allyesdebian (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Daniel-Golle/rt2x00-patches-form-OpenWrt-org/20170115-102250 HEAD 849367246e2b54e086e272ee2bd32b9983bc30fb builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_config_channel_rf3853':
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c:2734:2: error: implicit declaration of function 'rt2800_adjust_freq_offset' [-Werror=implicit-function-declaration]
     rt2800_adjust_freq_offset(rt2x00dev);
     ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_init_registers':
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5027:36: error: 'TX_TXBF_CFG_0' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
                                       ^~~~~~~~~~~~~
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5027:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5028:36: error: 'TX_TXBF_CFG_3' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
                                       ^~~~~~~~~~~~~
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5224:36: error: 'TX_FBK_CFG_3S_0' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
                                       ^~~~~~~~~~~~~~~
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5225:36: error: 'TX_FBK_CFG_3S_1' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
                                       ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/TX_TXBF_CFG_0 +5027 drivers/net/wireless/ralink/rt2x00/rt2800lib.c

  5021						      0x00000000);
  5022			}
  5023		} else if (rt2x00_rt(rt2x00dev, RT3883)) {
  5024			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
  5025			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
  5026			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
> 5027			rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
> 5028			rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
  5029		} else if (rt2x00_rt(rt2x00dev, RT5390) ||
  5030			   rt2x00_rt(rt2x00dev, RT5392)) {
  5031			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
  5032			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
  5033			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
  5034		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
  5035			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
  5036			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
  5037			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
  5038		} else {
  5039			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
  5040			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
  5041		}
  5042	
  5043		rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
  5044		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
  5045		rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
  5046		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
  5047		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
  5048		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
  5049		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
  5050		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
  5051		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
  5052		rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
  5053	
  5054		rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
  5055		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
  5056		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
  5057		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
  5058		rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
  5059	
  5060		rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
  5061		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
  5062		if (rt2x00_rt(rt2x00dev, RT3883)) {
  5063			drv_data->max_psdu = 3;
  5064			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 3);
  5065		} else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
  5066		    rt2x00_rt(rt2x00dev, RT2883) ||
  5067		    rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) {
  5068			drv_data->max_psdu = 2;
  5069			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
  5070		} else {
  5071			drv_data->max_psdu = 1;
  5072			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
  5073		}
  5074		rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 10);
  5075		rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 10);
  5076		rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
  5077	
  5078		rt2800_register_read(rt2x00dev, LED_CFG, &reg);
  5079		rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
  5080		rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
  5081		rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
  5082		rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
  5083		rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
  5084		rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
  5085		rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
  5086		rt2800_register_write(rt2x00dev, LED_CFG, reg);
  5087	
  5088		rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
  5089	
  5090		rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
  5091		rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);
  5092		rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 31);
  5093		rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
  5094		rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
  5095		rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
  5096		rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
  5097		rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
  5098	
  5099		rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
  5100		rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
  5101		rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
  5102		rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 1);
  5103		rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
  5104		rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 0);
  5105		rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
  5106		rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
  5107		rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
  5108	
  5109		rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
  5110		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
  5111		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
  5112		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5113		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
  5114		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5115		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5116		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5117		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5118		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5119		rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
  5120		rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
  5121	
  5122		rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
  5123		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
  5124		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
  5125		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5126		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
  5127		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5128		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5129		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5130		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5131		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5132		rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
  5133		rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
  5134	
  5135		rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
  5136		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
  5137		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 1);
  5138		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5139		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5140		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5141		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5142		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5143		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5144		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5145		rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
  5146		rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
  5147	
  5148		rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
  5149		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
  5150		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 1);
  5151		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5152		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5153		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5154		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5155		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
  5156		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5157		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
  5158		rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
  5159		rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
  5160	
  5161		rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
  5162		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
  5163		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 1);
  5164		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5165		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5166		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5167		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5168		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5169		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5170		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5171		rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
  5172		rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
  5173	
  5174		rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
  5175		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
  5176		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 1);
  5177		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5178		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5179		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5180		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5181		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
  5182		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5183		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
  5184		rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, 0);
  5185		rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
  5186	
  5187		if (rt2x00_is_usb(rt2x00dev)) {
  5188			rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
  5189	
  5190			rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
  5191			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
  5192			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
  5193			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
  5194			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
  5195			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
  5196			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
  5197			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
  5198			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
  5199			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
  5200			rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
  5201		}
  5202	
  5203		/*
  5204		 * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
  5205		 * although it is reserved.
  5206		 */
  5207		rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
  5208		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
  5209		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
  5210		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
  5211		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
  5212		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
  5213		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
  5214		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
  5215		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
  5216		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
  5217		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
  5218		rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
  5219	
  5220		reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
  5221		rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
  5222	
  5223		if (rt2x00_rt(rt2x00dev, RT3883)) {
> 5224			rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
> 5225			rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
  5226		}
  5227	
  5228		rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38065 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Matt Ranostay @ 2017-01-15 21:41 UTC (permalink / raw)
  To: Shawn Lin
  Cc: linux-wireless, Linux Kernel, linux-mmc, devicetree,
	Tony Lindgren, Ulf Hansson
In-Reply-To: <cd669d08-0db4-57e4-478b-2b200ccef6f1@rock-chips.com>

On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin@rock-chips.com> wrote:
> On 2017/1/13 13:29, Matt Ranostay wrote:
>>
>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>> This can be abstracted to other chipsets if needed in the future.
>>
>> Cc: Tony Lindgren <tony@atomide.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>> ---
>>  drivers/mmc/core/Kconfig         |  10 ++++
>>  drivers/mmc/core/Makefile        |   1 +
>>  drivers/mmc/core/pwrseq_sd8787.c | 117
>> +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 128 insertions(+)
>>  create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>
>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/mmc/core/Kconfig
>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>           This driver can also be built as a module. If so, the module
>>           will be called pwrseq_emmc.
>>
>> +config PWRSEQ_SD8787
>> +       tristate "HW reset support for SD8787 BT + Wifi module"
>> +       depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>> +       help
>> +         This selects hardware reset support for the SD8787 BT + Wifi
>> +         module. By default this option is set to n.
>> +
>> +         This driver can also be built as a module. If so, the module
>> +         will be called pwrseq_sd8787.
>> +
>
>
> I don't like this way, as we have a chance to list lots
> configure options here. wifi A,B,C,D...Z, all of them need a
> new section here if needed?
>
> Instead, could you just extent pwrseq_simple.c and add you
> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?

You mean all the chipset pwrseqs linked into the pwrseq-simple module?

Ulf your thoughts on this?

>
>
>
>>  config PWRSEQ_SIMPLE
>>         tristate "Simple HW reset support for MMC"
>>         default y
>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>> index b2a257dc644f..0f81464fa824 100644
>> --- a/drivers/mmc/core/Makefile
>> +++ b/drivers/mmc/core/Makefile
>> @@ -10,6 +10,7 @@ mmc_core-y                    := core.o bus.o host.o \
>>                                    quirks.o slot-gpio.o
>>  mmc_core-$(CONFIG_OF)          += pwrseq.o
>>  obj-$(CONFIG_PWRSEQ_SIMPLE)    += pwrseq_simple.o
>> +obj-$(CONFIG_PWRSEQ_SD8787)    += pwrseq_sd8787.o
>>  obj-$(CONFIG_PWRSEQ_EMMC)      += pwrseq_emmc.o
>>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>> diff --git a/drivers/mmc/core/pwrseq_sd8787.c
>> b/drivers/mmc/core/pwrseq_sd8787.c
>> new file mode 100644
>> index 000000000000..f4080fe6439e
>> --- /dev/null
>> +++ b/drivers/mmc/core/pwrseq_sd8787.c
>> @@ -0,0 +1,117 @@
>> +/*
>> + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi
>> chip
>> + *
>> + * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
>> + *
>> + * Based on the original work pwrseq_simple.c
>> + *  Copyright (C) 2014 Linaro Ltd
>> + *  Author: Ulf Hansson <ulf.hansson@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/gpio/consumer.h>
>> +
>> +#include <linux/mmc/host.h>
>> +
>> +#include "pwrseq.h"
>> +
>> +struct mmc_pwrseq_sd8787 {
>> +       struct mmc_pwrseq pwrseq;
>> +       struct gpio_desc *reset_gpio;
>> +       struct gpio_desc *pwrdn_gpio;
>> +};
>> +
>> +#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787,
>> pwrseq)
>> +
>> +static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>> +
>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
>> +
>> +       msleep(300);
>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
>> +}
>> +
>> +static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>> +
>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
>> +}
>> +
>> +static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
>> +       .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
>> +       .power_off = mmc_pwrseq_sd8787_power_off,
>> +};
>> +
>> +static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
>> +       { .compatible = "mmc-pwrseq-sd8787",},
>> +       {/* sentinel */},
>> +};
>> +MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
>> +
>> +static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq;
>> +       struct device *dev = &pdev->dev;
>> +
>> +       pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
>> +       if (!pwrseq)
>> +               return -ENOMEM;
>> +
>> +       pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "pwrdn", GPIOD_OUT_LOW);
>> +       if (IS_ERR(pwrseq->pwrdn_gpio))
>> +               return PTR_ERR(pwrseq->pwrdn_gpio);
>> +
>> +       pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
>> +       if (IS_ERR(pwrseq->reset_gpio))
>> +               return PTR_ERR(pwrseq->reset_gpio);
>> +
>> +       pwrseq->pwrseq.dev = dev;
>> +       pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
>> +       pwrseq->pwrseq.owner = THIS_MODULE;
>> +       platform_set_drvdata(pdev, pwrseq);
>> +
>> +       return mmc_pwrseq_register(&pwrseq->pwrseq);
>> +}
>> +
>> +static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
>> +
>> +       mmc_pwrseq_unregister(&pwrseq->pwrseq);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct platform_driver mmc_pwrseq_sd8787_driver = {
>> +       .probe = mmc_pwrseq_sd8787_probe,
>> +       .remove = mmc_pwrseq_sd8787_remove,
>> +       .driver = {
>> +               .name = "pwrseq_sd8787",
>> +               .of_match_table = mmc_pwrseq_sd8787_of_match,
>> +       },
>> +};
>> +
>> +module_platform_driver(mmc_pwrseq_sd8787_driver);
>> +MODULE_LICENSE("GPL v2");
>>
>
>
> --
> Best Regards
> Shawn Lin
>

^ permalink raw reply

* Re: [PATCH v2 2/3] mwifiex: pcie: don't loop/retry interrupt status checks
From: Dmitry Torokhov @ 2017-01-16  0:54 UTC (permalink / raw)
  To: Brian Norris
  Cc: Amitkumar Karwar, Nishant Sarmukadam, linux-kernel, Kalle Valo,
	linux-wireless, Cathy Luo
In-Reply-To: <20170113233538.36196-2-briannorris@chromium.org>

On Fri, Jan 13, 2017 at 03:35:37PM -0800, Brian Norris wrote:
> The following sequence occurs when using IEEE power-save on 8997:
> (a) driver sees SLEEP event
> (b) driver issues SLEEP CONFIRM
> (c) driver recevies CMD interrupt; within the interrupt processing loop,
>     we do (d) and (e):
> (d) wait for FW sleep cookie (and often time out; it takes a while), FW
>     is putting card into low power mode
> (e) re-check PCIE_HOST_INT_STATUS register; quit loop with 0 value
> 
> But at (e), no one actually signaled an interrupt (i.e., we didn't check
> adapter->int_status). And what's more, because the card is going to
> sleep, this register read appears to take a very long time in some cases
> -- 3 milliseconds in my case!
> 
> Now, I propose that (e) is completely unnecessary. If there were any
> additional interrupts signaled after the start of this loop, then the
> interrupt handler would have set adapter->int_status to non-zero and
> queued more work for the main loop -- and we'd catch it on the next
> iteration of the main loop.
> 
> So this patch drops all the looping/re-reading of PCIE_HOST_INT_STATUS,
> which avoids the problematic (and slow) register read in step (e).
> 
> Incidentally, this is a very similar issue to the one fixed in commit
> ec815dd2a5f1 ("mwifiex: prevent register accesses after host is
> sleeping"), except that the register read is just very slow instead of
> fatal in this case.
> 
> Tested on 8997 in both MSI and (though not technically supported at the
> moment) MSI-X mode.

Well, that kills interrupt mitigation and with PCIE that might be
somewhat important (SDIO is too slow to be important I think) and might
cost you throughput.

OTOH maybe Marvell should convert PICE to NAPI to make this more
obvious and probably more correct.

> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
> v2:
>  * new in v2, replacing an attempt to mess with step (d) above
> ---
>  drivers/net/wireless/marvell/mwifiex/pcie.c | 102 +++++++++-------------------
>  1 file changed, 32 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 3f4cda2d3b61..194e0e04c3b1 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -2332,79 +2332,41 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
>  			}
>  		}
>  	}
> -	while (pcie_ireg & HOST_INTR_MASK) {
> -		if (pcie_ireg & HOST_INTR_DNLD_DONE) {
> -			pcie_ireg &= ~HOST_INTR_DNLD_DONE;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: TX DNLD Done\n");
> -			ret = mwifiex_pcie_send_data_complete(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -		if (pcie_ireg & HOST_INTR_UPLD_RDY) {
> -			pcie_ireg &= ~HOST_INTR_UPLD_RDY;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: Rx DATA\n");
> -			ret = mwifiex_pcie_process_recv_data(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -		if (pcie_ireg & HOST_INTR_EVENT_RDY) {
> -			pcie_ireg &= ~HOST_INTR_EVENT_RDY;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: Rx EVENT\n");
> -			ret = mwifiex_pcie_process_event_ready(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -
> -		if (pcie_ireg & HOST_INTR_CMD_DONE) {
> -			pcie_ireg &= ~HOST_INTR_CMD_DONE;
> -			if (adapter->cmd_sent) {
> -				mwifiex_dbg(adapter, INTR,
> -					    "info: CMD sent Interrupt\n");
> -				adapter->cmd_sent = false;
> -			}
> -			/* Handle command response */
> -			ret = mwifiex_pcie_process_cmd_complete(adapter);
> -			if (ret)
> -				return ret;
> -			if (adapter->hs_activated)
> -				return ret;
> -		}
> -
> -		if (card->msi_enable) {
> -			spin_lock_irqsave(&adapter->int_lock, flags);
> -			adapter->int_status = 0;
> -			spin_unlock_irqrestore(&adapter->int_lock, flags);
> -		}
> -
> -		if (mwifiex_pcie_ok_to_access_hw(adapter)) {
> -			if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
> -					     &pcie_ireg)) {
> -				mwifiex_dbg(adapter, ERROR,
> -					    "Read register failed\n");
> -				return -1;
> -			}
>  
> -			if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
> -				if (mwifiex_write_reg(adapter,
> -						      PCIE_HOST_INT_STATUS,
> -						      ~pcie_ireg)) {
> -					mwifiex_dbg(adapter, ERROR,
> -						    "Write register failed\n");
> -					return -1;
> -				}
> -			}
> -
> -		}
> -		if (!card->msi_enable) {
> -			spin_lock_irqsave(&adapter->int_lock, flags);
> -			pcie_ireg |= adapter->int_status;
> -			adapter->int_status = 0;
> -			spin_unlock_irqrestore(&adapter->int_lock, flags);
> +	if (pcie_ireg & HOST_INTR_DNLD_DONE) {
> +		pcie_ireg &= ~HOST_INTR_DNLD_DONE;
> +		mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n");
> +		ret = mwifiex_pcie_send_data_complete(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_UPLD_RDY) {
> +		pcie_ireg &= ~HOST_INTR_UPLD_RDY;
> +		mwifiex_dbg(adapter, INTR, "info: Rx DATA\n");
> +		ret = mwifiex_pcie_process_recv_data(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_EVENT_RDY) {
> +		pcie_ireg &= ~HOST_INTR_EVENT_RDY;
> +		mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n");
> +		ret = mwifiex_pcie_process_event_ready(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_CMD_DONE) {
> +		pcie_ireg &= ~HOST_INTR_CMD_DONE;
> +		if (adapter->cmd_sent) {
> +			mwifiex_dbg(adapter, INTR,
> +				    "info: CMD sent Interrupt\n");
> +			adapter->cmd_sent = false;
>  		}
> +		/* Handle command response */
> +		ret = mwifiex_pcie_process_cmd_complete(adapter);
> +		if (ret)
> +			return ret;
>  	}
> +
>  	mwifiex_dbg(adapter, INTR,
>  		    "info: cmd_sent=%d data_sent=%d\n",
>  		    adapter->cmd_sent, adapter->data_sent);
> -- 
> 2.11.0.483.g087da7b7c-goog
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Shawn Lin @ 2017-01-16  2:35 UTC (permalink / raw)
  To: Matt Ranostay
  Cc: shawn.lin, linux-wireless, Linux Kernel, linux-mmc, devicetree,
	Tony Lindgren, Ulf Hansson
In-Reply-To: <CAJ_EiSQtPUwv9K7CbM5e_wnre6=qR=+hgtq-oVFub2phijvXgA@mail.gmail.com>

On 2017/1/16 5:41, Matt Ranostay wrote:
> On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin@rock-chips.com> wrote:
>> On 2017/1/13 13:29, Matt Ranostay wrote:
>>>
>>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>>> This can be abstracted to other chipsets if needed in the future.
>>>
>>> Cc: Tony Lindgren <tony@atomide.com>
>>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>> ---
>>>  drivers/mmc/core/Kconfig         |  10 ++++
>>>  drivers/mmc/core/Makefile        |   1 +
>>>  drivers/mmc/core/pwrseq_sd8787.c | 117
>>> +++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 128 insertions(+)
>>>  create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>>
>>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>>> --- a/drivers/mmc/core/Kconfig
>>> +++ b/drivers/mmc/core/Kconfig
>>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>>           This driver can also be built as a module. If so, the module
>>>           will be called pwrseq_emmc.
>>>
>>> +config PWRSEQ_SD8787
>>> +       tristate "HW reset support for SD8787 BT + Wifi module"
>>> +       depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>>> +       help
>>> +         This selects hardware reset support for the SD8787 BT + Wifi
>>> +         module. By default this option is set to n.
>>> +
>>> +         This driver can also be built as a module. If so, the module
>>> +         will be called pwrseq_sd8787.
>>> +
>>
>>
>> I don't like this way, as we have a chance to list lots
>> configure options here. wifi A,B,C,D...Z, all of them need a
>> new section here if needed?
>>
>> Instead, could you just extent pwrseq_simple.c and add you
>> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?
>
> You mean all the chipset pwrseqs linked into the pwrseq-simple module?

What I mean was if you just extent the pwrseq-simple a bit, you could
just add your chipset pwrseqs linked into the pwrseq-simple. But if you
need a different *pattern* of pwrseqs, you should need a new name, for
instance, pwrseq-sdio.c etc... But please don't use the name of
sd8787? So if I use a wifi named ABC but using the same pwrseq pattenr,
should I include your "mmc-pwrseq- sd8787" for that or I need a new
mmc-pwrseq-ABC.c?

>
> Ulf your thoughts on this?
>
>>
>>
>>
>>>  config PWRSEQ_SIMPLE
>>>         tristate "Simple HW reset support for MMC"
>>>         default y
>>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>>> index b2a257dc644f..0f81464fa824 100644
>>> --- a/drivers/mmc/core/Makefile
>>> +++ b/drivers/mmc/core/Makefile
>>> @@ -10,6 +10,7 @@ mmc_core-y                    := core.o bus.o host.o \
>>>                                    quirks.o slot-gpio.o
>>>  mmc_core-$(CONFIG_OF)          += pwrseq.o
>>>  obj-$(CONFIG_PWRSEQ_SIMPLE)    += pwrseq_simple.o
>>> +obj-$(CONFIG_PWRSEQ_SD8787)    += pwrseq_sd8787.o
>>>  obj-$(CONFIG_PWRSEQ_EMMC)      += pwrseq_emmc.o
>>>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>>>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>>> diff --git a/drivers/mmc/core/pwrseq_sd8787.c
>>> b/drivers/mmc/core/pwrseq_sd8787.c
>>> new file mode 100644
>>> index 000000000000..f4080fe6439e
>>> --- /dev/null
>>> +++ b/drivers/mmc/core/pwrseq_sd8787.c
>>> @@ -0,0 +1,117 @@
>>> +/*
>>> + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi
>>> chip
>>> + *
>>> + * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
>>> + *
>>> + * Based on the original work pwrseq_simple.c
>>> + *  Copyright (C) 2014 Linaro Ltd
>>> + *  Author: Ulf Hansson <ulf.hansson@linaro.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/module.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/device.h>
>>> +#include <linux/err.h>
>>> +#include <linux/gpio/consumer.h>
>>> +
>>> +#include <linux/mmc/host.h>
>>> +
>>> +#include "pwrseq.h"
>>> +
>>> +struct mmc_pwrseq_sd8787 {
>>> +       struct mmc_pwrseq pwrseq;
>>> +       struct gpio_desc *reset_gpio;
>>> +       struct gpio_desc *pwrdn_gpio;
>>> +};
>>> +
>>> +#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787,
>>> pwrseq)
>>> +
>>> +static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>>> +
>>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
>>> +
>>> +       msleep(300);
>>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
>>> +}
>>> +
>>> +static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>>> +
>>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
>>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
>>> +}
>>> +
>>> +static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
>>> +       .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
>>> +       .power_off = mmc_pwrseq_sd8787_power_off,
>>> +};
>>> +
>>> +static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
>>> +       { .compatible = "mmc-pwrseq-sd8787",},
>>> +       {/* sentinel */},
>>> +};
>>> +MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
>>> +
>>> +static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq;
>>> +       struct device *dev = &pdev->dev;
>>> +
>>> +       pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
>>> +       if (!pwrseq)
>>> +               return -ENOMEM;
>>> +
>>> +       pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "pwrdn", GPIOD_OUT_LOW);
>>> +       if (IS_ERR(pwrseq->pwrdn_gpio))
>>> +               return PTR_ERR(pwrseq->pwrdn_gpio);
>>> +
>>> +       pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
>>> +       if (IS_ERR(pwrseq->reset_gpio))
>>> +               return PTR_ERR(pwrseq->reset_gpio);
>>> +
>>> +       pwrseq->pwrseq.dev = dev;
>>> +       pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
>>> +       pwrseq->pwrseq.owner = THIS_MODULE;
>>> +       platform_set_drvdata(pdev, pwrseq);
>>> +
>>> +       return mmc_pwrseq_register(&pwrseq->pwrseq);
>>> +}
>>> +
>>> +static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
>>> +
>>> +       mmc_pwrseq_unregister(&pwrseq->pwrseq);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static struct platform_driver mmc_pwrseq_sd8787_driver = {
>>> +       .probe = mmc_pwrseq_sd8787_probe,
>>> +       .remove = mmc_pwrseq_sd8787_remove,
>>> +       .driver = {
>>> +               .name = "pwrseq_sd8787",
>>> +               .of_match_table = mmc_pwrseq_sd8787_of_match,
>>> +       },
>>> +};
>>> +
>>> +module_platform_driver(mmc_pwrseq_sd8787_driver);
>>> +MODULE_LICENSE("GPL v2");
>>>
>>
>>
>> --
>> Best Regards
>> Shawn Lin
>>
>
>
>


-- 
Best Regards
Shawn Lin

^ permalink raw reply

* [PATCH v2 00/14] rt2x00 patches from OpenWrt.org
From: Daniel Golle @ 2017-01-16  2:53 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

As requested the original series was devided so that everything except
for Rt3883 can go first. What's left are a couple of fixes and as well
as added support for some Rt3352 boards as well as the Rt5350 WiSoC.

Claudio Mignanti (1):
  rt2x00: rt2x00pci: set PCI MWI only if supported

Daniel Golle (2):
  rt2x00: rt2800lib: support for for RT3352 with external PA
  rt2x00: rt2800lib: add support for RT3352 with 20MHz crystal

Felix Fietkau (1):
  rt2x00: rt2800lib: fix rf id for RT3352

Gabor Juhos (8):
  rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
  rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
  rt2x00: rt2800: serialize shared memory access
  rt2x00: rt2800lib: fix beacon generation on RT3593
  rt2x00: rt2800lib: add hw_beacon_count field to struct rt2800_drv_data
  rt2x00: rt2800lib: init additional beacon offset registers
  rt2x00: rt2800lib: fix max supported beacon count for RT3593
  rt2x00: rt2800mmio: add a workaround for spurious TX_FIFO_STATUS
    interrupts

Michel Stempin (1):
  rt2x00: add support for RT5350 WiSoC

Serge Vasilugin (1):
  rt2x00: rt2800lib: correctly set HT20/HT40 filter

 drivers/net/wireless/ralink/rt2x00/rt2800.h     |  60 +++-
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c  | 406 ++++++++++++++++++++++--
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h  |  65 ++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c |  98 +++++-
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h |   4 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c  |  14 +
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c  |   3 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c  |  31 ++
 drivers/net/wireless/ralink/rt2x00/rt2x00.h     |  10 +
 drivers/net/wireless/ralink/rt2x00/rt2x00pci.c  |   2 +
 10 files changed, 640 insertions(+), 53 deletions(-)

-- 
2.11.0

^ permalink raw reply

* [PATCH v2 01/14] rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
From: Daniel Golle @ 2017-01-16  2:55 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

The rt2800_drv_data structure contains driver specific
information. Move the declaration into the rt2800lib.h
header which is a more logical place for it. Also fix
the comment style to avoid checkpatch warning.

The patch contains no functional changes, it is in
preparation for the next patch.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    | 16 ----------------
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 16 ++++++++++++++++
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index ec622a08a486..2371896c1e99 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -2969,20 +2969,4 @@ enum rt2800_eeprom_word {
 #define WCID_END	222
 #define STA_IDS_SIZE	(WCID_END - WCID_START + 2)
 
-/*
- * RT2800 driver data structure
- */
-struct rt2800_drv_data {
-	u8 calibration_bw20;
-	u8 calibration_bw40;
-	u8 bbp25;
-	u8 bbp26;
-	u8 txmixer_gain_24g;
-	u8 txmixer_gain_5g;
-	u8 max_psdu;
-	unsigned int tbtt_tick;
-	unsigned int ampdu_factor_cnt[4];
-	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
-};
-
 #endif /* RT2800_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 0a8b4df665fe..256928f0ea6a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -20,6 +20,22 @@
 #ifndef RT2800LIB_H
 #define RT2800LIB_H
 
+#include "rt2800.h"
+
+/* RT2800 driver data structure */
+struct rt2800_drv_data {
+	u8 calibration_bw20;
+	u8 calibration_bw40;
+	u8 bbp25;
+	u8 bbp26;
+	u8 txmixer_gain_24g;
+	u8 txmixer_gain_5g;
+	u8 max_psdu;
+	unsigned int tbtt_tick;
+	unsigned int ampdu_factor_cnt[4];
+	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+};
+
 struct rt2800_ops {
 	void (*register_read)(struct rt2x00_dev *rt2x00dev,
 			      const unsigned int offset, u32 *value);
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 02/14] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
From: Daniel Golle @ 2017-01-16  2:55 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

Some chipsets have more than 16KB of shared memory.
Introduce a new rt2800 specific flag to indicate that
and add a helper function which helps to check the
presence of the new flag.

Also enable the new flag for the RT3593 chipset which
has 24KB of shared memory. The flag can also be used
for other chipsets, but none of those has been tested
yet.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c |  4 ++++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 13 +++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 5436cdb07937..5045af1b0dc9 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -7770,6 +7770,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
 
 int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 	int retval;
 	u32 reg;
 
@@ -7777,6 +7778,9 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (retval)
 		return retval;
 
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
 	/*
 	 * Allocate eeprom data.
 	 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 256928f0ea6a..4ee424dfe23f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -22,6 +22,10 @@
 
 #include "rt2800.h"
 
+enum rt2800_flag {
+	RT2800_HAS_HIGH_SHARED_MEM,
+};
+
 /* RT2800 driver data structure */
 struct rt2800_drv_data {
 	u8 calibration_bw20;
@@ -34,6 +38,8 @@ struct rt2800_drv_data {
 	unsigned int tbtt_tick;
 	unsigned int ampdu_factor_cnt[4];
 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+
+	unsigned long rt2800_flags;
 };
 
 struct rt2800_ops {
@@ -66,6 +72,13 @@ struct rt2800_ops {
 	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
 };
 
+static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+}
+
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 					const unsigned int offset,
 					u32 *value)
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 03/14] rt2x00: rt2800: serialize shared memory access
From: Daniel Golle @ 2017-01-16  2:58 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

The shared memory of the rt2800 devices is accessible
through the register offset range between 0x4000 and
0x8000. The size of this range is 16KB only and on
devices which have more than 16KB of shared memory either
the low or the high part of the memory is accessible at a
time.

Serialize all accesses to the shared memory by a mutex,
in order to avoid concurrent use of that.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c  | 55 ++++++++++++++++++++++++-
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h  | 35 ++++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 26 ++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h |  4 ++
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c  | 14 +++++++
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c  |  3 ++
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c  | 31 ++++++++++++++
 7 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 5045af1b0dc9..0fd67026f806 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
 		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
 		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
 
 		reg = 0;
 		rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
 		rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	mutex_unlock(&rt2x00dev->csr_mutex);
@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	 * Wait for device to stabilize.
 	 */
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+		rt2800_shared_mem_unlock(rt2x00dev);
 		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
 			break;
 		msleep(1);
@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	/*
 	 * Initialize firmware.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
+
 	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
+
 		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 	}
 	msleep(1);
@@ -1035,8 +1045,10 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
+	rt2800_shared_mem_unlock(rt2x00dev);
 	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
 
 	/*
@@ -1066,6 +1078,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 
+	rt2800_shared_mem_lock(rt2x00dev);
+
 	/*
 	 * For the Beacon base registers we only need to clear
 	 * the whole TXWI which (when set to 0) will invalidate
@@ -1073,6 +1087,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 	 */
 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 void rt2800_clear_beacon(struct queue_entry *entry)
@@ -1261,7 +1277,9 @@ static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
 {
 	u32 offset;
 	offset = MAC_WCID_ATTR_ENTRY(wcid);
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, offset, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
@@ -1274,11 +1292,13 @@ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
 	 * The BSS Idx numbers is split in a main value of 3 bits,
 	 * and a extended field for adding one additional bit to the value.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_read(rt2x00dev, offset, &reg);
 	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
 	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
 			   (bssidx & 0x8) >> 3);
 	rt2800_register_write(rt2x00dev, offset, reg);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
@@ -1291,6 +1311,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 
 	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	if (crypto->cmd == SET_KEY) {
 		rt2800_register_read(rt2x00dev, offset, &reg);
 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
@@ -1315,6 +1336,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
 		rt2800_register_write(rt2x00dev, offset, reg);
 	}
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
@@ -1324,8 +1346,11 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 	    (crypto->cipher == CIPHER_AES))
 		iveiv_entry.iv[3] |= 0x20;
 	iveiv_entry.iv[3] |= key->keyidx << 6;
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, offset,
 				      &iveiv_entry, sizeof(iveiv_entry));
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1348,8 +1373,11 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 		       sizeof(key_entry.rx_mic));
 
 		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_multiwrite(rt2x00dev, offset,
 					      &key_entry, sizeof(key_entry));
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -1364,10 +1392,12 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 
 	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_read(rt2x00dev, offset, &reg);
 	rt2x00_set_field32(&reg, field,
 			   (crypto->cmd == SET_KEY) * crypto->cipher);
 	rt2800_register_write(rt2x00dev, offset, reg);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
 	 * Update WCID information
@@ -1405,8 +1435,11 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 		       sizeof(key_entry.rx_mic));
 
 		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_multiwrite(rt2x00dev, offset,
 					      &key_entry, sizeof(key_entry));
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -4930,14 +4963,19 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * ASIC will keep garbage value after boot, clear encryption keys.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	for (i = 0; i < 4; i++)
 		rt2800_register_write(rt2x00dev,
 					 SHARED_KEY_MODE_ENTRY(i), 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	for (i = 0; i < 256; i++) {
 		rt2800_config_wcid(rt2x00dev, NULL, i);
 		rt2800_delete_wcid_attr(rt2x00dev, i);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -5063,8 +5101,10 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
 	 * BBP was enabled after firmware was loaded,
 	 * but we need to reactivate it now.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 	msleep(1);
 
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
@@ -6760,11 +6800,19 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Send signal during boot time to initialize firmware.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-	if (rt2x00_is_usb(rt2x00dev))
+	rt2800_shared_mem_unlock(rt2x00dev);
+
+	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
+	}
+
 	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+
 	msleep(1);
 
 	/*
@@ -7774,6 +7822,8 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	int retval;
 	u32 reg;
 
+	rt2800_shared_mem_init_lock(rt2x00dev);
+
 	retval = rt2800_probe_rt(rt2x00dev);
 	if (retval)
 		return retval;
@@ -7857,8 +7907,11 @@ void rt2800_get_key_seq(struct ieee80211_hw *hw,
 		return;
 
 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiread(rt2x00dev, offset,
 				      &iveiv_entry, sizeof(iveiv_entry));
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2);
 	memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 4ee424dfe23f..ccfa8cf1f5ac 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -40,6 +40,14 @@ struct rt2800_drv_data {
 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
 
 	unsigned long rt2800_flags;
+
+	/* locks to serialize shared memory access */
+	union {
+		/* a spinlock is used for MMIO devices */
+		spinlock_t spin;
+		/* a mutex is used for PCI devices */
+		struct mutex mutex;
+	} shmem_lock;
 };
 
 struct rt2800_ops {
@@ -70,6 +78,10 @@ struct rt2800_ops {
 				  const u8 *data, const size_t len);
 	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
 	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+
+	void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev);
+	void (*shmem_lock)(struct rt2x00_dev *rt2x00dev);
+	void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev);
 };
 
 static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
@@ -79,6 +91,29 @@ static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
 	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 }
 
+static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+	rt2800ops->shmem_init_lock(rt2x00dev);
+}
+
+static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev)
+{
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+	if (rt2800_has_high_shared_mem(rt2x00dev))
+		rt2800ops->shmem_lock(rt2x00dev);
+}
+
+static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+	if (rt2800_has_high_shared_mem(rt2x00dev))
+		rt2800ops->shmem_unlock(rt2x00dev);
+}
+
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 					const unsigned int offset,
 					u32 *value)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index de4790b41be7..5f1936aa8fa7 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
 	rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	if (rt2x00_is_pcie(rt2x00dev) &&
 	    (rt2x00_rt(rt2x00dev, RT3090) ||
@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
 
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	spin_lock_init(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock);
+
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	spin_lock_bh(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock);
+
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	spin_unlock_bh(&drv_data->shmem_lock.spin);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock);
+
 MODULE_AUTHOR(DRV_PROJECT);
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION("rt2800 MMIO library");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
index b63312ce3f27..352b409dcff2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev);
 /* Device state switch handlers. */
 int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
 
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev);
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev);
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev);
+
 #endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 0af22573a2eb..beb1199acccb 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 		return;
 
 	for (i = 0; i < 200; i++) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+		rt2800_shared_mem_unlock(rt2x00dev);
 
 		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
 		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 	if (i == 200)
 		rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 	 */
 	reg = 0;
 	rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
 
 	/*
@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 
 	rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	return 0;
 }
@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
 		return retval;
 
 	/* After resume MCU_BOOT_SIGNAL will trash these. */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
 	rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 				   0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
 	} else if (state == STATE_SLEEP) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
 					  0xffffffff);
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
 					  0xffffffff);
+		rt2800_shared_mem_unlock(rt2x00dev);
 		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
 				   0xff, 0x01);
 	}
@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
 	.drv_write_firmware	= rt2800pci_write_firmware,
 	.drv_init_registers	= rt2800mmio_init_registers,
 	.drv_get_txwi		= rt2800mmio_get_txwi,
+	.shmem_init_lock	= rt2800mmio_shmem_init_lock,
+	.shmem_lock		= rt2800mmio_shmem_lock,
+	.shmem_unlock		= rt2800mmio_shmem_unlock,
 };
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index a985a5a7945e..871d9d331046 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc_rt2800_ops = {
 	.drv_write_firmware	= rt2800soc_write_firmware,
 	.drv_init_registers	= rt2800mmio_init_registers,
 	.drv_get_txwi		= rt2800mmio_get_txwi,
+	.shmem_init_lock	= rt2800mmio_shmem_init_lock,
+	.shmem_lock		= rt2800mmio_shmem_lock,
+	.shmem_unlock		= rt2800mmio_shmem_unlock,
 };
 
 static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index f38c44061b5b..f8d905c63ac8 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
 	return modparam_nohwcrypt;
 }
 
+static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	mutex_init(&drv_data->shmem_lock.mutex);
+}
+
+static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	mutex_lock(&drv_data->shmem_lock.mutex);
+}
+
+static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	mutex_unlock(&drv_data->shmem_lock.mutex);
+}
+
 /*
  * Queue handlers.
  */
@@ -299,8 +320,10 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 					      data + offset, length);
 	}
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
 	 * Send firmware request to device to load firmware,
@@ -315,7 +338,10 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 	}
 
 	msleep(10);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	return 0;
 }
@@ -333,8 +359,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
 	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
 	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	reg = 0;
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
@@ -860,6 +888,9 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
 	.drv_write_firmware	= rt2800usb_write_firmware,
 	.drv_init_registers	= rt2800usb_init_registers,
 	.drv_get_txwi		= rt2800usb_get_txwi,
+	.shmem_init_lock	= rt2800usb_shmem_init_lock,
+	.shmem_lock		= rt2800usb_shmem_lock,
+	.shmem_unlock		= rt2800usb_shmem_unlock,
 };
 
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 04/14] rt2x00: rt2800lib: fix beacon generation on RT3593
From: Daniel Golle @ 2017-01-16  3:01 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

On the RT3593 chipset, the beacon registers are located
in the high 8KB part of the shared memory.

The high part of the shared memory is only accessible
if it is explicitly selected. Add a helper function
in order to be able to control the SHR_MSEL bit in
the PBF_SYS_CTRL register. Also add a few more helper
functions and use those to select the correct part of
the shared memory before and after accessing the beacon
registers.

The base addresses of the beacon registers are also
different from the actually used values, so fix the
'rt2800_hw_beacon_base' function to return the correct
values.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    |  3 ++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 44 ++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 2371896c1e99..a81852cfb4f9 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -574,6 +574,7 @@
 #define PBF_SYS_CTRL			0x0400
 #define PBF_SYS_CTRL_READY		FIELD32(0x00000080)
 #define PBF_SYS_CTRL_HOST_RAM_WRITE	FIELD32(0x00010000)
+#define PBF_SYS_CTRL_SHR_MSEL		FIELD32(0x00080000)
 
 /*
  * HOST-MCU shared memory
@@ -2026,6 +2027,8 @@ struct mac_iveiv_entry {
 	  (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
 	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
 
+#define HW_BEACON_BASE_HIGH(__index)	(0x4000 + (__index) * 512)
+
 #define BEACON_BASE_TO_OFFSET(_base)	(((_base) - 0x4000) / 64)
 
 /*
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0fd67026f806..dcacfa54b3d6 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
 	return false;
 }
 
+static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev,
+					    bool high)
+{
+	u32 reg;
+
+	if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev)))
+		return;
+
+	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, PBF_SYS_CTRL_SHR_MSEL, high);
+	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+}
+
+static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return true;
+
+	return false;
+}
+
+static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2800_beacon_uses_high_mem(rt2x00dev))
+		rt2800_shared_mem_select(rt2x00dev, true);
+}
+
+static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2800_beacon_uses_high_mem(rt2x00dev))
+		rt2800_shared_mem_select(rt2x00dev, false);
+}
+
 static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
 			     const unsigned int word, const u8 value)
 {
@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
 					  unsigned int index)
 {
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return HW_BEACON_BASE_HIGH(index);
+
 	return HW_BEACON_BASE(index);
 }
 
@@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 
 	rt2800_shared_mem_lock(rt2x00dev);
+
+	rt2800_select_beacon_mem(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
+	rt2800_deselect_beacon_mem(rt2x00dev);
+
 	rt2800_shared_mem_unlock(rt2x00dev);
 	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
 
@@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 
 	rt2800_shared_mem_lock(rt2x00dev);
 
+	rt2800_select_beacon_mem(rt2x00dev);
+
 	/*
 	 * For the Beacon base registers we only need to clear
 	 * the whole TXWI which (when set to 0) will invalidate
@@ -1088,6 +1130,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 
+	rt2800_deselect_beacon_mem(rt2x00dev);
+
 	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 05/14] rt2x00: rt2800lib: add hw_beacon_count field to struct rt2800_drv_data
From: Daniel Golle @ 2017-01-16  3:02 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

Some chipsets can handle more than 8 beacons at once.
Add a new field to the rt2800_drv_data structure which
will hold the number of supported beacons of the given
chipset.

Update the rt2x00_init_registers function to get the
beacon count from the new field instead of using a
hardcoded value.

In order to keep the current behaviour, initialize the
new field with the actually used value.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 4 +++-
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index dcacfa54b3d6..0893d9147af9 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -5025,7 +5025,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Clear all beacons
 	 */
-	for (i = 0; i < 8; i++)
+	for (i = 0; i < drv_data->hw_beacon_count; i++)
 		rt2800_clear_beacon_register(rt2x00dev, i);
 
 	if (rt2x00_is_usb(rt2x00dev)) {
@@ -7875,6 +7875,8 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3593))
 		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 
+	drv_data->hw_beacon_count = 8;
+
 	/*
 	 * Allocate eeprom data.
 	 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index ccfa8cf1f5ac..ab49e6feeeb9 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -37,6 +37,7 @@ struct rt2800_drv_data {
 	u8 max_psdu;
 	unsigned int tbtt_tick;
 	unsigned int ampdu_factor_cnt[4];
+	unsigned int hw_beacon_count;
 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
 
 	unsigned long rt2800_flags;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 07/14] rt2x00: rt2800lib: fix max supported beacon count for RT3593
From: Daniel Golle @ 2017-01-16  3:03 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 5058494d6c27..ff653f0d43d2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -7899,7 +7899,10 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3593))
 		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 
-	drv_data->hw_beacon_count = 8;
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		drv_data->hw_beacon_count = 16;
+	else
+		drv_data->hw_beacon_count = 8;
 
 	/*
 	 * Allocate eeprom data.
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 06/14] rt2x00: rt2800lib: init additional beacon offset registers
From: Daniel Golle @ 2017-01-16  3:03 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    | 14 ++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index a81852cfb4f9..02ed0d512734 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -629,6 +629,20 @@
  */
 #define PBF_DBG				0x043c
 
+/* BCN_OFFSET2 */
+#define BCN_OFFSET2			0x0444
+#define BCN_OFFSET2_BCN8		FIELD32(0x000000ff)
+#define BCN_OFFSET2_BCN9		FIELD32(0x0000ff00)
+#define BCN_OFFSET2_BCN10		FIELD32(0x00ff0000)
+#define BCN_OFFSET2_BCN11		FIELD32(0xff000000)
+
+/* BCN_OFFSET3 */
+#define BCN_OFFSET3			0x0448
+#define BCN_OFFSET3_BCN12		FIELD32(0x000000ff)
+#define BCN_OFFSET3_BCN13		FIELD32(0x0000ff00)
+#define BCN_OFFSET3_BCN14		FIELD32(0x00ff0000)
+#define BCN_OFFSET3_BCN15		FIELD32(0xff000000)
+
 /*
  * RF registers
  */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0893d9147af9..5058494d6c27 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -4665,6 +4665,30 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	if (ret)
 		return ret;
 
+	if (drv_data->hw_beacon_count == 16) {
+		rt2800_register_read(rt2x00dev, BCN_OFFSET2, &reg);
+		rt2x00_set_field32(&reg, BCN_OFFSET2_BCN8,
+				   rt2800_get_beacon_offset(rt2x00dev, 8));
+		rt2x00_set_field32(&reg, BCN_OFFSET2_BCN9,
+				   rt2800_get_beacon_offset(rt2x00dev, 9));
+		rt2x00_set_field32(&reg, BCN_OFFSET2_BCN10,
+				   rt2800_get_beacon_offset(rt2x00dev, 10));
+		rt2x00_set_field32(&reg, BCN_OFFSET2_BCN11,
+				   rt2800_get_beacon_offset(rt2x00dev, 11));
+		rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg);
+
+		rt2800_register_read(rt2x00dev, BCN_OFFSET3, &reg);
+		rt2x00_set_field32(&reg, BCN_OFFSET3_BCN12,
+				   rt2800_get_beacon_offset(rt2x00dev, 12));
+		rt2x00_set_field32(&reg, BCN_OFFSET3_BCN13,
+				   rt2800_get_beacon_offset(rt2x00dev, 13));
+		rt2x00_set_field32(&reg, BCN_OFFSET3_BCN14,
+				   rt2800_get_beacon_offset(rt2x00dev, 14));
+		rt2x00_set_field32(&reg, BCN_OFFSET3_BCN15,
+				   rt2800_get_beacon_offset(rt2x00dev, 15));
+		rt2800_register_write(rt2x00dev, BCN_OFFSET3, reg);
+	}
+
 	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
 	rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 08/14] rt2x00: rt2800mmio: add a workaround for spurious TX_FIFO_STATUS interrupts
From: Daniel Golle @ 2017-01-16  3:05 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 72 ++++++++++++++++++++-----
 drivers/net/wireless/ralink/rt2x00/rt2x00.h     |  5 ++
 2 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index 5f1936aa8fa7..750a9425b5be 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -415,9 +415,9 @@ void rt2800mmio_autowake_tasklet(unsigned long data)
 }
 EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
 
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev,
+					  u32 status)
 {
-	u32 status;
 	int i;
 
 	/*
@@ -438,29 +438,77 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 	 * Since we have only one producer and one consumer we don't
 	 * need to lock the kfifo.
 	 */
-	for (i = 0; i < rt2x00dev->tx->limit; i++) {
-		rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
-
-		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
-			break;
-
+	i = 0;
+	do {
 		if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
-			rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
+			rt2x00_warn(rt2x00dev,
+				    "TX status FIFO overrun, drop TX status report\n");
 			break;
 		}
-	}
+
+		if (++i >= rt2x00dev->tx->limit)
+			break;
+
+		rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+	} while (rt2x00_get_field32(status, TX_STA_FIFO_VALID));
 
 	/* Schedule the tasklet for processing the tx status. */
 	tasklet_schedule(&rt2x00dev->txstatus_tasklet);
 }
 
+#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES	4
+
+static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev,
+					    u32 txstatus)
+{
+	if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) {
+		rt2x00dev->txstatus_irq_retries = 0;
+		return false;
+	}
+
+	rt2x00dev->txstatus_irq_retries++;
+
+	/* Ensure that we don't go into an infinite IRQ loop. */
+	if (rt2x00dev->txstatus_irq_retries >=
+	    RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) {
+		rt2x00_warn(rt2x00dev,
+			    "%u spurious TX_FIFO_STATUS interrupt(s)\n",
+			    rt2x00dev->txstatus_irq_retries);
+		rt2x00dev->txstatus_irq_retries = 0;
+		return false;
+	}
+
+	return true;
+}
+
 irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
 	u32 reg, mask;
+	u32 txstatus = 0;
 
-	/* Read status and ACK all interrupts */
+	/* Read status */
 	rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+		/* Due to unknown reason the hardware generates a
+		 * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
+		 * register contain valid data. Read the TX status
+		 * here to see if we have to process the actual
+		 * request.
+		 */
+		rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus);
+		if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
+			/* Remove the TX_FIFO_STATUS bit so it won't be
+			 * processed in this turn. The hardware will
+			 * generate another IRQ for us.
+			 */
+			rt2x00_set_field32(&reg,
+					   INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
+		}
+	}
+
+	/* ACK interrupts */
 	rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
 	if (!reg)
@@ -477,7 +525,7 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
 	mask = ~reg;
 
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
-		rt2800mmio_txstatus_interrupt(rt2x00dev);
+		rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus);
 		/*
 		 * Never disable the TX_FIFO_STATUS interrupt.
 		 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 034a07273038..c27408b494ef 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -995,6 +995,11 @@ struct rt2x00_dev {
 	int rf_channel;
 
 	/*
+	 * Counter for tx status irq retries (rt2800pci).
+	 */
+	unsigned int txstatus_irq_retries;
+
+	/*
 	 * Protect the interrupt mask register.
 	 */
 	spinlock_t irqmask_lock;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 09/14] rt2x00: rt2x00pci: set PCI MWI only if supported
From: Daniel Golle @ 2017-01-16  3:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Claudio Mignanti <c.mignanti@gmail.com>

This is needed for devices without support for PCI MWI. See also
https://dev.openwrt.org/changeset/21850

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2x00pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
index eb6dbcd4fddf..4becfeb75ba8 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
@@ -94,8 +94,10 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 
 	pci_set_master(pci_dev);
 
+#ifdef CONFIG_PCI_SET_MWI
 	if (pci_set_mwi(pci_dev))
 		rt2x00_probe_err("MWI not available\n");
+#endif
 
 	if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
 		rt2x00_probe_err("PCI DMA not supported\n");
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 10/14] rt2x00: rt2800lib: correctly set HT20/HT40 filter
From: Daniel Golle @ 2017-01-16  3:08 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Serge Vasilugin <vasilugin@yandex.ru>

Simple patch to correct HT20/HT40 filter setting.
Tested with Rt3290, Rt3352 and Rt5350

Signed-off-by: Serge Vasilugin <vasilugin@yandex.ru>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    |  2 ++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 13 +++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 02ed0d512734..8024fc1a6ae2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -2303,6 +2303,8 @@ struct mac_iveiv_entry {
 #define RFCSR30_RX_H20M			FIELD8(0x04)
 #define RFCSR30_RX_VCM			FIELD8(0x18)
 #define RFCSR30_RF_CALIBRATION		FIELD8(0x80)
+#define RF3322_RFCSR30_TX_H20M		FIELD8(0x01)
+#define RF3322_RFCSR30_RX_H20M		FIELD8(0x02)
 
 /*
  * RFCSR 31:
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index ff653f0d43d2..4f454e143266 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -3299,8 +3299,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	    rt2x00_rf(rt2x00dev, RF5390) ||
 	    rt2x00_rf(rt2x00dev, RF5392)) {
 		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-		rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
-		rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+		if (rt2x00_rf(rt2x00dev, RF3322)) {
+			rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M,
+					  conf_is_ht40(conf));
+			rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_RX_H20M,
+					  conf_is_ht40(conf));
+		} else {
+			rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M,
+					  conf_is_ht40(conf));
+			rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M,
+					  conf_is_ht40(conf));
+		}
 		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
 		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 11/14] rt2x00: rt2800lib: fix rf id for RT3352
From: Daniel Golle @ 2017-01-16  3:13 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Felix Fietkau <nbd@openwrt.org>

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 4f454e143266..366310011491 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -7229,6 +7229,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2x00_rt(rt2x00dev, RT5392))
 		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+	else if (rt2x00_rt(rt2x00dev, RT3352))
+		rf = RF3322;
 	else
 		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 12/14] rt2x00: rt2800lib: support for for RT3352 with external PA
From: Daniel Golle @ 2017-01-16  3:14 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

This is needed for WiFi to work e.g. on DIR-615 rev.H1 which got
external RF power amplifiers connected to the WiSoC.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    | 24 ++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 76 +++++++++++++++++++++-----
 drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  2 +
 3 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index 8024fc1a6ae2..e5110d24c0d7 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -2320,6 +2320,12 @@ struct mac_iveiv_entry {
 #define RFCSR36_RF_BS			FIELD8(0x80)
 
 /*
+ * RFCSR 34:
+ */
+#define RFCSR34_TX0_EXT_PA		FIELD8(0x04)
+#define RFCSR34_TX1_EXT_PA		FIELD8(0x08)
+
+/*
  * RFCSR 38:
  */
 #define RFCSR38_RX_LO1_EN		FIELD8(0x20)
@@ -2331,6 +2337,18 @@ struct mac_iveiv_entry {
 #define RFCSR39_RX_LO2_EN		FIELD8(0x80)
 
 /*
+ * RFCSR 41:
+ */
+#define RFCSR41_BIT1			FIELD8(0x01)
+#define RFCSR41_BIT4			FIELD8(0x08)
+
+/*
+ * RFCSR 42:
+ */
+#define RFCSR42_BIT1			FIELD8(0x01)
+#define RFCSR42_BIT4			FIELD8(0x08)
+
+/*
  * RFCSR 49:
  */
 #define RFCSR49_TX			FIELD8(0x3f)
@@ -2343,6 +2361,8 @@ struct mac_iveiv_entry {
  * RFCSR 50:
  */
 #define RFCSR50_TX			FIELD8(0x3f)
+#define RFCSR50_TX0_EXT_PA		FIELD8(0x02)
+#define RFCSR50_TX1_EXT_PA		FIELD8(0x10)
 #define RFCSR50_EP			FIELD8(0xc0)
 /* bits for RT3593 */
 #define RFCSR50_TX_LO1_EN		FIELD8(0x20)
@@ -2490,6 +2510,8 @@ enum rt2800_eeprom_word {
  * INTERNAL_TX_ALC: 0: disable, 1: enable
  * BT_COEXIST: 0: disable, 1: enable
  * DAC_TEST: 0: disable, 1: enable
+ * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352)
+ * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352)
  */
 #define EEPROM_NIC_CONF1_HW_RADIO		FIELD16(0x0001)
 #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC	FIELD16(0x0002)
@@ -2506,6 +2528,8 @@ enum rt2800_eeprom_word {
 #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC	FIELD16(0x2000)
 #define EEPROM_NIC_CONF1_BT_COEXIST		FIELD16(0x4000)
 #define EEPROM_NIC_CONF1_DAC_TEST		FIELD16(0x8000)
+#define EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352	FIELD16(0x4000)
+#define EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352	FIELD16(0x8000)
 
 /*
  * EEPROM frequency
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 366310011491..93c97eade334 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -3320,11 +3320,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	/*
 	 * Change BBP settings
 	 */
+
 	if (rt2x00_rt(rt2x00dev, RT3352)) {
+		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+
 		rt2800_bbp_write(rt2x00dev, 27, 0x0);
 		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
 		rt2800_bbp_write(rt2x00dev, 27, 0x20);
 		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+		rt2800_bbp_write(rt2x00dev, 86, 0x38);
+		rt2800_bbp_write(rt2x00dev, 83, 0x6a);
 	} else if (rt2x00_rt(rt2x00dev, RT3593)) {
 		if (rf->channel > 14) {
 			/* Disable CCK Packet detection on 5GHz */
@@ -6296,6 +6303,12 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
 
 static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
 {
+	int tx0_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX0,
+				  &rt2x00dev->cap_flags);
+	int tx1_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX1,
+				  &rt2x00dev->cap_flags);
+	u8 rfcsr;
+
 	rt2800_rf_init_calibration(rt2x00dev, 30);
 
 	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
@@ -6331,15 +6344,30 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
 	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
 	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
 	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
-	rt2800_rfcsr_write(rt2x00dev, 34, 0x01);
+	rfcsr = 0x01;
+	if (!tx0_int_pa)
+		rt2x00_set_field8(&rfcsr, RFCSR34_TX0_EXT_PA, 1);
+	if (!tx1_int_pa)
+		rt2x00_set_field8(&rfcsr, RFCSR34_TX1_EXT_PA, 1);
+	rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
 	rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
 	rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
 	rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
 	rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
 	rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
 	rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
-	rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
-	rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
+	rfcsr = 0x52;
+	if (tx0_int_pa) {
+		rt2x00_set_field8(&rfcsr, RFCSR41_BIT1, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR41_BIT4, 1);
+	}
+	rt2800_rfcsr_write(rt2x00dev, 41, rfcsr);
+	rfcsr = 0x52;
+	if (tx1_int_pa) {
+		rt2x00_set_field8(&rfcsr, RFCSR42_BIT1, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR42_BIT4, 1);
+	}
+	rt2800_rfcsr_write(rt2x00dev, 42, rfcsr);
 	rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
 	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
 	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
@@ -6347,15 +6375,20 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
 	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
 	rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
 	rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
-	rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
-	rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
-	rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
-	rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
-	rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
-	rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
-	rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
-	rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
-	rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
+	rfcsr = 0x2d;
+	if (!tx0_int_pa)
+		rt2x00_set_field8(&rfcsr, RFCSR50_TX0_EXT_PA, 1);
+	if (!tx1_int_pa)
+		rt2x00_set_field8(&rfcsr, RFCSR50_TX1_EXT_PA, 1);
+	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+	rt2800_rfcsr_write(rt2x00dev, 51, (tx0_int_pa ? 0x7f : 0x52));
+	rt2800_rfcsr_write(rt2x00dev, 52, (tx0_int_pa ? 0x00 : 0xc0));
+	rt2800_rfcsr_write(rt2x00dev, 53, (tx0_int_pa ? 0x52 : 0xd2));
+	rt2800_rfcsr_write(rt2x00dev, 54, (tx0_int_pa ? 0x1b : 0xc0));
+	rt2800_rfcsr_write(rt2x00dev, 55, (tx1_int_pa ? 0x7f : 0x52));
+	rt2800_rfcsr_write(rt2x00dev, 56, (tx1_int_pa ? 0x00 : 0xc0));
+	rt2800_rfcsr_write(rt2x00dev, 57, (tx0_int_pa ? 0x52 : 0x49));
+	rt2800_rfcsr_write(rt2x00dev, 58, (tx1_int_pa ? 0x1b : 0xc0));
 	rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
 	rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
 	rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
@@ -7320,7 +7353,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Detect if this device has Bluetooth co-existence.
 	 */
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
+	if (!rt2x00_rt(rt2x00dev, RT3352) &&
+	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
 		__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
 
 	/*
@@ -7349,6 +7383,22 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 					EIRP_MAX_TX_POWER_LIMIT)
 		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
 
+	/*
+	 * Detect if device uses internal or external PA
+	 */
+	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+
+	if (rt2x00_rt(rt2x00dev, RT3352)) {
+		if (!rt2x00_get_field16(eeprom,
+		    EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
+		    __set_bit(CAPABILITY_INTERNAL_PA_TX0,
+			      &rt2x00dev->cap_flags);
+		if (!rt2x00_get_field16(eeprom,
+		    EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352))
+		    __set_bit(CAPABILITY_INTERNAL_PA_TX1,
+			      &rt2x00dev->cap_flags);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index c27408b494ef..cfbf414c2627 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -716,6 +716,8 @@ enum rt2x00_capability_flags {
 	CAPABILITY_DOUBLE_ANTENNA,
 	CAPABILITY_BT_COEXIST,
 	CAPABILITY_VCO_RECALIBRATION,
+	CAPABILITY_INTERNAL_PA_TX0,
+	CAPABILITY_INTERNAL_PA_TX1,
 };
 
 /*
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 13/14] rt2x00: rt2800lib: add support for RT3352 with 20MHz crystal
From: Daniel Golle @ 2017-01-16  3:15 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Mathias Kresin <dev@kresin.me>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 50 +++++++++++++++++++++++++-
 drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  2 ++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 93c97eade334..cb1457595f05 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -36,6 +36,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include "rt2x00.h"
 #include "rt2800lib.h"
@@ -7675,6 +7676,27 @@ static const struct rf_channel rf_vals_5592_xtal40[] = {
 	{196, 83, 0, 12, 1},
 };
 
+/*
+ * RF value list for rt3xxx with Xtal20MHz
+ * Supports: 2.4 GHz (all) (RF3322)
+ */
+static const struct rf_channel rf_vals_xtal20mhz_3x[] = {
+	{1,    0xE2,	 2,  0x14},
+	{2,    0xE3,	 2,  0x14},
+	{3,    0xE4,	 2,  0x14},
+	{4,    0xE5,	 2,  0x14},
+	{5,    0xE6,	 2,  0x14},
+	{6,    0xE7,	 2,  0x14},
+	{7,    0xE8,	 2,  0x14},
+	{8,    0xE9,	 2,  0x14},
+	{9,    0xEA,	 2,  0x14},
+	{10,   0xEB,	 2,  0x14},
+	{11,   0xEC,	 2,  0x14},
+	{12,   0xED,	 2,  0x14},
+	{13,   0xEE,	 2,  0x14},
+	{14,   0xF0,	 2,  0x18},
+};
+
 static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
@@ -7764,7 +7786,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	case RF5390:
 	case RF5392:
 		spec->num_channels = 14;
-		spec->channels = rf_vals_3x;
+		if (spec->clk_is_20mhz)
+			spec->channels = rf_vals_xtal20mhz_3x;
+		else
+			spec->channels = rf_vals_3x;
 		break;
 
 	case RF3052:
@@ -7945,6 +7970,20 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
 	return 0;
 }
 
+int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev)
+{
+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+	struct clk *clk = clk_get(rt2x00dev->dev, NULL);
+
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	if (clk_get_rate(clk) == 20000000)
+		spec->clk_is_20mhz = 1;
+
+	return 0;
+}
+
 int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
@@ -7985,6 +8024,15 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
 
 	/*
+	 * Probe SoC clock.
+	 */
+	if (rt2x00_is_soc(rt2x00dev)) {
+		retval = rt2800_probe_clk(rt2x00dev);
+		if (retval)
+			return retval;
+	}
+
+	/*
 	 * Initialize hw specifications.
 	 */
 	retval = rt2800_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index cfbf414c2627..b1eec49b0dac 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -400,6 +400,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
  * @channels: Device/chipset specific channel values (See &struct rf_channel).
  * @channels_info: Additional information for channels (See &struct channel_info).
  * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
+ * @clk_is_20mhz: External crystal of WiSoC is 20MHz instead of 40MHz
  */
 struct hw_mode_spec {
 	unsigned int supported_bands;
@@ -415,6 +416,7 @@ struct hw_mode_spec {
 	const struct channel_info *channels_info;
 
 	struct ieee80211_sta_ht_cap ht;
+	int clk_is_20mhz;
 };
 
 /*
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 14/14] rt2x00: add support for RT5350 WiSoC
From: Daniel Golle @ 2017-01-16  3:17 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <874m114lwq.fsf@codeaurora.org>

From: Michel Stempin <michel.stempin@wanadoo.fr>

Support for the RT5350 WiSoC was added to OpenWrt after having a
lengthy debate about the legality of the original submission, see
https://lists.openwrt.org/pipermail/openwrt-devel/2013-January/018224.html
MTK/Ralink Acked replied and says we can merge this patch under the GPL.
https://dev.openwrt.org/changeset/36177

Signed-off-by: Serge Vasilugin <vasilugin@yandex.ru>
Tested-by: Michel Stempin <michel.stempin@wanadoo.fr>
Acked-by: John Crispin <blogic@openwrt.org>
[daniel@makrotopia.org: added commit message, fixed code formatting]

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800.h    |   1 +
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 131 +++++++++++++++++++++++--
 drivers/net/wireless/ralink/rt2x00/rt2x00.h    |   1 +
 3 files changed, 126 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
index e5110d24c0d7..7d101334d9f7 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
@@ -72,6 +72,7 @@
 #define RF5592				0x000f
 #define RF3070				0x3070
 #define RF3290				0x3290
+#define RF5350				0x5350
 #define RF5360				0x5360
 #define RF5362				0x5362
 #define RF5370				0x5370
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index cb1457595f05..709930ecb0d8 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -2838,6 +2838,13 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 
 				rt2800_rfcsr_write(rt2x00dev, 59,
 						   r59_non_bt[idx]);
+			} else if (rt2x00_rt(rt2x00dev, RT5350)) {
+				static const char r59_non_bt[] = {0x0b, 0x0b,
+					0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
+					0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
+
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_non_bt[idx]);
 			}
 		}
 	}
@@ -3275,6 +3282,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
 		break;
 	case RF3070:
+	case RF5350:
 	case RF5360:
 	case RF5362:
 	case RF5370:
@@ -3293,6 +3301,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00_rf(rt2x00dev, RF3070) ||
 	    rt2x00_rf(rt2x00dev, RF3290) ||
 	    rt2x00_rf(rt2x00dev, RF3322) ||
+	    rt2x00_rf(rt2x00dev, RF5350) ||
 	    rt2x00_rf(rt2x00dev, RF5360) ||
 	    rt2x00_rf(rt2x00dev, RF5362) ||
 	    rt2x00_rf(rt2x00dev, RF5370) ||
@@ -3550,7 +3559,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	/*
 	 * Clear update flag
 	 */
-	if (rt2x00_rt(rt2x00dev, RT3352)) {
+	if (rt2x00_rt(rt2x00dev, RT3352) ||
+	    rt2x00_rt(rt2x00dev, RT5350)) {
 		rt2800_bbp_read(rt2x00dev, 49, &bbp);
 		rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
 		rt2800_bbp_write(rt2x00dev, 49, bbp);
@@ -4431,6 +4441,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
 	case RF3053:
 	case RF3070:
 	case RF3290:
+	case RF5350:
 	case RF5360:
 	case RF5362:
 	case RF5370:
@@ -4837,6 +4848,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+	} else if (rt2x00_rt(rt2x00dev, RT5350)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 	} else {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -5488,9 +5501,13 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_bbp_write(rt2x00dev, 82, 0x62);
 
-	rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-	rt2800_bbp_write(rt2x00dev, 84, 0x99);
+	if (rt2x00_rt(rt2x00dev, RT5350)) {
+		rt2800_bbp_write(rt2x00dev, 83, 0x7a);
+		rt2800_bbp_write(rt2x00dev, 84, 0x9a);
+	} else {
+		rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+		rt2800_bbp_write(rt2x00dev, 84, 0x99);
+	}
 
 	rt2800_bbp_write(rt2x00dev, 86, 0x38);
 
@@ -5504,9 +5521,13 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_bbp_write(rt2x00dev, 104, 0x92);
 
-	rt2800_bbp_write(rt2x00dev, 105, 0x34);
-
-	rt2800_bbp_write(rt2x00dev, 106, 0x05);
+	if (rt2x00_rt(rt2x00dev, RT5350)) {
+		rt2800_bbp_write(rt2x00dev, 105, 0x3c);
+		rt2800_bbp_write(rt2x00dev, 106, 0x03);
+	} else {
+		rt2800_bbp_write(rt2x00dev, 105, 0x34);
+		rt2800_bbp_write(rt2x00dev, 106, 0x05);
+	}
 
 	rt2800_bbp_write(rt2x00dev, 120, 0x50);
 
@@ -5531,6 +5552,16 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)
 	rt2800_bbp_write(rt2x00dev, 143, 0xa2);
 
 	rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+
+	if (rt2x00_rt(rt2x00dev, RT5350)) {
+		/* Antenna Software OFDM */
+		rt2800_bbp_write(rt2x00dev, 150, 0x40);
+		/* Antenna Software CCK */
+		rt2800_bbp_write(rt2x00dev, 151, 0x30);
+		rt2800_bbp_write(rt2x00dev, 152, 0xa3);
+		/* Clear previously selected antenna */
+		rt2800_bbp_write(rt2x00dev, 154, 0);
+	}
 }
 
 static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
@@ -5831,6 +5862,7 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_init_bbp_3290(rt2x00dev);
 		break;
 	case RT3352:
+	case RT5350:
 		rt2800_init_bbp_3352(rt2x00dev);
 		break;
 	case RT3390:
@@ -6641,6 +6673,76 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
 	/* TODO: enable stream mode support */
 }
 
+static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev)
+{
+	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
+	rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
+	rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
+	rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+	rt2800_rfcsr_write(rt2x00dev, 4, 0x49);
+	rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+	rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+	rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+	rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+	if (rt2x00dev->spec.clk_is_20mhz)
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x1f);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+	rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 16, 0xc0);
+	rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+	rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+	rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+	rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 29, 0xd0);
+	rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+	rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+	rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+	rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+	rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
+	rt2800_rfcsr_write(rt2x00dev, 44, 0x0c);
+	rt2800_rfcsr_write(rt2x00dev, 45, 0xa6);
+	rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+	rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+	rt2800_rfcsr_write(rt2x00dev, 49, 0x80);
+	rt2800_rfcsr_write(rt2x00dev, 50, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 51, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+	rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
+	rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+	rt2800_rfcsr_write(rt2x00dev, 56, 0x82);
+	rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
+	rt2800_rfcsr_write(rt2x00dev, 59, 0x0b);
+	rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+	rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
+	rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
+	rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+}
+
 static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
 {
 	rt2800_rf_init_calibration(rt2x00dev, 2);
@@ -6878,6 +6980,9 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	case RT3593:
 		rt2800_init_rfcsr_3593(rt2x00dev);
 		break;
+	case RT5350:
+		rt2800_init_rfcsr_5350(rt2x00dev);
+		break;
 	case RT5390:
 		rt2800_init_rfcsr_5390(rt2x00dev);
 		break;
@@ -7131,6 +7236,12 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
 		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
 		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+	} else if (rt2x00_rt(rt2x00dev, RT5350)) {
+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1);
+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
+		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF3320);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
 	} else if (rt2x00_rt(rt2x00dev, RT2860) ||
 		   rt2x00_rt(rt2x00dev, RT2872)) {
 		/*
@@ -7265,6 +7376,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 	else if (rt2x00_rt(rt2x00dev, RT3352))
 		rf = RF3322;
+	else if (rt2x00_rt(rt2x00dev, RT5350))
+		rf = RF5350;
 	else
 		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 
@@ -7283,6 +7396,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RF3290:
 	case RF3320:
 	case RF3322:
+	case RF5350:
 	case RF5360:
 	case RF5362:
 	case RF5370:
@@ -7779,6 +7893,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	case RF3290:
 	case RF3320:
 	case RF3322:
+	case RF5350:
 	case RF5360:
 	case RF5362:
 	case RF5370:
@@ -7915,6 +8030,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	case RF3053:
 	case RF3070:
 	case RF3290:
+	case RF5350:
 	case RF5360:
 	case RF5362:
 	case RF5370:
@@ -7955,6 +8071,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
 	case RT3390:
 	case RT3572:
 	case RT3593:
+	case RT5350:
 	case RT5390:
 	case RT5392:
 	case RT5592:
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index b1eec49b0dac..3c447eca4ea2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -169,6 +169,7 @@ struct rt2x00_chip {
 #define RT3572		0x3572
 #define RT3593		0x3593
 #define RT3883		0x3883	/* WSOC */
+#define RT5350		0x5350  /* WSOC 2.4GHz */
 #define RT5390		0x5390  /* 2.4GHz */
 #define RT5392		0x5392  /* 2.4GHz */
 #define RT5592		0x5592
-- 
2.11.0

^ permalink raw reply related

* Re: pull-request: mac80211 2017-01-13
From: David Miller @ 2017-01-16  4:47 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20170113135516.19593-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Fri, 13 Jan 2017 14:55:15 +0100

> Here's another update for the current cycle. Some of those
> patches have been sitting in our tree and I haven't been
> pulling them out quickly enough - will try to do better...
> 
> Please pull and let me know if there's any problem.

Pulled, thank you.

^ permalink raw reply

* Re: support for Ampak AP6255 (bcm43455c0 with SDIO device ID 0xa9bf)
From: Arend Van Spriel @ 2017-01-16  9:43 UTC (permalink / raw)
  To: Martin Blumenstingl, brcm80211-dev-list.pdl
  Cc: hante.meuleman, linux-wireless
In-Reply-To: <CAFBinCDyQqDQ3mS4H0qZCzHs7xYKwxRqvfboU4ibdN0WNmpkQA@mail.gmail.com>

On 15-1-2017 0:18, Martin Blumenstingl wrote:
> Hello,
> 
> I recently got a "Khadas VIM Pro" (see [0] for more information)
> The "Pro" version comes with an AP6255 wifi chipset.
> Looking at the vendor firmware this seems to be a bcm43455 device: [1]
> 
> To my surprise brcmfmac from a mainline 4.10-rc3 kernel did not pick
> this device up.
> So I started investigating:
> $ grep "" /sys/class/mmc_host/mmc2/mmc2\:0001/mmc2\:0001\:*/{class,device,vendor}
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/class:0x00
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/class:0x00
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/class:0x02
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/device:0xa9bf
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/device:0xa9bf
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/device:0xa9bf
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/vendor:0x02d0
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/vendor:0x02d0
> /sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/vendor:0x02d0
> 
> I then went ahead and added the device ID to
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c (sample
> patch attached)
> as a result of that the device is now being detected.
> it boots fine with the firmware found in linux-firmware: [2] (plus the
> nvram.txt from the vendor repo [1] renamed to brcmfmac43455-sdio.txt)
> 
> $ cat /sys/kernel/debug/brcmfmac/mmc2\:0001\:1/revinfo
> vendorid: 0x14e4
> deviceid: 0x43ab
> radiorev: 0.88.3.11
> chipnum: 17221 (4345)
> chiprev: 6
> chippkg: 2
> corerev: 54
> boardid: 0x06e4
> boardvendor: 0x14e4
> boardrev: P304
> driverrev: 7.45.18
> ucoderev: 0
> bus: 0
> phytype: 11
> phyrev: 20
> anarev: 0
> nvramrev: 00079ac5
> 
> downloading a random 100MB file from the internet using curl confirms this.
> There are no hangs, connection drops, other devices are also working fine.
> 
> the problem I'm facing is very simply (but unfortunately a very common
> development problem): naming things (the SDIO_DEVICE_ID_BROADCOM_TODO
> constant)!
> there's already a definition for SDIO_DEVICE_ID_BROADCOM_4345 with
> value 0x4345, does that mean 0xa9bf should be
> SDIO_DEVICE_ID_BROADCOM_43455?

Yup. That seems a good name to me.

Regards,
Arend

> Regards,
> Martin
> 
> 
> [0] http://khadas.com/vim/
> [1] https://github.com/khadas/android_hardware_amlogic_wifi/tree/b6709758755568e4a0ff6e80993be0fc64c77fb9/bcm_ampak/config/6255
> [2] https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/commit/brcm/brcmfmac43455-sdio.bin?id=b9a38d041d38ac6cf47274e9933f8083e12fc601
> 

^ permalink raw reply

* Re: [PATCH v2 04/14] rt2x00: rt2800lib: fix beacon generation on RT3593
From: Stanislaw Gruszka @ 2017-01-16 10:04 UTC (permalink / raw)
  To: Daniel Golle
  Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
	evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170116030054.GA32187@makrotopia.org>

Hi

I looked more detail in the patches and now I think shared mem
and 16 hw beacons patches are not needed. Explanation is below.
Sorry for not pointing this before.

On Mon, Jan 16, 2017 at 04:01:14AM +0100, Daniel Golle wrote:
> From: Gabor Juhos <juhosg@openwrt.org>
> 
> On the RT3593 chipset, the beacon registers are located
> in the high 8KB part of the shared memory.
> 
> The high part of the shared memory is only accessible
> if it is explicitly selected. Add a helper function
> in order to be able to control the SHR_MSEL bit in
> the PBF_SYS_CTRL register. Also add a few more helper
> functions and use those to select the correct part of
> the shared memory before and after accessing the beacon
> registers.
> 
> The base addresses of the beacon registers are also
> different from the actually used values, so fix the
> 'rt2800_hw_beacon_base' function to return the correct
> values.
> 
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
<snip>
> +static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
> +{
> +	if (rt2x00_rt(rt2x00dev, RT3593))
> +		return true;

I just check that RT3593 (USB) device send beacon on AP mode when it is
configured previous way. I believe on RT3883 old way of configuring
beacons will work as well.

This change is only needed if we have to configure more than 8 beacons
i.e. add support to more than 8 APs per device. However there is no
patch increasing number of supported AP to 16 (by changing max_ap_intf),
so apparently nobody use this feature.

Hence I believe shared mem and 16 hw beacons is not needed and I prefer
to not add support for 16 APs per device with cost of adding this
additional complexity to the driver.

Stanislaw

^ permalink raw reply

* Re: [PATCH v2 09/14] rt2x00: rt2x00pci: set PCI MWI only if supported
From: Stanislaw Gruszka @ 2017-01-16 10:08 UTC (permalink / raw)
  To: Daniel Golle
  Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
	evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170116030613.GA32249@makrotopia.org>

On Mon, Jan 16, 2017 at 04:06:25AM +0100, Daniel Golle wrote:
> From: Claudio Mignanti <c.mignanti@gmail.com>
> 
> This is needed for devices without support for PCI MWI. See also
> https://dev.openwrt.org/changeset/21850
> 
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> ---
>  drivers/net/wireless/ralink/rt2x00/rt2x00pci.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
> index eb6dbcd4fddf..4becfeb75ba8 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
> @@ -94,8 +94,10 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
>  
>  	pci_set_master(pci_dev);
>  
> +#ifdef CONFIG_PCI_SET_MWI
>  	if (pci_set_mwi(pci_dev))
>  		rt2x00_probe_err("MWI not available\n");
> +#endif

There is no CONFIG_PCI_SET_MWI in the kernel. This patch is either not
needed (pci subsystem has own PCI_DISABLE_MWI define) or wrong (we
should not call this function for some devices).

Stanislaw

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox