diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2018-01-25 12:39:07 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-01-25 12:39:07 -0500 |
commit | f7a611707b2755e2658a80c96e276e9506e674c4 (patch) | |
tree | 4f80ed729f555a74553040820d22844eafa77591 | |
parent | f2f6026af7a894f7e3ac1280fc2fff1b2e4c739c (diff) | |
parent | d0bb950b9f5f4e5894ec3053c0d2bb24be5f8dd8 (diff) |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.16. Major changes:
wil6210
* add PCI device id for Talyn
* support flashless device
ath9k
* improve RSSI/signal accuracy on AR9003 series
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 133 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/boot_loader.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/fw.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/fw_inc.c | 167 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/interrupt.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 217 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pcie_bus.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 55 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 90 |
14 files changed, 752 insertions, 89 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index c2e210c0a770..f019a20e5a1f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3310,6 +3310,12 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, | |||
3310 | if (ar9300_check_eeprom_header(ah, read, cptr)) | 3310 | if (ar9300_check_eeprom_header(ah, read, cptr)) |
3311 | goto found; | 3311 | goto found; |
3312 | 3312 | ||
3313 | cptr = AR9300_BASE_ADDR_4K; | ||
3314 | ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n", | ||
3315 | cptr); | ||
3316 | if (ar9300_check_eeprom_header(ah, read, cptr)) | ||
3317 | goto found; | ||
3318 | |||
3313 | cptr = AR9300_BASE_ADDR_512; | 3319 | cptr = AR9300_BASE_ADDR_512; |
3314 | ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n", | 3320 | ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n", |
3315 | cptr); | 3321 | cptr); |
@@ -3430,6 +3436,60 @@ static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size, | |||
3430 | return len; | 3436 | return len; |
3431 | } | 3437 | } |
3432 | 3438 | ||
3439 | static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size, | ||
3440 | bool is_2g) | ||
3441 | { | ||
3442 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
3443 | struct ar9300_base_eep_hdr *pBase; | ||
3444 | struct ar9300_cal_data_per_freq_op_loop *cal_pier; | ||
3445 | int cal_pier_nr; | ||
3446 | int freq; | ||
3447 | int i, j; | ||
3448 | |||
3449 | pBase = &eep->baseEepHeader; | ||
3450 | |||
3451 | if (is_2g) | ||
3452 | cal_pier_nr = AR9300_NUM_2G_CAL_PIERS; | ||
3453 | else | ||
3454 | cal_pier_nr = AR9300_NUM_5G_CAL_PIERS; | ||
3455 | |||
3456 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
3457 | if (!((pBase->txrxMask >> i) & 1)) | ||
3458 | continue; | ||
3459 | |||
3460 | len += snprintf(buf + len, size - len, "Chain %d\n", i); | ||
3461 | |||
3462 | len += snprintf(buf + len, size - len, | ||
3463 | "Freq\t ref\tvolt\ttemp\tnf_cal\tnf_pow\trx_temp\n"); | ||
3464 | |||
3465 | for (j = 0; j < cal_pier_nr; j++) { | ||
3466 | if (is_2g) { | ||
3467 | cal_pier = &eep->calPierData2G[i][j]; | ||
3468 | freq = 2300 + eep->calFreqPier2G[j]; | ||
3469 | } else { | ||
3470 | cal_pier = &eep->calPierData5G[i][j]; | ||
3471 | freq = 4800 + eep->calFreqPier5G[j] * 5; | ||
3472 | } | ||
3473 | |||
3474 | len += snprintf(buf + len, size - len, | ||
3475 | "%d\t", freq); | ||
3476 | |||
3477 | len += snprintf(buf + len, size - len, | ||
3478 | "%d\t%d\t%d\t%d\t%d\t%d\n", | ||
3479 | cal_pier->refPower, | ||
3480 | cal_pier->voltMeas, | ||
3481 | cal_pier->tempMeas, | ||
3482 | cal_pier->rxTempMeas ? | ||
3483 | N2DBM(cal_pier->rxNoisefloorCal) : 0, | ||
3484 | cal_pier->rxTempMeas ? | ||
3485 | N2DBM(cal_pier->rxNoisefloorPower) : 0, | ||
3486 | cal_pier->rxTempMeas); | ||
3487 | } | ||
3488 | } | ||
3489 | |||
3490 | return len; | ||
3491 | } | ||
3492 | |||
3433 | static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | 3493 | static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, |
3434 | u8 *buf, u32 len, u32 size) | 3494 | u8 *buf, u32 len, u32 size) |
3435 | { | 3495 | { |
@@ -3441,10 +3501,18 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
3441 | "%20s :\n", "2GHz modal Header"); | 3501 | "%20s :\n", "2GHz modal Header"); |
3442 | len = ar9003_dump_modal_eeprom(buf, len, size, | 3502 | len = ar9003_dump_modal_eeprom(buf, len, size, |
3443 | &eep->modalHeader2G); | 3503 | &eep->modalHeader2G); |
3444 | len += scnprintf(buf + len, size - len, | 3504 | |
3505 | len += scnprintf(buf + len, size - len, "Calibration data\n"); | ||
3506 | len = ar9003_dump_cal_data(ah, buf, len, size, true); | ||
3507 | |||
3508 | len += snprintf(buf + len, size - len, | ||
3445 | "%20s :\n", "5GHz modal Header"); | 3509 | "%20s :\n", "5GHz modal Header"); |
3446 | len = ar9003_dump_modal_eeprom(buf, len, size, | 3510 | len = ar9003_dump_modal_eeprom(buf, len, size, |
3447 | &eep->modalHeader5G); | 3511 | &eep->modalHeader5G); |
3512 | |||
3513 | len += snprintf(buf + len, size - len, "Calibration data\n"); | ||
3514 | len = ar9003_dump_cal_data(ah, buf, len, size, false); | ||
3515 | |||
3448 | goto out; | 3516 | goto out; |
3449 | } | 3517 | } |
3450 | 3518 | ||
@@ -4683,7 +4751,8 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
4683 | int ichain, | 4751 | int ichain, |
4684 | int *pfrequency, | 4752 | int *pfrequency, |
4685 | int *pcorrection, | 4753 | int *pcorrection, |
4686 | int *ptemperature, int *pvoltage) | 4754 | int *ptemperature, int *pvoltage, |
4755 | int *pnf_cal, int *pnf_power) | ||
4687 | { | 4756 | { |
4688 | u8 *pCalPier; | 4757 | u8 *pCalPier; |
4689 | struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct; | 4758 | struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct; |
@@ -4725,6 +4794,10 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
4725 | *pcorrection = pCalPierStruct->refPower; | 4794 | *pcorrection = pCalPierStruct->refPower; |
4726 | *ptemperature = pCalPierStruct->tempMeas; | 4795 | *ptemperature = pCalPierStruct->tempMeas; |
4727 | *pvoltage = pCalPierStruct->voltMeas; | 4796 | *pvoltage = pCalPierStruct->voltMeas; |
4797 | *pnf_cal = pCalPierStruct->rxTempMeas ? | ||
4798 | N2DBM(pCalPierStruct->rxNoisefloorCal) : 0; | ||
4799 | *pnf_power = pCalPierStruct->rxTempMeas ? | ||
4800 | N2DBM(pCalPierStruct->rxNoisefloorPower) : 0; | ||
4728 | 4801 | ||
4729 | return 0; | 4802 | return 0; |
4730 | } | 4803 | } |
@@ -4889,14 +4962,18 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4889 | int mode; | 4962 | int mode; |
4890 | int lfrequency[AR9300_MAX_CHAINS], | 4963 | int lfrequency[AR9300_MAX_CHAINS], |
4891 | lcorrection[AR9300_MAX_CHAINS], | 4964 | lcorrection[AR9300_MAX_CHAINS], |
4892 | ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS]; | 4965 | ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS], |
4966 | lnf_cal[AR9300_MAX_CHAINS], lnf_pwr[AR9300_MAX_CHAINS]; | ||
4893 | int hfrequency[AR9300_MAX_CHAINS], | 4967 | int hfrequency[AR9300_MAX_CHAINS], |
4894 | hcorrection[AR9300_MAX_CHAINS], | 4968 | hcorrection[AR9300_MAX_CHAINS], |
4895 | htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS]; | 4969 | htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS], |
4970 | hnf_cal[AR9300_MAX_CHAINS], hnf_pwr[AR9300_MAX_CHAINS]; | ||
4896 | int fdiff; | 4971 | int fdiff; |
4897 | int correction[AR9300_MAX_CHAINS], | 4972 | int correction[AR9300_MAX_CHAINS], |
4898 | voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS]; | 4973 | voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS], |
4899 | int pfrequency, pcorrection, ptemperature, pvoltage; | 4974 | nf_cal[AR9300_MAX_CHAINS], nf_pwr[AR9300_MAX_CHAINS]; |
4975 | int pfrequency, pcorrection, ptemperature, pvoltage, | ||
4976 | pnf_cal, pnf_pwr; | ||
4900 | struct ath_common *common = ath9k_hw_common(ah); | 4977 | struct ath_common *common = ath9k_hw_common(ah); |
4901 | 4978 | ||
4902 | mode = (frequency >= 4000); | 4979 | mode = (frequency >= 4000); |
@@ -4914,7 +4991,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4914 | for (ipier = 0; ipier < npier; ipier++) { | 4991 | for (ipier = 0; ipier < npier; ipier++) { |
4915 | if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain, | 4992 | if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain, |
4916 | &pfrequency, &pcorrection, | 4993 | &pfrequency, &pcorrection, |
4917 | &ptemperature, &pvoltage)) { | 4994 | &ptemperature, &pvoltage, |
4995 | &pnf_cal, &pnf_pwr)) { | ||
4918 | fdiff = frequency - pfrequency; | 4996 | fdiff = frequency - pfrequency; |
4919 | 4997 | ||
4920 | /* | 4998 | /* |
@@ -4936,6 +5014,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4936 | htemperature[ichain] = | 5014 | htemperature[ichain] = |
4937 | ptemperature; | 5015 | ptemperature; |
4938 | hvoltage[ichain] = pvoltage; | 5016 | hvoltage[ichain] = pvoltage; |
5017 | hnf_cal[ichain] = pnf_cal; | ||
5018 | hnf_pwr[ichain] = pnf_pwr; | ||
4939 | } | 5019 | } |
4940 | } | 5020 | } |
4941 | if (fdiff >= 0) { | 5021 | if (fdiff >= 0) { |
@@ -4952,6 +5032,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4952 | ltemperature[ichain] = | 5032 | ltemperature[ichain] = |
4953 | ptemperature; | 5033 | ptemperature; |
4954 | lvoltage[ichain] = pvoltage; | 5034 | lvoltage[ichain] = pvoltage; |
5035 | lnf_cal[ichain] = pnf_cal; | ||
5036 | lnf_pwr[ichain] = pnf_pwr; | ||
4955 | } | 5037 | } |
4956 | } | 5038 | } |
4957 | } | 5039 | } |
@@ -4960,15 +5042,20 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4960 | 5042 | ||
4961 | /* interpolate */ | 5043 | /* interpolate */ |
4962 | for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { | 5044 | for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { |
4963 | ath_dbg(common, EEPROM, "ch=%d f=%d low=%d %d h=%d %d\n", | 5045 | ath_dbg(common, EEPROM, |
5046 | "ch=%d f=%d low=%d %d h=%d %d n=%d %d p=%d %d\n", | ||
4964 | ichain, frequency, lfrequency[ichain], | 5047 | ichain, frequency, lfrequency[ichain], |
4965 | lcorrection[ichain], hfrequency[ichain], | 5048 | lcorrection[ichain], hfrequency[ichain], |
4966 | hcorrection[ichain]); | 5049 | hcorrection[ichain], lnf_cal[ichain], |
5050 | hnf_cal[ichain], lnf_pwr[ichain], | ||
5051 | hnf_pwr[ichain]); | ||
4967 | /* they're the same, so just pick one */ | 5052 | /* they're the same, so just pick one */ |
4968 | if (hfrequency[ichain] == lfrequency[ichain]) { | 5053 | if (hfrequency[ichain] == lfrequency[ichain]) { |
4969 | correction[ichain] = lcorrection[ichain]; | 5054 | correction[ichain] = lcorrection[ichain]; |
4970 | voltage[ichain] = lvoltage[ichain]; | 5055 | voltage[ichain] = lvoltage[ichain]; |
4971 | temperature[ichain] = ltemperature[ichain]; | 5056 | temperature[ichain] = ltemperature[ichain]; |
5057 | nf_cal[ichain] = lnf_cal[ichain]; | ||
5058 | nf_pwr[ichain] = lnf_pwr[ichain]; | ||
4972 | } | 5059 | } |
4973 | /* the low frequency is good */ | 5060 | /* the low frequency is good */ |
4974 | else if (frequency - lfrequency[ichain] < 1000) { | 5061 | else if (frequency - lfrequency[ichain] < 1000) { |
@@ -4992,12 +5079,26 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
4992 | hfrequency[ichain], | 5079 | hfrequency[ichain], |
4993 | lvoltage[ichain], | 5080 | lvoltage[ichain], |
4994 | hvoltage[ichain]); | 5081 | hvoltage[ichain]); |
5082 | |||
5083 | nf_cal[ichain] = interpolate(frequency, | ||
5084 | lfrequency[ichain], | ||
5085 | hfrequency[ichain], | ||
5086 | lnf_cal[ichain], | ||
5087 | hnf_cal[ichain]); | ||
5088 | |||
5089 | nf_pwr[ichain] = interpolate(frequency, | ||
5090 | lfrequency[ichain], | ||
5091 | hfrequency[ichain], | ||
5092 | lnf_pwr[ichain], | ||
5093 | hnf_pwr[ichain]); | ||
4995 | } | 5094 | } |
4996 | /* only low is good, use it */ | 5095 | /* only low is good, use it */ |
4997 | else { | 5096 | else { |
4998 | correction[ichain] = lcorrection[ichain]; | 5097 | correction[ichain] = lcorrection[ichain]; |
4999 | temperature[ichain] = ltemperature[ichain]; | 5098 | temperature[ichain] = ltemperature[ichain]; |
5000 | voltage[ichain] = lvoltage[ichain]; | 5099 | voltage[ichain] = lvoltage[ichain]; |
5100 | nf_cal[ichain] = lnf_cal[ichain]; | ||
5101 | nf_pwr[ichain] = lnf_pwr[ichain]; | ||
5001 | } | 5102 | } |
5002 | } | 5103 | } |
5003 | /* only high is good, use it */ | 5104 | /* only high is good, use it */ |
@@ -5005,10 +5106,14 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
5005 | correction[ichain] = hcorrection[ichain]; | 5106 | correction[ichain] = hcorrection[ichain]; |
5006 | temperature[ichain] = htemperature[ichain]; | 5107 | temperature[ichain] = htemperature[ichain]; |
5007 | voltage[ichain] = hvoltage[ichain]; | 5108 | voltage[ichain] = hvoltage[ichain]; |
5109 | nf_cal[ichain] = hnf_cal[ichain]; | ||
5110 | nf_pwr[ichain] = hnf_pwr[ichain]; | ||
5008 | } else { /* nothing is good, presume 0???? */ | 5111 | } else { /* nothing is good, presume 0???? */ |
5009 | correction[ichain] = 0; | 5112 | correction[ichain] = 0; |
5010 | temperature[ichain] = 0; | 5113 | temperature[ichain] = 0; |
5011 | voltage[ichain] = 0; | 5114 | voltage[ichain] = 0; |
5115 | nf_cal[ichain] = 0; | ||
5116 | nf_pwr[ichain] = 0; | ||
5012 | } | 5117 | } |
5013 | } | 5118 | } |
5014 | 5119 | ||
@@ -5019,6 +5124,16 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
5019 | "for frequency=%d, calibration correction = %d %d %d\n", | 5124 | "for frequency=%d, calibration correction = %d %d %d\n", |
5020 | frequency, correction[0], correction[1], correction[2]); | 5125 | frequency, correction[0], correction[1], correction[2]); |
5021 | 5126 | ||
5127 | /* Store calibrated noise floor values */ | ||
5128 | for (ichain = 0; ichain < AR5416_MAX_CHAINS; ichain++) | ||
5129 | if (mode) { | ||
5130 | ah->nf_5g.cal[ichain] = nf_cal[ichain]; | ||
5131 | ah->nf_5g.pwr[ichain] = nf_pwr[ichain]; | ||
5132 | } else { | ||
5133 | ah->nf_2g.cal[ichain] = nf_cal[ichain]; | ||
5134 | ah->nf_2g.pwr[ichain] = nf_pwr[ichain]; | ||
5135 | } | ||
5136 | |||
5022 | return 0; | 5137 | return 0; |
5023 | } | 5138 | } |
5024 | 5139 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index bd2269c7de6b..e8fda54acfe3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -62,6 +62,16 @@ | |||
62 | */ | 62 | */ |
63 | #define AR9300_PWR_TABLE_OFFSET 0 | 63 | #define AR9300_PWR_TABLE_OFFSET 0 |
64 | 64 | ||
65 | /* Noise power data definitions | ||
66 | * units are: 4 x dBm - NOISE_PWR_DATA_OFFSET | ||
67 | * (e.g. -25 = (-25/4 - 90) = -96.25 dBm) | ||
68 | * range (for 6 signed bits) is (-32 to 31) + offset => -122dBm to -59dBm | ||
69 | * resolution (2 bits) is 0.25dBm | ||
70 | */ | ||
71 | #define NOISE_PWR_DATA_OFFSET -90 | ||
72 | #define NOISE_PWR_DBM_2_INT(_p) ((((_p) + 3) >> 2) + NOISE_PWR_DATA_OFFSET) | ||
73 | #define N2DBM(_p) NOISE_PWR_DBM_2_INT(_p) | ||
74 | |||
65 | /* byte addressable */ | 75 | /* byte addressable */ |
66 | #define AR9300_EEPROM_SIZE (16*1024) | 76 | #define AR9300_EEPROM_SIZE (16*1024) |
67 | 77 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 13ab6bc46775..3d9447e21025 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -58,19 +58,25 @@ static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, | |||
58 | } | 58 | } |
59 | 59 | ||
60 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | 60 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, |
61 | struct ath9k_channel *chan) | 61 | struct ath9k_channel *chan, |
62 | int chain) | ||
62 | { | 63 | { |
63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | 64 | s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain]; |
65 | |||
66 | if (calib_nf) | ||
67 | return calib_nf; | ||
68 | else | ||
69 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | ||
64 | } | 70 | } |
65 | 71 | ||
66 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, | 72 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, |
67 | s16 nf) | 73 | s16 nf) |
68 | { | 74 | { |
69 | s8 noise = ATH_DEFAULT_NOISE_FLOOR; | 75 | s8 noise = ath9k_hw_get_default_nf(ah, chan, 0); |
70 | 76 | ||
71 | if (nf) { | 77 | if (nf) { |
72 | s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - | 78 | s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - |
73 | ath9k_hw_get_default_nf(ah, chan); | 79 | ath9k_hw_get_default_nf(ah, chan, 0); |
74 | if (delta > 0) | 80 | if (delta > 0) |
75 | noise += delta; | 81 | noise += delta; |
76 | } | 82 | } |
@@ -240,7 +246,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
240 | unsigned i, j; | 246 | unsigned i, j; |
241 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 247 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
242 | struct ath_common *common = ath9k_hw_common(ah); | 248 | struct ath_common *common = ath9k_hw_common(ah); |
243 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 249 | s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal; |
244 | u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL); | 250 | u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL); |
245 | 251 | ||
246 | if (ah->caldata) | 252 | if (ah->caldata) |
@@ -258,8 +264,13 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
258 | nfval = ah->nf_override; | 264 | nfval = ah->nf_override; |
259 | else if (h) | 265 | else if (h) |
260 | nfval = h[i].privNF; | 266 | nfval = h[i].privNF; |
261 | else | 267 | else { |
262 | nfval = default_nf; | 268 | /* Try to get calibrated noise floor value */ |
269 | nfval = | ||
270 | ath9k_hw_get_nf_limits(ah, chan)->cal[i]; | ||
271 | if (nfval > -60 || nfval < -127) | ||
272 | nfval = default_nf; | ||
273 | } | ||
263 | 274 | ||
264 | REG_RMW(ah, ah->nf_regs[i], | 275 | REG_RMW(ah, ah->nf_regs[i], |
265 | (((u32) nfval << 1) & 0x1ff), 0x1ff); | 276 | (((u32) nfval << 1) & 0x1ff), 0x1ff); |
@@ -429,20 +440,19 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
429 | struct ath9k_channel *chan) | 440 | struct ath9k_channel *chan) |
430 | { | 441 | { |
431 | struct ath9k_nfcal_hist *h; | 442 | struct ath9k_nfcal_hist *h; |
432 | s16 default_nf; | 443 | int i, j, k = 0; |
433 | int i, j; | ||
434 | 444 | ||
435 | ah->caldata->channel = chan->channel; | 445 | ah->caldata->channel = chan->channel; |
436 | ah->caldata->channelFlags = chan->channelFlags; | 446 | ah->caldata->channelFlags = chan->channelFlags; |
437 | h = ah->caldata->nfCalHist; | 447 | h = ah->caldata->nfCalHist; |
438 | default_nf = ath9k_hw_get_default_nf(ah, chan); | ||
439 | for (i = 0; i < NUM_NF_READINGS; i++) { | 448 | for (i = 0; i < NUM_NF_READINGS; i++) { |
440 | h[i].currIndex = 0; | 449 | h[i].currIndex = 0; |
441 | h[i].privNF = default_nf; | 450 | h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k); |
442 | h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; | 451 | h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; |
443 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | 452 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) |
444 | h[i].nfCalBuffer[j] = default_nf; | 453 | h[i].nfCalBuffer[j] = h[i].privNF; |
445 | } | 454 | if (++k >= AR5416_MAX_CHAINS) |
455 | k = 0; | ||
446 | } | 456 | } |
447 | } | 457 | } |
448 | 458 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0d6c07c77372..9804a24a2dc0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -754,6 +754,8 @@ struct ath_nf_limits { | |||
754 | s16 max; | 754 | s16 max; |
755 | s16 min; | 755 | s16 min; |
756 | s16 nominal; | 756 | s16 nominal; |
757 | s16 cal[AR5416_MAX_CHAINS]; | ||
758 | s16 pwr[AR5416_MAX_CHAINS]; | ||
757 | }; | 759 | }; |
758 | 760 | ||
759 | enum ath_cal_list { | 761 | enum ath_cal_list { |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 2197aee2bb72..a8ac42c96d71 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
826 | sc->rx.discard_next = false; | 826 | sc->rx.discard_next = false; |
827 | 827 | ||
828 | /* | 828 | /* |
829 | * Discard zero-length packets. | 829 | * Discard zero-length packets and packets smaller than an ACK |
830 | */ | 830 | */ |
831 | if (!rx_stats->rs_datalen) { | 831 | if (rx_stats->rs_datalen < 10) { |
832 | RX_STAT_INC(rx_len_err); | 832 | RX_STAT_INC(rx_len_err); |
833 | goto corrupt; | 833 | goto corrupt; |
834 | } | 834 | } |
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d5c810a8cc52..a3f1f7d042a4 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
@@ -236,6 +236,14 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn | |||
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
238 | 238 | ||
239 | static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) | ||
240 | { | ||
241 | size_t size; | ||
242 | |||
243 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); | ||
244 | dma_free_coherent(dev, size,wcn_ch->cpu_addr, wcn_ch->dma_addr); | ||
245 | } | ||
246 | |||
239 | static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, | 247 | static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, |
240 | struct wcn36xx_dxe_mem_pool *pool) | 248 | struct wcn36xx_dxe_mem_pool *pool) |
241 | { | 249 | { |
@@ -722,7 +730,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
722 | /***************************************/ | 730 | /***************************************/ |
723 | /* Init descriptors for TX LOW channel */ | 731 | /* Init descriptors for TX LOW channel */ |
724 | /***************************************/ | 732 | /***************************************/ |
725 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); | 733 | ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); |
734 | if (ret) { | ||
735 | dev_err(wcn->dev, "Error allocating descriptor\n"); | ||
736 | return ret; | ||
737 | } | ||
726 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); | 738 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); |
727 | 739 | ||
728 | /* Write channel head to a NEXT register */ | 740 | /* Write channel head to a NEXT register */ |
@@ -740,7 +752,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
740 | /***************************************/ | 752 | /***************************************/ |
741 | /* Init descriptors for TX HIGH channel */ | 753 | /* Init descriptors for TX HIGH channel */ |
742 | /***************************************/ | 754 | /***************************************/ |
743 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); | 755 | ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); |
756 | if (ret) { | ||
757 | dev_err(wcn->dev, "Error allocating descriptor\n"); | ||
758 | goto out_err_txh_ch; | ||
759 | } | ||
760 | |||
744 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); | 761 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); |
745 | 762 | ||
746 | /* Write channel head to a NEXT register */ | 763 | /* Write channel head to a NEXT register */ |
@@ -760,7 +777,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
760 | /***************************************/ | 777 | /***************************************/ |
761 | /* Init descriptors for RX LOW channel */ | 778 | /* Init descriptors for RX LOW channel */ |
762 | /***************************************/ | 779 | /***************************************/ |
763 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); | 780 | ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); |
781 | if (ret) { | ||
782 | dev_err(wcn->dev, "Error allocating descriptor\n"); | ||
783 | goto out_err_rxl_ch; | ||
784 | } | ||
785 | |||
764 | 786 | ||
765 | /* For RX we need to preallocated buffers */ | 787 | /* For RX we need to preallocated buffers */ |
766 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); | 788 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); |
@@ -790,7 +812,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
790 | /***************************************/ | 812 | /***************************************/ |
791 | /* Init descriptors for RX HIGH channel */ | 813 | /* Init descriptors for RX HIGH channel */ |
792 | /***************************************/ | 814 | /***************************************/ |
793 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); | 815 | ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); |
816 | if (ret) { | ||
817 | dev_err(wcn->dev, "Error allocating descriptor\n"); | ||
818 | goto out_err_rxh_ch; | ||
819 | } | ||
794 | 820 | ||
795 | /* For RX we need to prealocat buffers */ | 821 | /* For RX we need to prealocat buffers */ |
796 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); | 822 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); |
@@ -819,11 +845,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
819 | 845 | ||
820 | ret = wcn36xx_dxe_request_irqs(wcn); | 846 | ret = wcn36xx_dxe_request_irqs(wcn); |
821 | if (ret < 0) | 847 | if (ret < 0) |
822 | goto out_err; | 848 | goto out_err_irq; |
823 | 849 | ||
824 | return 0; | 850 | return 0; |
825 | 851 | ||
826 | out_err: | 852 | out_err_irq: |
853 | wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_h_ch); | ||
854 | out_err_rxh_ch: | ||
855 | wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_l_ch); | ||
856 | out_err_rxl_ch: | ||
857 | wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_h_ch); | ||
858 | out_err_txh_ch: | ||
859 | wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_l_ch); | ||
860 | |||
827 | return ret; | 861 | return ret; |
828 | } | 862 | } |
829 | 863 | ||
diff --git a/drivers/net/wireless/ath/wil6210/boot_loader.h b/drivers/net/wireless/ath/wil6210/boot_loader.h index c131b5e1292f..d32c1f4e533a 100644 --- a/drivers/net/wireless/ath/wil6210/boot_loader.h +++ b/drivers/net/wireless/ath/wil6210/boot_loader.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Copyright (c) 2015 Qualcomm Atheros, Inc. | 1 | /* Copyright (c) 2015 Qualcomm Atheros, Inc. |
2 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
2 | * | 3 | * |
3 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
4 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -39,7 +40,8 @@ struct bl_dedicated_registers_v1 { | |||
39 | /* valid only for version 2 and above */ | 40 | /* valid only for version 2 and above */ |
40 | __le32 bl_assert_code; /* 0x880A58 BL Assert code */ | 41 | __le32 bl_assert_code; /* 0x880A58 BL Assert code */ |
41 | __le32 bl_assert_blink; /* 0x880A5C BL Assert Branch */ | 42 | __le32 bl_assert_blink; /* 0x880A5C BL Assert Branch */ |
42 | __le32 bl_reserved[22]; /* 0x880A60 - 0x880AB4 */ | 43 | __le32 bl_shutdown_handshake; /* 0x880A60 BL cleaner shutdown */ |
44 | __le32 bl_reserved[21]; /* 0x880A64 - 0x880AB4 */ | ||
43 | __le32 bl_magic_number; /* 0x880AB8 BL Magic number */ | 45 | __le32 bl_magic_number; /* 0x880AB8 BL Magic number */ |
44 | } __packed; | 46 | } __packed; |
45 | 47 | ||
@@ -58,4 +60,9 @@ struct bl_dedicated_registers_v0 { | |||
58 | u8 mac_address[6]; /* 0x880A4c BL mac address */ | 60 | u8 mac_address[6]; /* 0x880A4c BL mac address */ |
59 | } __packed; | 61 | } __packed; |
60 | 62 | ||
63 | /* bits for bl_shutdown_handshake */ | ||
64 | #define BL_SHUTDOWN_HS_GRTD BIT(0) | ||
65 | #define BL_SHUTDOWN_HS_RTD BIT(1) | ||
66 | #define BL_SHUTDOWN_HS_PROT_VER(x) WIL_GET_BITS(x, 28, 31) | ||
67 | |||
61 | #endif /* BOOT_LOADER_EXPORT_H_ */ | 68 | #endif /* BOOT_LOADER_EXPORT_H_ */ |
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h index 2f2b910501ba..2c7b24f61587 100644 --- a/drivers/net/wireless/ath/wil6210/fw.h +++ b/drivers/net/wireless/ath/wil6210/fw.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -58,15 +59,30 @@ struct wil_fw_record_comment { /* type == wil_fw_type_comment */ | |||
58 | u8 data[0]; /* free-form data [data_size], see above */ | 59 | u8 data[0]; /* free-form data [data_size], see above */ |
59 | } __packed; | 60 | } __packed; |
60 | 61 | ||
62 | /* Comment header - common for all comment record types */ | ||
63 | struct wil_fw_record_comment_hdr { | ||
64 | __le32 magic; | ||
65 | }; | ||
66 | |||
61 | /* FW capabilities encoded inside a comment record */ | 67 | /* FW capabilities encoded inside a comment record */ |
62 | #define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba) | 68 | #define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba) |
63 | struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ | 69 | struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ |
64 | /* identifies capabilities record */ | 70 | /* identifies capabilities record */ |
65 | __le32 magic; | 71 | struct wil_fw_record_comment_hdr hdr; |
66 | /* capabilities (variable size), see enum wmi_fw_capability */ | 72 | /* capabilities (variable size), see enum wmi_fw_capability */ |
67 | u8 capabilities[0]; | 73 | u8 capabilities[0]; |
68 | }; | 74 | }; |
69 | 75 | ||
76 | /* brd file info encoded inside a comment record */ | ||
77 | #define WIL_BRD_FILE_MAGIC (0xabcddcbb) | ||
78 | struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ | ||
79 | /* identifies brd file record */ | ||
80 | struct wil_fw_record_comment_hdr hdr; | ||
81 | __le32 version; | ||
82 | __le32 base_addr; | ||
83 | __le32 max_size_bytes; | ||
84 | } __packed; | ||
85 | |||
70 | /* perform action | 86 | /* perform action |
71 | * data_size = @head.size - offsetof(struct wil_fw_record_action, data) | 87 | * data_size = @head.size - offsetof(struct wil_fw_record_action, data) |
72 | */ | 88 | */ |
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 77d1902947e3..914c0106e94b 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -128,14 +129,13 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data, | |||
128 | } | 129 | } |
129 | 130 | ||
130 | static int | 131 | static int |
131 | fw_handle_comment(struct wil6210_priv *wil, const void *data, | 132 | fw_handle_capabilities(struct wil6210_priv *wil, const void *data, |
132 | size_t size) | 133 | size_t size) |
133 | { | 134 | { |
134 | const struct wil_fw_record_capabilities *rec = data; | 135 | const struct wil_fw_record_capabilities *rec = data; |
135 | size_t capa_size; | 136 | size_t capa_size; |
136 | 137 | ||
137 | if (size < sizeof(*rec) || | 138 | if (size < sizeof(*rec)) { |
138 | le32_to_cpu(rec->magic) != WIL_FW_CAPABILITIES_MAGIC) { | ||
139 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, | 139 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, |
140 | data, size, true); | 140 | data, size, true); |
141 | return 0; | 141 | return 0; |
@@ -151,8 +151,56 @@ fw_handle_comment(struct wil6210_priv *wil, const void *data, | |||
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | static int fw_handle_data(struct wil6210_priv *wil, const void *data, | 154 | static int |
155 | size_t size) | 155 | fw_handle_brd_file(struct wil6210_priv *wil, const void *data, |
156 | size_t size) | ||
157 | { | ||
158 | const struct wil_fw_record_brd_file *rec = data; | ||
159 | |||
160 | if (size < sizeof(*rec)) { | ||
161 | wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1, | ||
162 | data, size, true); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | wil->brd_file_addr = le32_to_cpu(rec->base_addr); | ||
167 | wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes); | ||
168 | |||
169 | wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n", | ||
170 | wil->brd_file_addr, wil->brd_file_max_size); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int | ||
176 | fw_handle_comment(struct wil6210_priv *wil, const void *data, | ||
177 | size_t size) | ||
178 | { | ||
179 | const struct wil_fw_record_comment_hdr *hdr = data; | ||
180 | u32 magic; | ||
181 | int rc = 0; | ||
182 | |||
183 | if (size < sizeof(*hdr)) | ||
184 | return 0; | ||
185 | |||
186 | magic = le32_to_cpu(hdr->magic); | ||
187 | |||
188 | switch (magic) { | ||
189 | case WIL_FW_CAPABILITIES_MAGIC: | ||
190 | wil_dbg_fw(wil, "magic is WIL_FW_CAPABILITIES_MAGIC\n"); | ||
191 | rc = fw_handle_capabilities(wil, data, size); | ||
192 | break; | ||
193 | case WIL_BRD_FILE_MAGIC: | ||
194 | wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n"); | ||
195 | rc = fw_handle_brd_file(wil, data, size); | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | return rc; | ||
200 | } | ||
201 | |||
202 | static int __fw_handle_data(struct wil6210_priv *wil, const void *data, | ||
203 | size_t size, __le32 addr) | ||
156 | { | 204 | { |
157 | const struct wil_fw_record_data *d = data; | 205 | const struct wil_fw_record_data *d = data; |
158 | void __iomem *dst; | 206 | void __iomem *dst; |
@@ -163,16 +211,23 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data, | |||
163 | return -EINVAL; | 211 | return -EINVAL; |
164 | } | 212 | } |
165 | 213 | ||
166 | if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) | 214 | if (!wil_fw_addr_check(wil, &dst, addr, s, "address")) |
167 | return -EINVAL; | 215 | return -EINVAL; |
168 | wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), | 216 | wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(addr), s); |
169 | s); | ||
170 | wil_memcpy_toio_32(dst, d->data, s); | 217 | wil_memcpy_toio_32(dst, d->data, s); |
171 | wmb(); /* finish before processing next record */ | 218 | wmb(); /* finish before processing next record */ |
172 | 219 | ||
173 | return 0; | 220 | return 0; |
174 | } | 221 | } |
175 | 222 | ||
223 | static int fw_handle_data(struct wil6210_priv *wil, const void *data, | ||
224 | size_t size) | ||
225 | { | ||
226 | const struct wil_fw_record_data *d = data; | ||
227 | |||
228 | return __fw_handle_data(wil, data, size, d->addr); | ||
229 | } | ||
230 | |||
176 | static int fw_handle_fill(struct wil6210_priv *wil, const void *data, | 231 | static int fw_handle_fill(struct wil6210_priv *wil, const void *data, |
177 | size_t size) | 232 | size_t size) |
178 | { | 233 | { |
@@ -552,6 +607,100 @@ out: | |||
552 | } | 607 | } |
553 | 608 | ||
554 | /** | 609 | /** |
610 | * wil_brd_process - process section from BRD file | ||
611 | * | ||
612 | * Return error code | ||
613 | */ | ||
614 | static int wil_brd_process(struct wil6210_priv *wil, const void *data, | ||
615 | size_t size) | ||
616 | { | ||
617 | int rc = 0; | ||
618 | const struct wil_fw_record_head *hdr = data; | ||
619 | size_t s, hdr_sz; | ||
620 | u16 type; | ||
621 | |||
622 | /* Assuming the board file includes only one header record and one data | ||
623 | * record. Each record starts with wil_fw_record_head. | ||
624 | */ | ||
625 | if (size < sizeof(*hdr)) | ||
626 | return -EINVAL; | ||
627 | s = sizeof(*hdr) + le32_to_cpu(hdr->size); | ||
628 | if (s > size) | ||
629 | return -EINVAL; | ||
630 | |||
631 | /* Skip the header record and handle the data record */ | ||
632 | hdr = (const void *)hdr + s; | ||
633 | size -= s; | ||
634 | if (size < sizeof(*hdr)) | ||
635 | return -EINVAL; | ||
636 | hdr_sz = le32_to_cpu(hdr->size); | ||
637 | |||
638 | if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size) | ||
639 | return -EINVAL; | ||
640 | if (sizeof(*hdr) + hdr_sz > size) | ||
641 | return -EINVAL; | ||
642 | if (hdr_sz % 4) { | ||
643 | wil_err_fw(wil, "unaligned record size: %zu\n", | ||
644 | hdr_sz); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | type = le16_to_cpu(hdr->type); | ||
648 | if (type != wil_fw_type_data) { | ||
649 | wil_err_fw(wil, "invalid record type for board file: %d\n", | ||
650 | type); | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | if (hdr_sz < sizeof(struct wil_fw_record_data)) { | ||
654 | wil_err_fw(wil, "data record too short: %zu\n", hdr_sz); | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n", | ||
659 | wil->brd_file_addr); | ||
660 | |||
661 | rc = __fw_handle_data(wil, &hdr[1], hdr_sz, | ||
662 | cpu_to_le32(wil->brd_file_addr)); | ||
663 | |||
664 | return rc; | ||
665 | } | ||
666 | |||
667 | /** | ||
668 | * wil_request_board - Request board file | ||
669 | * | ||
670 | * Request board image from the file | ||
671 | * board file address and max size are read from FW file | ||
672 | * during initialization. | ||
673 | * brd file shall include one header and one data section. | ||
674 | * | ||
675 | * Return error code | ||
676 | */ | ||
677 | int wil_request_board(struct wil6210_priv *wil, const char *name) | ||
678 | { | ||
679 | int rc, dlen; | ||
680 | const struct firmware *brd; | ||
681 | |||
682 | rc = request_firmware(&brd, name, wil_to_dev(wil)); | ||
683 | if (rc) { | ||
684 | wil_err_fw(wil, "Failed to load brd %s\n", name); | ||
685 | return rc; | ||
686 | } | ||
687 | wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, brd->size); | ||
688 | |||
689 | /* Verify the header */ | ||
690 | dlen = wil_fw_verify(wil, brd->data, brd->size); | ||
691 | if (dlen < 0) { | ||
692 | rc = dlen; | ||
693 | goto out; | ||
694 | } | ||
695 | /* Process the data record */ | ||
696 | rc = wil_brd_process(wil, brd->data, dlen); | ||
697 | |||
698 | out: | ||
699 | release_firmware(brd); | ||
700 | return rc; | ||
701 | } | ||
702 | |||
703 | /** | ||
555 | * wil_fw_verify_file_exists - checks if firmware file exist | 704 | * wil_fw_verify_file_exists - checks if firmware file exist |
556 | * | 705 | * |
557 | * @wil: driver context | 706 | * @wil: driver context |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index dcf87a7f99da..1835187ea075 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -395,8 +396,9 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
395 | wil6210_mask_irq_misc(wil, false); | 396 | wil6210_mask_irq_misc(wil, false); |
396 | 397 | ||
397 | if (isr & ISR_MISC_FW_ERROR) { | 398 | if (isr & ISR_MISC_FW_ERROR) { |
398 | u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); | 399 | u32 fw_assert_code = wil_r(wil, wil->rgf_fw_assert_code_addr); |
399 | u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE); | 400 | u32 ucode_assert_code = |
401 | wil_r(wil, wil->rgf_ucode_assert_code_addr); | ||
400 | 402 | ||
401 | wil_err(wil, | 403 | wil_err(wil, |
402 | "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", | 404 | "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index aa6f9c4a21f1..0c61a6c13991 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -637,6 +638,98 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
637 | destroy_workqueue(wil->wmi_wq); | 638 | destroy_workqueue(wil->wmi_wq); |
638 | } | 639 | } |
639 | 640 | ||
641 | static void wil_shutdown_bl(struct wil6210_priv *wil) | ||
642 | { | ||
643 | u32 val; | ||
644 | |||
645 | wil_s(wil, RGF_USER_BL + | ||
646 | offsetof(struct bl_dedicated_registers_v1, | ||
647 | bl_shutdown_handshake), BL_SHUTDOWN_HS_GRTD); | ||
648 | |||
649 | usleep_range(100, 150); | ||
650 | |||
651 | val = wil_r(wil, RGF_USER_BL + | ||
652 | offsetof(struct bl_dedicated_registers_v1, | ||
653 | bl_shutdown_handshake)); | ||
654 | if (val & BL_SHUTDOWN_HS_RTD) { | ||
655 | wil_dbg_misc(wil, "BL is ready for halt\n"); | ||
656 | return; | ||
657 | } | ||
658 | |||
659 | wil_err(wil, "BL did not report ready for halt\n"); | ||
660 | } | ||
661 | |||
662 | /* this format is used by ARC embedded CPU for instruction memory */ | ||
663 | static inline u32 ARC_me_imm32(u32 d) | ||
664 | { | ||
665 | return ((d & 0xffff0000) >> 16) | ((d & 0x0000ffff) << 16); | ||
666 | } | ||
667 | |||
668 | /* defines access to interrupt vectors for wil_freeze_bl */ | ||
669 | #define ARC_IRQ_VECTOR_OFFSET(N) ((N) * 8) | ||
670 | /* ARC long jump instruction */ | ||
671 | #define ARC_JAL_INST (0x20200f80) | ||
672 | |||
673 | static void wil_freeze_bl(struct wil6210_priv *wil) | ||
674 | { | ||
675 | u32 jal, upc, saved; | ||
676 | u32 ivt3 = ARC_IRQ_VECTOR_OFFSET(3); | ||
677 | |||
678 | jal = wil_r(wil, wil->iccm_base + ivt3); | ||
679 | if (jal != ARC_me_imm32(ARC_JAL_INST)) { | ||
680 | wil_dbg_misc(wil, "invalid IVT entry found, skipping\n"); | ||
681 | return; | ||
682 | } | ||
683 | |||
684 | /* prevent the target from entering deep sleep | ||
685 | * and disabling memory access | ||
686 | */ | ||
687 | saved = wil_r(wil, RGF_USER_USAGE_8); | ||
688 | wil_w(wil, RGF_USER_USAGE_8, saved | BIT_USER_PREVENT_DEEP_SLEEP); | ||
689 | usleep_range(20, 25); /* let the BL process the bit */ | ||
690 | |||
691 | /* redirect to endless loop in the INT_L1 context and let it trap */ | ||
692 | wil_w(wil, wil->iccm_base + ivt3 + 4, ARC_me_imm32(ivt3)); | ||
693 | usleep_range(20, 25); /* let the BL get into the trap */ | ||
694 | |||
695 | /* verify the BL is frozen */ | ||
696 | upc = wil_r(wil, RGF_USER_CPU_PC); | ||
697 | if (upc < ivt3 || (upc > (ivt3 + 8))) | ||
698 | wil_dbg_misc(wil, "BL freeze failed, PC=0x%08X\n", upc); | ||
699 | |||
700 | wil_w(wil, RGF_USER_USAGE_8, saved); | ||
701 | } | ||
702 | |||
703 | static void wil_bl_prepare_halt(struct wil6210_priv *wil) | ||
704 | { | ||
705 | u32 tmp, ver; | ||
706 | |||
707 | /* before halting device CPU driver must make sure BL is not accessing | ||
708 | * host memory. This is done differently depending on BL version: | ||
709 | * 1. For very old BL versions the procedure is skipped | ||
710 | * (not supported). | ||
711 | * 2. For old BL version we use a special trick to freeze the BL | ||
712 | * 3. For new BL versions we shutdown the BL using handshake procedure. | ||
713 | */ | ||
714 | tmp = wil_r(wil, RGF_USER_BL + | ||
715 | offsetof(struct bl_dedicated_registers_v0, | ||
716 | boot_loader_struct_version)); | ||
717 | if (!tmp) { | ||
718 | wil_dbg_misc(wil, "old BL, skipping halt preperation\n"); | ||
719 | return; | ||
720 | } | ||
721 | |||
722 | tmp = wil_r(wil, RGF_USER_BL + | ||
723 | offsetof(struct bl_dedicated_registers_v1, | ||
724 | bl_shutdown_handshake)); | ||
725 | ver = BL_SHUTDOWN_HS_PROT_VER(tmp); | ||
726 | |||
727 | if (ver > 0) | ||
728 | wil_shutdown_bl(wil); | ||
729 | else | ||
730 | wil_freeze_bl(wil); | ||
731 | } | ||
732 | |||
640 | static inline void wil_halt_cpu(struct wil6210_priv *wil) | 733 | static inline void wil_halt_cpu(struct wil6210_priv *wil) |
641 | { | 734 | { |
642 | wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST); | 735 | wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST); |
@@ -670,7 +763,7 @@ static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode) | |||
670 | } | 763 | } |
671 | } | 764 | } |
672 | 765 | ||
673 | static int wil_target_reset(struct wil6210_priv *wil) | 766 | static int wil_target_reset(struct wil6210_priv *wil, int no_flash) |
674 | { | 767 | { |
675 | int delay = 0; | 768 | int delay = 0; |
676 | u32 x, x1 = 0; | 769 | u32 x, x1 = 0; |
@@ -684,9 +777,16 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
684 | 777 | ||
685 | wil_halt_cpu(wil); | 778 | wil_halt_cpu(wil); |
686 | 779 | ||
687 | /* clear all boot loader "ready" bits */ | 780 | if (!no_flash) { |
688 | wil_w(wil, RGF_USER_BL + | 781 | /* clear all boot loader "ready" bits */ |
689 | offsetof(struct bl_dedicated_registers_v0, boot_loader_ready), 0); | 782 | wil_w(wil, RGF_USER_BL + |
783 | offsetof(struct bl_dedicated_registers_v0, | ||
784 | boot_loader_ready), 0); | ||
785 | /* this should be safe to write even with old BLs */ | ||
786 | wil_w(wil, RGF_USER_BL + | ||
787 | offsetof(struct bl_dedicated_registers_v1, | ||
788 | bl_shutdown_handshake), 0); | ||
789 | } | ||
690 | /* Clear Fw Download notification */ | 790 | /* Clear Fw Download notification */ |
691 | wil_c(wil, RGF_USER_USAGE_6, BIT(0)); | 791 | wil_c(wil, RGF_USER_USAGE_6, BIT(0)); |
692 | 792 | ||
@@ -727,21 +827,33 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
727 | wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 827 | wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
728 | 828 | ||
729 | /* wait until device ready. typical time is 20..80 msec */ | 829 | /* wait until device ready. typical time is 20..80 msec */ |
730 | do { | 830 | if (no_flash) |
731 | msleep(RST_DELAY); | 831 | do { |
732 | x = wil_r(wil, RGF_USER_BL + | 832 | msleep(RST_DELAY); |
733 | offsetof(struct bl_dedicated_registers_v0, | 833 | x = wil_r(wil, USER_EXT_USER_PMU_3); |
734 | boot_loader_ready)); | 834 | if (delay++ > RST_COUNT) { |
735 | if (x1 != x) { | 835 | wil_err(wil, "Reset not completed, PMU_3 0x%08x\n", |
736 | wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n", x1, x); | 836 | x); |
737 | x1 = x; | 837 | return -ETIME; |
738 | } | 838 | } |
739 | if (delay++ > RST_COUNT) { | 839 | } while ((x & BIT_PMU_DEVICE_RDY) == 0); |
740 | wil_err(wil, "Reset not completed, bl.ready 0x%08x\n", | 840 | else |
741 | x); | 841 | do { |
742 | return -ETIME; | 842 | msleep(RST_DELAY); |
743 | } | 843 | x = wil_r(wil, RGF_USER_BL + |
744 | } while (x != BL_READY); | 844 | offsetof(struct bl_dedicated_registers_v0, |
845 | boot_loader_ready)); | ||
846 | if (x1 != x) { | ||
847 | wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n", | ||
848 | x1, x); | ||
849 | x1 = x; | ||
850 | } | ||
851 | if (delay++ > RST_COUNT) { | ||
852 | wil_err(wil, "Reset not completed, bl.ready 0x%08x\n", | ||
853 | x); | ||
854 | return -ETIME; | ||
855 | } | ||
856 | } while (x != BL_READY); | ||
745 | 857 | ||
746 | wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); | 858 | wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); |
747 | 859 | ||
@@ -749,6 +861,21 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
749 | wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN | | 861 | wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN | |
750 | BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC); | 862 | BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC); |
751 | 863 | ||
864 | if (no_flash) { | ||
865 | /* Reset OTP HW vectors to fit 40MHz */ | ||
866 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME1, 0x60001); | ||
867 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME2, 0x20027); | ||
868 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME3, 0x1); | ||
869 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME4, 0x20027); | ||
870 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME5, 0x30003); | ||
871 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME6, 0x20002); | ||
872 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME7, 0x60001); | ||
873 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME8, 0x60001); | ||
874 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME9, 0x60001); | ||
875 | wil_w(wil, RGF_USER_XPM_IFC_RD_TIME10, 0x60001); | ||
876 | wil_w(wil, RGF_USER_XPM_RD_DOUT_SAMPLE_TIME, 0x57); | ||
877 | } | ||
878 | |||
752 | wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY); | 879 | wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY); |
753 | return 0; | 880 | return 0; |
754 | } | 881 | } |
@@ -906,6 +1033,27 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err) | |||
906 | } | 1033 | } |
907 | } | 1034 | } |
908 | 1035 | ||
1036 | static int wil_get_otp_info(struct wil6210_priv *wil) | ||
1037 | { | ||
1038 | struct net_device *ndev = wil_to_ndev(wil); | ||
1039 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
1040 | u8 mac[8]; | ||
1041 | |||
1042 | wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(RGF_OTP_MAC), | ||
1043 | sizeof(mac)); | ||
1044 | if (!is_valid_ether_addr(mac)) { | ||
1045 | wil_err(wil, "Invalid MAC %pM\n", mac); | ||
1046 | return -EINVAL; | ||
1047 | } | ||
1048 | |||
1049 | ether_addr_copy(ndev->perm_addr, mac); | ||
1050 | ether_addr_copy(wiphy->perm_addr, mac); | ||
1051 | if (!is_valid_ether_addr(ndev->dev_addr)) | ||
1052 | ether_addr_copy(ndev->dev_addr, mac); | ||
1053 | |||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
909 | static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | 1057 | static int wil_wait_for_fw_ready(struct wil6210_priv *wil) |
910 | { | 1058 | { |
911 | ulong to = msecs_to_jiffies(1000); | 1059 | ulong to = msecs_to_jiffies(1000); |
@@ -999,6 +1147,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
999 | { | 1147 | { |
1000 | int rc; | 1148 | int rc; |
1001 | unsigned long status_flags = BIT(wil_status_resetting); | 1149 | unsigned long status_flags = BIT(wil_status_resetting); |
1150 | int no_flash; | ||
1002 | 1151 | ||
1003 | wil_dbg_misc(wil, "reset\n"); | 1152 | wil_dbg_misc(wil, "reset\n"); |
1004 | 1153 | ||
@@ -1074,20 +1223,28 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1074 | flush_workqueue(wil->wq_service); | 1223 | flush_workqueue(wil->wq_service); |
1075 | flush_workqueue(wil->wmi_wq); | 1224 | flush_workqueue(wil->wmi_wq); |
1076 | 1225 | ||
1077 | wil_bl_crash_info(wil, false); | 1226 | no_flash = test_bit(hw_capa_no_flash, wil->hw_capa); |
1227 | if (!no_flash) | ||
1228 | wil_bl_crash_info(wil, false); | ||
1078 | wil_disable_irq(wil); | 1229 | wil_disable_irq(wil); |
1079 | rc = wil_target_reset(wil); | 1230 | rc = wil_target_reset(wil, no_flash); |
1080 | wil6210_clear_irq(wil); | 1231 | wil6210_clear_irq(wil); |
1081 | wil_enable_irq(wil); | 1232 | wil_enable_irq(wil); |
1082 | wil_rx_fini(wil); | 1233 | wil_rx_fini(wil); |
1083 | if (rc) { | 1234 | if (rc) { |
1084 | wil_bl_crash_info(wil, true); | 1235 | if (!no_flash) |
1236 | wil_bl_crash_info(wil, true); | ||
1085 | goto out; | 1237 | goto out; |
1086 | } | 1238 | } |
1087 | 1239 | ||
1088 | rc = wil_get_bl_info(wil); | 1240 | if (no_flash) { |
1089 | if (rc == -EAGAIN && !load_fw) /* ignore RF error if not going up */ | 1241 | rc = wil_get_otp_info(wil); |
1090 | rc = 0; | 1242 | } else { |
1243 | rc = wil_get_bl_info(wil); | ||
1244 | if (rc == -EAGAIN && !load_fw) | ||
1245 | /* ignore RF error if not going up */ | ||
1246 | rc = 0; | ||
1247 | } | ||
1091 | if (rc) | 1248 | if (rc) |
1092 | goto out; | 1249 | goto out; |
1093 | 1250 | ||
@@ -1096,13 +1253,21 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
1096 | wil_info(wil, "Use firmware <%s> + board <%s>\n", | 1253 | wil_info(wil, "Use firmware <%s> + board <%s>\n", |
1097 | wil->wil_fw_name, WIL_BOARD_FILE_NAME); | 1254 | wil->wil_fw_name, WIL_BOARD_FILE_NAME); |
1098 | 1255 | ||
1256 | if (!no_flash) | ||
1257 | wil_bl_prepare_halt(wil); | ||
1258 | |||
1099 | wil_halt_cpu(wil); | 1259 | wil_halt_cpu(wil); |
1100 | memset(wil->fw_version, 0, sizeof(wil->fw_version)); | 1260 | memset(wil->fw_version, 0, sizeof(wil->fw_version)); |
1101 | /* Loading f/w from the file */ | 1261 | /* Loading f/w from the file */ |
1102 | rc = wil_request_firmware(wil, wil->wil_fw_name, true); | 1262 | rc = wil_request_firmware(wil, wil->wil_fw_name, true); |
1103 | if (rc) | 1263 | if (rc) |
1104 | goto out; | 1264 | goto out; |
1105 | rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true); | 1265 | if (wil->brd_file_addr) |
1266 | rc = wil_request_board(wil, WIL_BOARD_FILE_NAME); | ||
1267 | else | ||
1268 | rc = wil_request_firmware(wil, | ||
1269 | WIL_BOARD_FILE_NAME, | ||
1270 | true); | ||
1106 | if (rc) | 1271 | if (rc) |
1107 | goto out; | 1272 | goto out; |
1108 | 1273 | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 0c401bf151a2..809092a49192 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -35,15 +36,16 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, | |||
35 | unsigned long mode, void *unused); | 36 | unsigned long mode, void *unused); |
36 | 37 | ||
37 | static | 38 | static |
38 | void wil_set_capabilities(struct wil6210_priv *wil) | 39 | int wil_set_capabilities(struct wil6210_priv *wil) |
39 | { | 40 | { |
40 | const char *wil_fw_name; | 41 | const char *wil_fw_name; |
41 | u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); | 42 | u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); |
42 | u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & | 43 | u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & |
43 | RGF_USER_REVISION_ID_MASK); | 44 | RGF_USER_REVISION_ID_MASK); |
44 | int platform_capa; | 45 | int platform_capa; |
46 | struct fw_map *iccm_section, *sct; | ||
45 | 47 | ||
46 | bitmap_zero(wil->hw_capabilities, hw_capability_last); | 48 | bitmap_zero(wil->hw_capa, hw_capa_last); |
47 | bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); | 49 | bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); |
48 | bitmap_zero(wil->platform_capa, WIL_PLATFORM_CAPA_MAX); | 50 | bitmap_zero(wil->platform_capa, WIL_PLATFORM_CAPA_MAX); |
49 | wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT : | 51 | wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT : |
@@ -52,6 +54,8 @@ void wil_set_capabilities(struct wil6210_priv *wil) | |||
52 | 54 | ||
53 | switch (jtag_id) { | 55 | switch (jtag_id) { |
54 | case JTAG_DEV_ID_SPARROW: | 56 | case JTAG_DEV_ID_SPARROW: |
57 | memcpy(fw_mapping, sparrow_fw_mapping, | ||
58 | sizeof(sparrow_fw_mapping)); | ||
55 | switch (chip_revision) { | 59 | switch (chip_revision) { |
56 | case REVISION_ID_SPARROW_D0: | 60 | case REVISION_ID_SPARROW_D0: |
57 | wil->hw_name = "Sparrow D0"; | 61 | wil->hw_name = "Sparrow D0"; |
@@ -61,6 +65,12 @@ void wil_set_capabilities(struct wil6210_priv *wil) | |||
61 | 65 | ||
62 | if (wil_fw_verify_file_exists(wil, wil_fw_name)) | 66 | if (wil_fw_verify_file_exists(wil, wil_fw_name)) |
63 | wil->wil_fw_name = wil_fw_name; | 67 | wil->wil_fw_name = wil_fw_name; |
68 | sct = wil_find_fw_mapping("mac_rgf_ext"); | ||
69 | if (!sct) { | ||
70 | wil_err(wil, "mac_rgf_ext section not found in fw_mapping\n"); | ||
71 | return -EINVAL; | ||
72 | } | ||
73 | memcpy(sct, &sparrow_d0_mac_rgf_ext, sizeof(*sct)); | ||
64 | break; | 74 | break; |
65 | case REVISION_ID_SPARROW_B0: | 75 | case REVISION_ID_SPARROW_B0: |
66 | wil->hw_name = "Sparrow B0"; | 76 | wil->hw_name = "Sparrow B0"; |
@@ -71,15 +81,36 @@ void wil_set_capabilities(struct wil6210_priv *wil) | |||
71 | wil->hw_version = HW_VER_UNKNOWN; | 81 | wil->hw_version = HW_VER_UNKNOWN; |
72 | break; | 82 | break; |
73 | } | 83 | } |
84 | wil->rgf_fw_assert_code_addr = SPARROW_RGF_FW_ASSERT_CODE; | ||
85 | wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE; | ||
86 | break; | ||
87 | case JTAG_DEV_ID_TALYN: | ||
88 | wil->hw_name = "Talyn"; | ||
89 | wil->hw_version = HW_VER_TALYN; | ||
90 | memcpy(fw_mapping, talyn_fw_mapping, sizeof(talyn_fw_mapping)); | ||
91 | wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE; | ||
92 | wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE; | ||
93 | if (wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1) & | ||
94 | BIT_NO_FLASH_INDICATION) | ||
95 | set_bit(hw_capa_no_flash, wil->hw_capa); | ||
74 | break; | 96 | break; |
75 | default: | 97 | default: |
76 | wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", | 98 | wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", |
77 | jtag_id, chip_revision); | 99 | jtag_id, chip_revision); |
78 | wil->hw_name = "Unknown"; | 100 | wil->hw_name = "Unknown"; |
79 | wil->hw_version = HW_VER_UNKNOWN; | 101 | wil->hw_version = HW_VER_UNKNOWN; |
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | iccm_section = wil_find_fw_mapping("fw_code"); | ||
106 | if (!iccm_section) { | ||
107 | wil_err(wil, "fw_code section not found in fw_mapping\n"); | ||
108 | return -EINVAL; | ||
80 | } | 109 | } |
110 | wil->iccm_base = iccm_section->host; | ||
81 | 111 | ||
82 | wil_info(wil, "Board hardware is %s\n", wil->hw_name); | 112 | wil_info(wil, "Board hardware is %s, flash %sexist\n", wil->hw_name, |
113 | test_bit(hw_capa_no_flash, wil->hw_capa) ? "doesn't " : ""); | ||
83 | 114 | ||
84 | /* Get platform capabilities */ | 115 | /* Get platform capabilities */ |
85 | if (wil->platform_ops.get_capa) { | 116 | if (wil->platform_ops.get_capa) { |
@@ -92,6 +123,8 @@ void wil_set_capabilities(struct wil6210_priv *wil) | |||
92 | /* extract FW capabilities from file without loading the FW */ | 123 | /* extract FW capabilities from file without loading the FW */ |
93 | wil_request_firmware(wil, wil->wil_fw_name, false); | 124 | wil_request_firmware(wil, wil->wil_fw_name, false); |
94 | wil_refresh_fw_capabilities(wil); | 125 | wil_refresh_fw_capabilities(wil); |
126 | |||
127 | return 0; | ||
95 | } | 128 | } |
96 | 129 | ||
97 | void wil_disable_irq(struct wil6210_priv *wil) | 130 | void wil_disable_irq(struct wil6210_priv *wil) |
@@ -302,7 +335,11 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
302 | /* rollback to err_iounmap */ | 335 | /* rollback to err_iounmap */ |
303 | wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr); | 336 | wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr); |
304 | 337 | ||
305 | wil_set_capabilities(wil); | 338 | rc = wil_set_capabilities(wil); |
339 | if (rc) { | ||
340 | wil_err(wil, "wil_set_capabilities failed, rc %d\n", rc); | ||
341 | goto err_iounmap; | ||
342 | } | ||
306 | wil6210_clear_irq(wil); | 343 | wil6210_clear_irq(wil); |
307 | 344 | ||
308 | /* FW should raise IRQ when ready */ | 345 | /* FW should raise IRQ when ready */ |
@@ -378,6 +415,7 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
378 | static const struct pci_device_id wil6210_pcie_ids[] = { | 415 | static const struct pci_device_id wil6210_pcie_ids[] = { |
379 | { PCI_DEVICE(0x1ae9, 0x0310) }, | 416 | { PCI_DEVICE(0x1ae9, 0x0310) }, |
380 | { PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */ | 417 | { PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */ |
418 | { PCI_DEVICE(0x17cb, 0x1201) }, /* Talyn */ | ||
381 | { /* end: all zeroes */ }, | 419 | { /* end: all zeroes */ }, |
382 | }; | 420 | }; |
383 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | 421 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 0a0766b2c80a..0df2aada6659 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -169,6 +170,7 @@ struct RGF_ICR { | |||
169 | #define HW_MACHINE_BOOT_DONE (0x3fffffd) | 170 | #define HW_MACHINE_BOOT_DONE (0x3fffffd) |
170 | #define RGF_USER_USER_CPU_0 (0x8801e0) | 171 | #define RGF_USER_USER_CPU_0 (0x8801e0) |
171 | #define BIT_USER_USER_CPU_MAN_RST BIT(1) /* user_cpu_man_rst */ | 172 | #define BIT_USER_USER_CPU_MAN_RST BIT(1) /* user_cpu_man_rst */ |
173 | #define RGF_USER_CPU_PC (0x8801e8) | ||
172 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | 174 | #define RGF_USER_MAC_CPU_0 (0x8801fc) |
173 | #define BIT_USER_MAC_CPU_MAN_RST BIT(1) /* mac_cpu_man_rst */ | 175 | #define BIT_USER_MAC_CPU_MAN_RST BIT(1) /* mac_cpu_man_rst */ |
174 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | 176 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) |
@@ -194,6 +196,19 @@ struct RGF_ICR { | |||
194 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c) | 196 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c) |
195 | #define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */ | 197 | #define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */ |
196 | #define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2) | 198 | #define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2) |
199 | #define RGF_USER_OTP_HW_RD_MACHINE_1 (0x880ce0) | ||
200 | #define BIT_NO_FLASH_INDICATION BIT(8) | ||
201 | #define RGF_USER_XPM_IFC_RD_TIME1 (0x880cec) | ||
202 | #define RGF_USER_XPM_IFC_RD_TIME2 (0x880cf0) | ||
203 | #define RGF_USER_XPM_IFC_RD_TIME3 (0x880cf4) | ||
204 | #define RGF_USER_XPM_IFC_RD_TIME4 (0x880cf8) | ||
205 | #define RGF_USER_XPM_IFC_RD_TIME5 (0x880cfc) | ||
206 | #define RGF_USER_XPM_IFC_RD_TIME6 (0x880d00) | ||
207 | #define RGF_USER_XPM_IFC_RD_TIME7 (0x880d04) | ||
208 | #define RGF_USER_XPM_IFC_RD_TIME8 (0x880d08) | ||
209 | #define RGF_USER_XPM_IFC_RD_TIME9 (0x880d0c) | ||
210 | #define RGF_USER_XPM_IFC_RD_TIME10 (0x880d10) | ||
211 | #define RGF_USER_XPM_RD_DOUT_SAMPLE_TIME (0x880d64) | ||
197 | 212 | ||
198 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | 213 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ |
199 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | 214 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) |
@@ -284,22 +299,33 @@ struct RGF_ICR { | |||
284 | #define RGF_CAF_PLL_LOCK_STATUS (0x88afec) | 299 | #define RGF_CAF_PLL_LOCK_STATUS (0x88afec) |
285 | #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) | 300 | #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) |
286 | 301 | ||
302 | #define USER_EXT_USER_PMU_3 (0x88d00c) | ||
303 | #define BIT_PMU_DEVICE_RDY BIT(0) | ||
304 | |||
287 | #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ | 305 | #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ |
288 | #define JTAG_DEV_ID_SPARROW (0x2632072f) | 306 | #define JTAG_DEV_ID_SPARROW (0x2632072f) |
307 | #define JTAG_DEV_ID_TALYN (0x7e0e1) | ||
289 | 308 | ||
290 | #define RGF_USER_REVISION_ID (0x88afe4) | 309 | #define RGF_USER_REVISION_ID (0x88afe4) |
291 | #define RGF_USER_REVISION_ID_MASK (3) | 310 | #define RGF_USER_REVISION_ID_MASK (3) |
292 | #define REVISION_ID_SPARROW_B0 (0x0) | 311 | #define REVISION_ID_SPARROW_B0 (0x0) |
293 | #define REVISION_ID_SPARROW_D0 (0x3) | 312 | #define REVISION_ID_SPARROW_D0 (0x3) |
294 | 313 | ||
314 | #define RGF_OTP_MAC (0x8a0620) | ||
315 | |||
295 | /* crash codes for FW/Ucode stored here */ | 316 | /* crash codes for FW/Ucode stored here */ |
296 | #define RGF_FW_ASSERT_CODE (0x91f020) | 317 | |
297 | #define RGF_UCODE_ASSERT_CODE (0x91f028) | 318 | /* ASSERT RGFs */ |
319 | #define SPARROW_RGF_FW_ASSERT_CODE (0x91f020) | ||
320 | #define SPARROW_RGF_UCODE_ASSERT_CODE (0x91f028) | ||
321 | #define TALYN_RGF_FW_ASSERT_CODE (0xa37020) | ||
322 | #define TALYN_RGF_UCODE_ASSERT_CODE (0xa37028) | ||
298 | 323 | ||
299 | enum { | 324 | enum { |
300 | HW_VER_UNKNOWN, | 325 | HW_VER_UNKNOWN, |
301 | HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */ | 326 | HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */ |
302 | HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */ | 327 | HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */ |
328 | HW_VER_TALYN, /* JTAG_DEV_ID_TALYN */ | ||
303 | }; | 329 | }; |
304 | 330 | ||
305 | /* popular locations */ | 331 | /* popular locations */ |
@@ -315,6 +341,10 @@ enum { | |||
315 | #define WIL_DATA_COMPLETION_TO_MS 200 | 341 | #define WIL_DATA_COMPLETION_TO_MS 200 |
316 | 342 | ||
317 | /* Hardware definitions end */ | 343 | /* Hardware definitions end */ |
344 | #define SPARROW_FW_MAPPING_TABLE_SIZE 10 | ||
345 | #define TALYN_FW_MAPPING_TABLE_SIZE 13 | ||
346 | #define MAX_FW_MAPPING_TABLE_SIZE 13 | ||
347 | |||
318 | struct fw_map { | 348 | struct fw_map { |
319 | u32 from; /* linker address - from, inclusive */ | 349 | u32 from; /* linker address - from, inclusive */ |
320 | u32 to; /* linker address - to, exclusive */ | 350 | u32 to; /* linker address - to, exclusive */ |
@@ -324,7 +354,10 @@ struct fw_map { | |||
324 | }; | 354 | }; |
325 | 355 | ||
326 | /* array size should be in sync with actual definition in the wmi.c */ | 356 | /* array size should be in sync with actual definition in the wmi.c */ |
327 | extern const struct fw_map fw_mapping[10]; | 357 | extern const struct fw_map sparrow_fw_mapping[SPARROW_FW_MAPPING_TABLE_SIZE]; |
358 | extern const struct fw_map sparrow_d0_mac_rgf_ext; | ||
359 | extern const struct fw_map talyn_fw_mapping[TALYN_FW_MAPPING_TABLE_SIZE]; | ||
360 | extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE]; | ||
328 | 361 | ||
329 | /** | 362 | /** |
330 | * mk_cidxtid - construct @cidxtid field | 363 | * mk_cidxtid - construct @cidxtid field |
@@ -570,7 +603,8 @@ enum { | |||
570 | }; | 603 | }; |
571 | 604 | ||
572 | enum { | 605 | enum { |
573 | hw_capability_last | 606 | hw_capa_no_flash, |
607 | hw_capa_last | ||
574 | }; | 608 | }; |
575 | 609 | ||
576 | struct wil_probe_client_req { | 610 | struct wil_probe_client_req { |
@@ -646,7 +680,10 @@ struct wil6210_priv { | |||
646 | u8 chip_revision; | 680 | u8 chip_revision; |
647 | const char *hw_name; | 681 | const char *hw_name; |
648 | const char *wil_fw_name; | 682 | const char *wil_fw_name; |
649 | DECLARE_BITMAP(hw_capabilities, hw_capability_last); | 683 | char *board_file; |
684 | u32 brd_file_addr; | ||
685 | u32 brd_file_max_size; | ||
686 | DECLARE_BITMAP(hw_capa, hw_capa_last); | ||
650 | DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); | 687 | DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); |
651 | DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX); | 688 | DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX); |
652 | u8 n_mids; /* number of additional MIDs as reported by FW */ | 689 | u8 n_mids; /* number of additional MIDs as reported by FW */ |
@@ -720,7 +757,7 @@ struct wil6210_priv { | |||
720 | atomic_t isr_count_rx, isr_count_tx; | 757 | atomic_t isr_count_rx, isr_count_tx; |
721 | /* debugfs */ | 758 | /* debugfs */ |
722 | struct dentry *debug; | 759 | struct dentry *debug; |
723 | struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; | 760 | struct wil_blob_wrapper blobs[MAX_FW_MAPPING_TABLE_SIZE]; |
724 | u8 discovery_mode; | 761 | u8 discovery_mode; |
725 | u8 abft_len; | 762 | u8 abft_len; |
726 | u8 wakeup_trigger; | 763 | u8 wakeup_trigger; |
@@ -755,6 +792,10 @@ struct wil6210_priv { | |||
755 | bool suspend_resp_comp; | 792 | bool suspend_resp_comp; |
756 | u32 bus_request_kbps; | 793 | u32 bus_request_kbps; |
757 | u32 bus_request_kbps_pre_suspend; | 794 | u32 bus_request_kbps_pre_suspend; |
795 | |||
796 | u32 rgf_fw_assert_code_addr; | ||
797 | u32 rgf_ucode_assert_code_addr; | ||
798 | u32 iccm_base; | ||
758 | }; | 799 | }; |
759 | 800 | ||
760 | #define wil_to_wiphy(i) (i->wdev->wiphy) | 801 | #define wil_to_wiphy(i) (i->wdev->wiphy) |
@@ -880,6 +921,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); | |||
880 | int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); | 921 | int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); |
881 | void wil_set_ethtoolops(struct net_device *ndev); | 922 | void wil_set_ethtoolops(struct net_device *ndev); |
882 | 923 | ||
924 | struct fw_map *wil_find_fw_mapping(const char *section); | ||
883 | void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); | 925 | void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); |
884 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); | 926 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); |
885 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); | 927 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); |
@@ -1013,6 +1055,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type); | |||
1013 | 1055 | ||
1014 | int wil_request_firmware(struct wil6210_priv *wil, const char *name, | 1056 | int wil_request_firmware(struct wil6210_priv *wil, const char *name, |
1015 | bool load); | 1057 | bool load); |
1058 | int wil_request_board(struct wil6210_priv *wil, const char *name); | ||
1016 | bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); | 1059 | bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); |
1017 | 1060 | ||
1018 | void wil_pm_runtime_allow(struct wil6210_priv *wil); | 1061 | void wil_pm_runtime_allow(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 2ab71bb32327..b31e2514f8c2 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -70,23 +71,23 @@ MODULE_PARM_DESC(led_id, | |||
70 | * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing | 71 | * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing |
71 | * AHB addresses starting from 0x880000 | 72 | * AHB addresses starting from 0x880000 |
72 | * | 73 | * |
73 | * Internally, firmware uses addresses that allows faster access but | 74 | * Internally, firmware uses addresses that allow faster access but |
74 | * are invisible from the host. To read from these addresses, alternative | 75 | * are invisible from the host. To read from these addresses, alternative |
75 | * AHB address must be used. | 76 | * AHB address must be used. |
76 | * | ||
77 | * Memory mapping | ||
78 | * Linker address PCI/Host address | ||
79 | * 0x880000 .. 0xa80000 2Mb BAR0 | ||
80 | * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM | ||
81 | * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH | ||
82 | */ | 77 | */ |
83 | 78 | ||
84 | /** | 79 | /** |
85 | * @fw_mapping provides memory remapping table | 80 | * @sparrow_fw_mapping provides memory remapping table for sparrow |
86 | * | 81 | * |
87 | * array size should be in sync with the declaration in the wil6210.h | 82 | * array size should be in sync with the declaration in the wil6210.h |
83 | * | ||
84 | * Sparrow memory mapping: | ||
85 | * Linker address PCI/Host address | ||
86 | * 0x880000 .. 0xa80000 2Mb BAR0 | ||
87 | * 0x800000 .. 0x808000 0x900000 .. 0x908000 32k DCCM | ||
88 | * 0x840000 .. 0x860000 0x908000 .. 0x928000 128k PERIPH | ||
88 | */ | 89 | */ |
89 | const struct fw_map fw_mapping[] = { | 90 | const struct fw_map sparrow_fw_mapping[] = { |
90 | /* FW code RAM 256k */ | 91 | /* FW code RAM 256k */ |
91 | {0x000000, 0x040000, 0x8c0000, "fw_code", true}, | 92 | {0x000000, 0x040000, 0x8c0000, "fw_code", true}, |
92 | /* FW data RAM 32k */ | 93 | /* FW data RAM 32k */ |
@@ -112,6 +113,59 @@ const struct fw_map fw_mapping[] = { | |||
112 | {0x800000, 0x804000, 0x940000, "uc_data", false}, | 113 | {0x800000, 0x804000, 0x940000, "uc_data", false}, |
113 | }; | 114 | }; |
114 | 115 | ||
116 | /** | ||
117 | * @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0 | ||
118 | * it is a bit larger to support extra features | ||
119 | */ | ||
120 | const struct fw_map sparrow_d0_mac_rgf_ext = { | ||
121 | 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true | ||
122 | }; | ||
123 | |||
124 | /** | ||
125 | * @talyn_fw_mapping provides memory remapping table for Talyn | ||
126 | * | ||
127 | * array size should be in sync with the declaration in the wil6210.h | ||
128 | * | ||
129 | * Talyn memory mapping: | ||
130 | * Linker address PCI/Host address | ||
131 | * 0x880000 .. 0xc80000 4Mb BAR0 | ||
132 | * 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM | ||
133 | * 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH | ||
134 | */ | ||
135 | const struct fw_map talyn_fw_mapping[] = { | ||
136 | /* FW code RAM 1M */ | ||
137 | {0x000000, 0x100000, 0x900000, "fw_code", true}, | ||
138 | /* FW data RAM 128k */ | ||
139 | {0x800000, 0x820000, 0xa00000, "fw_data", true}, | ||
140 | /* periph. data RAM 96k */ | ||
141 | {0x840000, 0x858000, 0xa20000, "fw_peri", true}, | ||
142 | /* various RGF 40k */ | ||
143 | {0x880000, 0x88a000, 0x880000, "rgf", true}, | ||
144 | /* AGC table 4k */ | ||
145 | {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true}, | ||
146 | /* Pcie_ext_rgf 4k */ | ||
147 | {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true}, | ||
148 | /* mac_ext_rgf 1344b */ | ||
149 | {0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true}, | ||
150 | /* ext USER RGF 4k */ | ||
151 | {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true}, | ||
152 | /* OTP 4k */ | ||
153 | {0x8a0000, 0x8a1000, 0x8a0000, "otp", true}, | ||
154 | /* DMA EXT RGF 64k */ | ||
155 | {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true}, | ||
156 | /* upper area 1536k */ | ||
157 | {0x900000, 0xa80000, 0x900000, "upper", true}, | ||
158 | /* UCODE areas - accessible by debugfs blobs but not by | ||
159 | * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas! | ||
160 | */ | ||
161 | /* ucode code RAM 256k */ | ||
162 | {0x000000, 0x040000, 0xa38000, "uc_code", false}, | ||
163 | /* ucode data RAM 32k */ | ||
164 | {0x800000, 0x808000, 0xa78000, "uc_data", false}, | ||
165 | }; | ||
166 | |||
167 | struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE]; | ||
168 | |||
115 | struct blink_on_off_time led_blink_time[] = { | 169 | struct blink_on_off_time led_blink_time[] = { |
116 | {WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS}, | 170 | {WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS}, |
117 | {WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS}, | 171 | {WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS}, |
@@ -139,6 +193,24 @@ static u32 wmi_addr_remap(u32 x) | |||
139 | } | 193 | } |
140 | 194 | ||
141 | /** | 195 | /** |
196 | * find fw_mapping entry by section name | ||
197 | * @section - section name | ||
198 | * | ||
199 | * Return pointer to section or NULL if not found | ||
200 | */ | ||
201 | struct fw_map *wil_find_fw_mapping(const char *section) | ||
202 | { | ||
203 | int i; | ||
204 | |||
205 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) | ||
206 | if (fw_mapping[i].name && | ||
207 | !strcmp(section, fw_mapping[i].name)) | ||
208 | return &fw_mapping[i]; | ||
209 | |||
210 | return NULL; | ||
211 | } | ||
212 | |||
213 | /** | ||
142 | * Check address validity for WMI buffer; remap if needed | 214 | * Check address validity for WMI buffer; remap if needed |
143 | * @ptr - internal (linker) fw/ucode address | 215 | * @ptr - internal (linker) fw/ucode address |
144 | * @size - if non zero, validate the block does not | 216 | * @size - if non zero, validate the block does not |