diff options
| author | Luciano Coelho <coelho@ti.com> | 2012-06-26 15:43:29 -0400 |
|---|---|---|
| committer | Luciano Coelho <coelho@ti.com> | 2012-06-26 15:43:29 -0400 |
| commit | a572ac1a3d37440dc9daf69f9ad63243bef6893f (patch) | |
| tree | 4f2f66f8849118c4e7d0288825e779e9b8fcfef0 | |
| parent | 6bcfe67f9865fb51ec78fc9b09887375db7e08b5 (diff) | |
| parent | 680c6055b9bebdf07fc2d5ebe816a14c7daecdc1 (diff) | |
Merge branch 'wl12xx-next' into for-linville
22 files changed, 1257 insertions, 475 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 0d2fdca2aa32..47ba2e0017f4 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
| @@ -598,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = { | |||
| 598 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" | 598 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" |
| 599 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" | 599 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" |
| 600 | 600 | ||
| 601 | static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 601 | static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
| 602 | { | 602 | { |
| 603 | int ret; | ||
| 604 | |||
| 603 | if (wl->chip.id != CHIP_ID_1283_PG20) { | 605 | if (wl->chip.id != CHIP_ID_1283_PG20) { |
| 604 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 606 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
| 605 | struct wl127x_rx_mem_pool_addr rx_mem_addr; | 607 | struct wl127x_rx_mem_pool_addr rx_mem_addr; |
| @@ -616,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
| 616 | 618 | ||
| 617 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; | 619 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; |
| 618 | 620 | ||
| 619 | wl1271_write(wl, WL1271_SLV_REG_DATA, | 621 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr, |
| 620 | &rx_mem_addr, sizeof(rx_mem_addr), false); | 622 | sizeof(rx_mem_addr), false); |
| 623 | if (ret < 0) | ||
| 624 | return ret; | ||
| 621 | } | 625 | } |
| 626 | |||
| 627 | return 0; | ||
| 622 | } | 628 | } |
| 623 | 629 | ||
| 624 | static int wl12xx_identify_chip(struct wl1271 *wl) | 630 | static int wl12xx_identify_chip(struct wl1271 *wl) |
| @@ -682,64 +688,95 @@ out: | |||
| 682 | return ret; | 688 | return ret; |
| 683 | } | 689 | } |
| 684 | 690 | ||
| 685 | static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 691 | static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr, |
| 692 | u16 val) | ||
| 686 | { | 693 | { |
| 694 | int ret; | ||
| 695 | |||
| 687 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 696 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
| 688 | addr = (addr >> 1) + 0x30000; | 697 | addr = (addr >> 1) + 0x30000; |
| 689 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 698 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
| 699 | if (ret < 0) | ||
| 700 | goto out; | ||
| 690 | 701 | ||
| 691 | /* write value to OCP_POR_WDATA */ | 702 | /* write value to OCP_POR_WDATA */ |
| 692 | wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val); | 703 | ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val); |
| 704 | if (ret < 0) | ||
| 705 | goto out; | ||
| 693 | 706 | ||
| 694 | /* write 1 to OCP_CMD */ | 707 | /* write 1 to OCP_CMD */ |
| 695 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); | 708 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); |
| 709 | if (ret < 0) | ||
| 710 | goto out; | ||
| 711 | |||
| 712 | out: | ||
| 713 | return ret; | ||
| 696 | } | 714 | } |
| 697 | 715 | ||
| 698 | static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr) | 716 | static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr, |
| 717 | u16 *out) | ||
| 699 | { | 718 | { |
| 700 | u32 val; | 719 | u32 val; |
| 701 | int timeout = OCP_CMD_LOOP; | 720 | int timeout = OCP_CMD_LOOP; |
| 721 | int ret; | ||
| 702 | 722 | ||
| 703 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 723 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
| 704 | addr = (addr >> 1) + 0x30000; | 724 | addr = (addr >> 1) + 0x30000; |
| 705 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 725 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
| 726 | if (ret < 0) | ||
| 727 | return ret; | ||
| 706 | 728 | ||
| 707 | /* write 2 to OCP_CMD */ | 729 | /* write 2 to OCP_CMD */ |
| 708 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); | 730 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); |
| 731 | if (ret < 0) | ||
| 732 | return ret; | ||
| 709 | 733 | ||
| 710 | /* poll for data ready */ | 734 | /* poll for data ready */ |
| 711 | do { | 735 | do { |
| 712 | val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); | 736 | ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val); |
| 737 | if (ret < 0) | ||
| 738 | return ret; | ||
| 713 | } while (!(val & OCP_READY_MASK) && --timeout); | 739 | } while (!(val & OCP_READY_MASK) && --timeout); |
| 714 | 740 | ||
| 715 | if (!timeout) { | 741 | if (!timeout) { |
| 716 | wl1271_warning("Top register access timed out."); | 742 | wl1271_warning("Top register access timed out."); |
| 717 | return 0xffff; | 743 | return -ETIMEDOUT; |
| 718 | } | 744 | } |
| 719 | 745 | ||
| 720 | /* check data status and return if OK */ | 746 | /* check data status and return if OK */ |
| 721 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | 747 | if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) { |
| 722 | return val & 0xffff; | ||
| 723 | else { | ||
| 724 | wl1271_warning("Top register access returned error."); | 748 | wl1271_warning("Top register access returned error."); |
| 725 | return 0xffff; | 749 | return -EIO; |
| 726 | } | 750 | } |
| 751 | |||
| 752 | if (out) | ||
| 753 | *out = val & 0xffff; | ||
| 754 | |||
| 755 | return 0; | ||
| 727 | } | 756 | } |
| 728 | 757 | ||
| 729 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | 758 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) |
| 730 | { | 759 | { |
| 731 | u16 spare_reg; | 760 | u16 spare_reg; |
| 761 | int ret; | ||
| 732 | 762 | ||
| 733 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ | 763 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ |
| 734 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 764 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
| 765 | if (ret < 0) | ||
| 766 | return ret; | ||
| 767 | |||
| 735 | if (spare_reg == 0xFFFF) | 768 | if (spare_reg == 0xFFFF) |
| 736 | return -EFAULT; | 769 | return -EFAULT; |
| 737 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); | 770 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); |
| 738 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 771 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
| 772 | if (ret < 0) | ||
| 773 | return ret; | ||
| 739 | 774 | ||
| 740 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ | 775 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ |
| 741 | wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, | 776 | ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, |
| 742 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); | 777 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); |
| 778 | if (ret < 0) | ||
| 779 | return ret; | ||
| 743 | 780 | ||
| 744 | /* Delay execution for 15msec, to let the HW settle */ | 781 | /* Delay execution for 15msec, to let the HW settle */ |
| 745 | mdelay(15); | 782 | mdelay(15); |
| @@ -750,8 +787,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | |||
| 750 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | 787 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) |
| 751 | { | 788 | { |
| 752 | u16 tcxo_detection; | 789 | u16 tcxo_detection; |
| 790 | int ret; | ||
| 791 | |||
| 792 | ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection); | ||
| 793 | if (ret < 0) | ||
| 794 | return false; | ||
| 753 | 795 | ||
| 754 | tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG); | ||
| 755 | if (tcxo_detection & TCXO_DET_FAILED) | 796 | if (tcxo_detection & TCXO_DET_FAILED) |
| 756 | return false; | 797 | return false; |
| 757 | 798 | ||
| @@ -761,8 +802,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | |||
| 761 | static bool wl128x_is_fref_valid(struct wl1271 *wl) | 802 | static bool wl128x_is_fref_valid(struct wl1271 *wl) |
| 762 | { | 803 | { |
| 763 | u16 fref_detection; | 804 | u16 fref_detection; |
| 805 | int ret; | ||
| 806 | |||
| 807 | ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection); | ||
| 808 | if (ret < 0) | ||
| 809 | return false; | ||
| 764 | 810 | ||
| 765 | fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG); | ||
| 766 | if (fref_detection & FREF_CLK_DETECT_FAIL) | 811 | if (fref_detection & FREF_CLK_DETECT_FAIL) |
| 767 | return false; | 812 | return false; |
| 768 | 813 | ||
| @@ -771,11 +816,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl) | |||
| 771 | 816 | ||
| 772 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) | 817 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) |
| 773 | { | 818 | { |
| 774 | wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); | 819 | int ret; |
| 775 | wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
| 776 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); | ||
| 777 | 820 | ||
| 778 | return 0; | 821 | ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); |
| 822 | if (ret < 0) | ||
| 823 | goto out; | ||
| 824 | |||
| 825 | ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
| 826 | if (ret < 0) | ||
| 827 | goto out; | ||
| 828 | |||
| 829 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, | ||
| 830 | MCS_PLL_CONFIG_REG_VAL); | ||
| 831 | |||
| 832 | out: | ||
| 833 | return ret; | ||
| 779 | } | 834 | } |
| 780 | 835 | ||
| 781 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | 836 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) |
| @@ -784,13 +839,19 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
| 784 | u16 pll_config; | 839 | u16 pll_config; |
| 785 | u8 input_freq; | 840 | u8 input_freq; |
| 786 | struct wl12xx_priv *priv = wl->priv; | 841 | struct wl12xx_priv *priv = wl->priv; |
| 842 | int ret; | ||
| 787 | 843 | ||
| 788 | /* Mask bits [3:1] in the sys_clk_cfg register */ | 844 | /* Mask bits [3:1] in the sys_clk_cfg register */ |
| 789 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 845 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
| 846 | if (ret < 0) | ||
| 847 | return ret; | ||
| 848 | |||
| 790 | if (spare_reg == 0xFFFF) | 849 | if (spare_reg == 0xFFFF) |
| 791 | return -EFAULT; | 850 | return -EFAULT; |
| 792 | spare_reg |= BIT(2); | 851 | spare_reg |= BIT(2); |
| 793 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 852 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
| 853 | if (ret < 0) | ||
| 854 | return ret; | ||
| 794 | 855 | ||
| 795 | /* Handle special cases of the TCXO clock */ | 856 | /* Handle special cases of the TCXO clock */ |
| 796 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | 857 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || |
| @@ -800,14 +861,17 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
| 800 | /* Set the input frequency according to the selected clock source */ | 861 | /* Set the input frequency according to the selected clock source */ |
| 801 | input_freq = (clk & 1) + 1; | 862 | input_freq = (clk & 1) + 1; |
| 802 | 863 | ||
| 803 | pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG); | 864 | ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config); |
| 865 | if (ret < 0) | ||
| 866 | return ret; | ||
| 867 | |||
| 804 | if (pll_config == 0xFFFF) | 868 | if (pll_config == 0xFFFF) |
| 805 | return -EFAULT; | 869 | return -EFAULT; |
| 806 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); | 870 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); |
| 807 | pll_config |= MCS_PLL_ENABLE_HP; | 871 | pll_config |= MCS_PLL_ENABLE_HP; |
| 808 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); | 872 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); |
| 809 | 873 | ||
| 810 | return 0; | 874 | return ret; |
| 811 | } | 875 | } |
| 812 | 876 | ||
| 813 | /* | 877 | /* |
| @@ -821,6 +885,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
| 821 | { | 885 | { |
| 822 | struct wl12xx_priv *priv = wl->priv; | 886 | struct wl12xx_priv *priv = wl->priv; |
| 823 | u16 sys_clk_cfg; | 887 | u16 sys_clk_cfg; |
| 888 | int ret; | ||
| 824 | 889 | ||
| 825 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | 890 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ |
| 826 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || | 891 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || |
| @@ -831,7 +896,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
| 831 | } | 896 | } |
| 832 | 897 | ||
| 833 | /* Query the HW, to determine which clock source we should use */ | 898 | /* Query the HW, to determine which clock source we should use */ |
| 834 | sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG); | 899 | ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg); |
| 900 | if (ret < 0) | ||
| 901 | return ret; | ||
| 902 | |||
| 835 | if (sys_clk_cfg == 0xFFFF) | 903 | if (sys_clk_cfg == 0xFFFF) |
| 836 | return -EINVAL; | 904 | return -EINVAL; |
| 837 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) | 905 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) |
| @@ -866,6 +934,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
| 866 | struct wl12xx_priv *priv = wl->priv; | 934 | struct wl12xx_priv *priv = wl->priv; |
| 867 | u32 pause; | 935 | u32 pause; |
| 868 | u32 clk; | 936 | u32 clk; |
| 937 | int ret; | ||
| 869 | 938 | ||
| 870 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | 939 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
| 871 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; | 940 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; |
| @@ -886,48 +955,74 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
| 886 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { | 955 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { |
| 887 | u16 val; | 956 | u16 val; |
| 888 | /* Set clock type (open drain) */ | 957 | /* Set clock type (open drain) */ |
| 889 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); | 958 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val); |
| 959 | if (ret < 0) | ||
| 960 | goto out; | ||
| 961 | |||
| 890 | val &= FREF_CLK_TYPE_BITS; | 962 | val &= FREF_CLK_TYPE_BITS; |
| 891 | wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 963 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
| 964 | if (ret < 0) | ||
| 965 | goto out; | ||
| 892 | 966 | ||
| 893 | /* Set clock pull mode (no pull) */ | 967 | /* Set clock pull mode (no pull) */ |
| 894 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL); | 968 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val); |
| 969 | if (ret < 0) | ||
| 970 | goto out; | ||
| 971 | |||
| 895 | val |= NO_PULL; | 972 | val |= NO_PULL; |
| 896 | wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); | 973 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); |
| 974 | if (ret < 0) | ||
| 975 | goto out; | ||
| 897 | } else { | 976 | } else { |
| 898 | u16 val; | 977 | u16 val; |
| 899 | /* Set clock polarity */ | 978 | /* Set clock polarity */ |
| 900 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY); | 979 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val); |
| 980 | if (ret < 0) | ||
| 981 | goto out; | ||
| 982 | |||
| 901 | val &= FREF_CLK_POLARITY_BITS; | 983 | val &= FREF_CLK_POLARITY_BITS; |
| 902 | val |= CLK_REQ_OUTN_SEL; | 984 | val |= CLK_REQ_OUTN_SEL; |
| 903 | wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | 985 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
| 986 | if (ret < 0) | ||
| 987 | goto out; | ||
| 904 | } | 988 | } |
| 905 | 989 | ||
| 906 | wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); | 990 | ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk); |
| 991 | if (ret < 0) | ||
| 992 | goto out; | ||
| 907 | 993 | ||
| 908 | pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); | 994 | ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause); |
| 995 | if (ret < 0) | ||
| 996 | goto out; | ||
| 909 | 997 | ||
| 910 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 998 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
| 911 | 999 | ||
| 912 | pause &= ~(WU_COUNTER_PAUSE_VAL); | 1000 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
| 913 | pause |= WU_COUNTER_PAUSE_VAL; | 1001 | pause |= WU_COUNTER_PAUSE_VAL; |
| 914 | wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); | 1002 | ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); |
| 915 | 1003 | ||
| 916 | return 0; | 1004 | out: |
| 1005 | return ret; | ||
| 917 | } | 1006 | } |
| 918 | 1007 | ||
| 919 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 1008 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
| 920 | { | 1009 | { |
| 921 | unsigned long timeout; | 1010 | unsigned long timeout; |
| 922 | u32 boot_data; | 1011 | u32 boot_data; |
| 1012 | int ret = 0; | ||
| 923 | 1013 | ||
| 924 | /* perform soft reset */ | 1014 | /* perform soft reset */ |
| 925 | wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | 1015 | ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
| 1016 | if (ret < 0) | ||
| 1017 | goto out; | ||
| 926 | 1018 | ||
| 927 | /* SOFT_RESET is self clearing */ | 1019 | /* SOFT_RESET is self clearing */ |
| 928 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 1020 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
| 929 | while (1) { | 1021 | while (1) { |
| 930 | boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); | 1022 | ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data); |
| 1023 | if (ret < 0) | ||
| 1024 | goto out; | ||
| 1025 | |||
| 931 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 1026 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
| 932 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 1027 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
| 933 | break; | 1028 | break; |
| @@ -943,12 +1038,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
| 943 | } | 1038 | } |
| 944 | 1039 | ||
| 945 | /* disable Rx/Tx */ | 1040 | /* disable Rx/Tx */ |
| 946 | wl1271_write32(wl, WL12XX_ENABLE, 0x0); | 1041 | ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0); |
| 1042 | if (ret < 0) | ||
| 1043 | goto out; | ||
| 947 | 1044 | ||
| 948 | /* disable auto calibration on start*/ | 1045 | /* disable auto calibration on start*/ |
| 949 | wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); | 1046 | ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff); |
| 950 | 1047 | ||
| 951 | return 0; | 1048 | out: |
| 1049 | return ret; | ||
| 952 | } | 1050 | } |
| 953 | 1051 | ||
| 954 | static int wl12xx_pre_boot(struct wl1271 *wl) | 1052 | static int wl12xx_pre_boot(struct wl1271 *wl) |
| @@ -969,16 +1067,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
| 969 | } | 1067 | } |
| 970 | 1068 | ||
| 971 | /* Continue the ELP wake up sequence */ | 1069 | /* Continue the ELP wake up sequence */ |
| 972 | wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 1070 | ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
| 1071 | if (ret < 0) | ||
| 1072 | goto out; | ||
| 1073 | |||
| 973 | udelay(500); | 1074 | udelay(500); |
| 974 | 1075 | ||
| 975 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1076 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
| 1077 | if (ret < 0) | ||
| 1078 | goto out; | ||
| 976 | 1079 | ||
| 977 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 1080 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
| 978 | to be used by DRPw FW. The RTRIM value will be added by the FW | 1081 | to be used by DRPw FW. The RTRIM value will be added by the FW |
| 979 | before taking DRPw out of reset */ | 1082 | before taking DRPw out of reset */ |
| 980 | 1083 | ||
| 981 | clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); | 1084 | ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk); |
| 1085 | if (ret < 0) | ||
| 1086 | goto out; | ||
| 982 | 1087 | ||
| 983 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 1088 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
| 984 | 1089 | ||
| @@ -987,12 +1092,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
| 987 | else | 1092 | else |
| 988 | clk |= (priv->ref_clock << 1) << 4; | 1093 | clk |= (priv->ref_clock << 1) << 4; |
| 989 | 1094 | ||
| 990 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); | 1095 | ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); |
| 1096 | if (ret < 0) | ||
| 1097 | goto out; | ||
| 991 | 1098 | ||
| 992 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 1099 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
| 1100 | if (ret < 0) | ||
| 1101 | goto out; | ||
| 993 | 1102 | ||
| 994 | /* Disable interrupts */ | 1103 | /* Disable interrupts */ |
| 995 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 1104 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
| 1105 | if (ret < 0) | ||
| 1106 | goto out; | ||
| 996 | 1107 | ||
| 997 | ret = wl1271_boot_soft_reset(wl); | 1108 | ret = wl1271_boot_soft_reset(wl); |
| 998 | if (ret < 0) | 1109 | if (ret < 0) |
| @@ -1002,47 +1113,72 @@ out: | |||
| 1002 | return ret; | 1113 | return ret; |
| 1003 | } | 1114 | } |
| 1004 | 1115 | ||
| 1005 | static void wl12xx_pre_upload(struct wl1271 *wl) | 1116 | static int wl12xx_pre_upload(struct wl1271 *wl) |
| 1006 | { | 1117 | { |
| 1007 | u32 tmp, polarity; | 1118 | u32 tmp; |
| 1119 | u16 polarity; | ||
| 1120 | int ret; | ||
| 1008 | 1121 | ||
| 1009 | /* write firmware's last address (ie. it's length) to | 1122 | /* write firmware's last address (ie. it's length) to |
| 1010 | * ACX_EEPROMLESS_IND_REG */ | 1123 | * ACX_EEPROMLESS_IND_REG */ |
| 1011 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 1124 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
| 1012 | 1125 | ||
| 1013 | wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); | 1126 | ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); |
| 1127 | if (ret < 0) | ||
| 1128 | goto out; | ||
| 1014 | 1129 | ||
| 1015 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 1130 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
| 1131 | if (ret < 0) | ||
| 1132 | goto out; | ||
| 1016 | 1133 | ||
| 1017 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 1134 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
| 1018 | 1135 | ||
| 1019 | /* 6. read the EEPROM parameters */ | 1136 | /* 6. read the EEPROM parameters */ |
| 1020 | tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); | 1137 | ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp); |
| 1138 | if (ret < 0) | ||
| 1139 | goto out; | ||
| 1021 | 1140 | ||
| 1022 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 1141 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
| 1023 | * to upload_fw) */ | 1142 | * to upload_fw) */ |
| 1024 | 1143 | ||
| 1025 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1144 | if (wl->chip.id == CHIP_ID_1283_PG20) { |
| 1026 | wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); | 1145 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); |
| 1146 | if (ret < 0) | ||
| 1147 | goto out; | ||
| 1148 | } | ||
| 1027 | 1149 | ||
| 1028 | /* polarity must be set before the firmware is loaded */ | 1150 | /* polarity must be set before the firmware is loaded */ |
| 1029 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); | 1151 | ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity); |
| 1152 | if (ret < 0) | ||
| 1153 | goto out; | ||
| 1030 | 1154 | ||
| 1031 | /* We use HIGH polarity, so unset the LOW bit */ | 1155 | /* We use HIGH polarity, so unset the LOW bit */ |
| 1032 | polarity &= ~POLARITY_LOW; | 1156 | polarity &= ~POLARITY_LOW; |
| 1033 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); | 1157 | ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); |
| 1034 | 1158 | ||
| 1159 | out: | ||
| 1160 | return ret; | ||
| 1035 | } | 1161 | } |
| 1036 | 1162 | ||
| 1037 | static void wl12xx_enable_interrupts(struct wl1271 *wl) | 1163 | static int wl12xx_enable_interrupts(struct wl1271 *wl) |
| 1038 | { | 1164 | { |
| 1039 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR); | 1165 | int ret; |
| 1166 | |||
| 1167 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, | ||
| 1168 | WL12XX_ACX_ALL_EVENTS_VECTOR); | ||
| 1169 | if (ret < 0) | ||
| 1170 | goto out; | ||
| 1040 | 1171 | ||
| 1041 | wlcore_enable_interrupts(wl); | 1172 | wlcore_enable_interrupts(wl); |
| 1042 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 1173 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
| 1043 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); | 1174 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); |
| 1175 | if (ret < 0) | ||
| 1176 | goto out; | ||
| 1044 | 1177 | ||
| 1045 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); | 1178 | ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); |
| 1179 | |||
| 1180 | out: | ||
| 1181 | return ret; | ||
| 1046 | } | 1182 | } |
| 1047 | 1183 | ||
| 1048 | static int wl12xx_boot(struct wl1271 *wl) | 1184 | static int wl12xx_boot(struct wl1271 *wl) |
| @@ -1057,7 +1193,9 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
| 1057 | if (ret < 0) | 1193 | if (ret < 0) |
| 1058 | goto out; | 1194 | goto out; |
| 1059 | 1195 | ||
| 1060 | wl12xx_pre_upload(wl); | 1196 | ret = wl12xx_pre_upload(wl); |
| 1197 | if (ret < 0) | ||
| 1198 | goto out; | ||
| 1061 | 1199 | ||
| 1062 | ret = wlcore_boot_upload_firmware(wl); | 1200 | ret = wlcore_boot_upload_firmware(wl); |
| 1063 | if (ret < 0) | 1201 | if (ret < 0) |
| @@ -1067,22 +1205,30 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
| 1067 | if (ret < 0) | 1205 | if (ret < 0) |
| 1068 | goto out; | 1206 | goto out; |
| 1069 | 1207 | ||
| 1070 | wl12xx_enable_interrupts(wl); | 1208 | ret = wl12xx_enable_interrupts(wl); |
| 1071 | 1209 | ||
| 1072 | out: | 1210 | out: |
| 1073 | return ret; | 1211 | return ret; |
| 1074 | } | 1212 | } |
| 1075 | 1213 | ||
| 1076 | static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 1214 | static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
| 1077 | void *buf, size_t len) | 1215 | void *buf, size_t len) |
| 1078 | { | 1216 | { |
| 1079 | wl1271_write(wl, cmd_box_addr, buf, len, false); | 1217 | int ret; |
| 1080 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | 1218 | |
| 1219 | ret = wlcore_write(wl, cmd_box_addr, buf, len, false); | ||
| 1220 | if (ret < 0) | ||
| 1221 | return ret; | ||
| 1222 | |||
| 1223 | ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | ||
| 1224 | |||
| 1225 | return ret; | ||
| 1081 | } | 1226 | } |
| 1082 | 1227 | ||
| 1083 | static void wl12xx_ack_event(struct wl1271 *wl) | 1228 | static int wl12xx_ack_event(struct wl1271 *wl) |
| 1084 | { | 1229 | { |
| 1085 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK); | 1230 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
| 1231 | WL12XX_INTR_TRIG_EVENT_ACK); | ||
| 1086 | } | 1232 | } |
| 1087 | 1233 | ||
| 1088 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 1234 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
| @@ -1162,13 +1308,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | |||
| 1162 | return data_len - sizeof(*desc) - desc->pad_len; | 1308 | return data_len - sizeof(*desc) - desc->pad_len; |
| 1163 | } | 1309 | } |
| 1164 | 1310 | ||
| 1165 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) | 1311 | static int wl12xx_tx_delayed_compl(struct wl1271 *wl) |
| 1166 | { | 1312 | { |
| 1167 | if (wl->fw_status_1->tx_results_counter == | 1313 | if (wl->fw_status_1->tx_results_counter == |
| 1168 | (wl->tx_results_count & 0xff)) | 1314 | (wl->tx_results_count & 0xff)) |
| 1169 | return; | 1315 | return 0; |
| 1170 | 1316 | ||
| 1171 | wl1271_tx_complete(wl); | 1317 | return wlcore_tx_complete(wl); |
| 1172 | } | 1318 | } |
| 1173 | 1319 | ||
| 1174 | static int wl12xx_hw_init(struct wl1271 *wl) | 1320 | static int wl12xx_hw_init(struct wl1271 *wl) |
| @@ -1269,39 +1415,58 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | |||
| 1269 | return supported; | 1415 | return supported; |
| 1270 | } | 1416 | } |
| 1271 | 1417 | ||
| 1272 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | 1418 | static int wl12xx_get_fuse_mac(struct wl1271 *wl) |
| 1273 | { | 1419 | { |
| 1274 | u32 mac1, mac2; | 1420 | u32 mac1, mac2; |
| 1421 | int ret; | ||
| 1275 | 1422 | ||
| 1276 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1423 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
| 1424 | if (ret < 0) | ||
| 1425 | goto out; | ||
| 1277 | 1426 | ||
| 1278 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | 1427 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1); |
| 1279 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | 1428 | if (ret < 0) |
| 1429 | goto out; | ||
| 1430 | |||
| 1431 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2); | ||
| 1432 | if (ret < 0) | ||
| 1433 | goto out; | ||
| 1280 | 1434 | ||
| 1281 | /* these are the two parts of the BD_ADDR */ | 1435 | /* these are the two parts of the BD_ADDR */ |
| 1282 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1436 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
| 1283 | ((mac1 & 0xff000000) >> 24); | 1437 | ((mac1 & 0xff000000) >> 24); |
| 1284 | wl->fuse_nic_addr = mac1 & 0xffffff; | 1438 | wl->fuse_nic_addr = mac1 & 0xffffff; |
| 1285 | 1439 | ||
| 1286 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1440 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
| 1441 | |||
| 1442 | out: | ||
| 1443 | return ret; | ||
| 1287 | } | 1444 | } |
| 1288 | 1445 | ||
| 1289 | static s8 wl12xx_get_pg_ver(struct wl1271 *wl) | 1446 | static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
| 1290 | { | 1447 | { |
| 1291 | u32 die_info; | 1448 | u16 die_info; |
| 1449 | int ret; | ||
| 1292 | 1450 | ||
| 1293 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1451 | if (wl->chip.id == CHIP_ID_1283_PG20) |
| 1294 | die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | 1452 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, |
| 1453 | &die_info); | ||
| 1295 | else | 1454 | else |
| 1296 | die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | 1455 | ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1, |
| 1456 | &die_info); | ||
| 1297 | 1457 | ||
| 1298 | return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | 1458 | if (ret >= 0 && ver) |
| 1459 | *ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET); | ||
| 1460 | |||
| 1461 | return ret; | ||
| 1299 | } | 1462 | } |
| 1300 | 1463 | ||
| 1301 | static void wl12xx_get_mac(struct wl1271 *wl) | 1464 | static int wl12xx_get_mac(struct wl1271 *wl) |
| 1302 | { | 1465 | { |
| 1303 | if (wl12xx_mac_in_fuse(wl)) | 1466 | if (wl12xx_mac_in_fuse(wl)) |
| 1304 | wl12xx_get_fuse_mac(wl); | 1467 | return wl12xx_get_fuse_mac(wl); |
| 1468 | |||
| 1469 | return 0; | ||
| 1305 | } | 1470 | } |
| 1306 | 1471 | ||
| 1307 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, | 1472 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, |
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h index ebbaf611e97b..e2609a6b7341 100644 --- a/drivers/net/wireless/ti/wl18xx/acx.h +++ b/drivers/net/wireless/ti/wl18xx/acx.h | |||
| @@ -32,25 +32,21 @@ enum { | |||
| 32 | /* numbers of bits the length field takes (add 1 for the actual number) */ | 32 | /* numbers of bits the length field takes (add 1 for the actual number) */ |
| 33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 | 33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 |
| 34 | 34 | ||
| 35 | #define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 35 | #define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ |
| 36 | WL1271_ACX_INTR_INIT_COMPLETE | \ | 36 | WL1271_ACX_INTR_INIT_COMPLETE | \ |
| 37 | WL1271_ACX_INTR_EVENT_A | \ | 37 | WL1271_ACX_INTR_EVENT_A | \ |
| 38 | WL1271_ACX_INTR_EVENT_B | \ | 38 | WL1271_ACX_INTR_EVENT_B | \ |
| 39 | WL1271_ACX_INTR_CMD_COMPLETE | \ | 39 | WL1271_ACX_INTR_CMD_COMPLETE | \ |
| 40 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 40 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
| 41 | WL1271_ACX_INTR_DATA) | 41 | WL1271_ACX_INTR_DATA | \ |
| 42 | 42 | WL1271_ACX_SW_INTR_WATCHDOG) | |
| 43 | #define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \ | 43 | |
| 44 | WL1271_ACX_SW_INTR_WATCHDOG) | 44 | #define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ |
| 45 | 45 | WL1271_ACX_INTR_EVENT_A | \ | |
| 46 | #define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 46 | WL1271_ACX_INTR_EVENT_B | \ |
| 47 | WL1271_ACX_INTR_EVENT_A | \ | 47 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
| 48 | WL1271_ACX_INTR_EVENT_B | \ | 48 | WL1271_ACX_INTR_DATA | \ |
| 49 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 49 | WL1271_ACX_SW_INTR_WATCHDOG) |
| 50 | WL1271_ACX_INTR_DATA) | ||
| 51 | |||
| 52 | #define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \ | ||
| 53 | WL1271_ACX_SW_INTR_WATCHDOG) | ||
| 54 | 50 | ||
| 55 | struct wl18xx_acx_host_config_bitmap { | 51 | struct wl18xx_acx_host_config_bitmap { |
| 56 | struct acx_header header; | 52 | struct acx_header header; |
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c index 598c057e722b..0c06ccfd1b8c 100644 --- a/drivers/net/wireless/ti/wl18xx/io.c +++ b/drivers/net/wireless/ti/wl18xx/io.c | |||
| @@ -24,37 +24,52 @@ | |||
| 24 | 24 | ||
| 25 | #include "io.h" | 25 | #include "io.h" |
| 26 | 26 | ||
| 27 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 27 | int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
| 28 | { | 28 | { |
| 29 | u32 tmp; | 29 | u32 tmp; |
| 30 | int ret; | ||
| 30 | 31 | ||
| 31 | if (WARN_ON(addr % 2)) | 32 | if (WARN_ON(addr % 2)) |
| 32 | return; | 33 | return -EINVAL; |
| 33 | 34 | ||
| 34 | if ((addr % 4) == 0) { | 35 | if ((addr % 4) == 0) { |
| 35 | tmp = wl1271_read32(wl, addr); | 36 | ret = wlcore_read32(wl, addr, &tmp); |
| 37 | if (ret < 0) | ||
| 38 | goto out; | ||
| 39 | |||
| 36 | tmp = (tmp & 0xffff0000) | val; | 40 | tmp = (tmp & 0xffff0000) | val; |
| 37 | wl1271_write32(wl, addr, tmp); | 41 | ret = wlcore_write32(wl, addr, tmp); |
| 38 | } else { | 42 | } else { |
| 39 | tmp = wl1271_read32(wl, addr - 2); | 43 | ret = wlcore_read32(wl, addr - 2, &tmp); |
| 44 | if (ret < 0) | ||
| 45 | goto out; | ||
| 46 | |||
| 40 | tmp = (tmp & 0xffff) | (val << 16); | 47 | tmp = (tmp & 0xffff) | (val << 16); |
| 41 | wl1271_write32(wl, addr - 2, tmp); | 48 | ret = wlcore_write32(wl, addr - 2, tmp); |
| 42 | } | 49 | } |
| 50 | |||
| 51 | out: | ||
| 52 | return ret; | ||
| 43 | } | 53 | } |
| 44 | 54 | ||
| 45 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) | 55 | int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) |
| 46 | { | 56 | { |
| 47 | u32 val; | 57 | u32 val; |
| 58 | int ret; | ||
| 48 | 59 | ||
| 49 | if (WARN_ON(addr % 2)) | 60 | if (WARN_ON(addr % 2)) |
| 50 | return 0; | 61 | return -EINVAL; |
| 51 | 62 | ||
| 52 | if ((addr % 4) == 0) { | 63 | if ((addr % 4) == 0) { |
| 53 | /* address is 4-bytes aligned */ | 64 | /* address is 4-bytes aligned */ |
| 54 | val = wl1271_read32(wl, addr); | 65 | ret = wlcore_read32(wl, addr, &val); |
| 55 | return val & 0xffff; | 66 | if (ret >= 0 && out) |
| 67 | *out = val & 0xffff; | ||
| 56 | } else { | 68 | } else { |
| 57 | val = wl1271_read32(wl, addr - 2); | 69 | ret = wlcore_read32(wl, addr - 2, &val); |
| 58 | return (val & 0xffff0000) >> 16; | 70 | if (ret >= 0 && out) |
| 71 | *out = (val & 0xffff0000) >> 16; | ||
| 59 | } | 72 | } |
| 73 | |||
| 74 | return ret; | ||
| 60 | } | 75 | } |
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h index be4e126ff617..c32ae30277df 100644 --- a/drivers/net/wireless/ti/wl18xx/io.h +++ b/drivers/net/wireless/ti/wl18xx/io.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #ifndef __WL18XX_IO_H__ | 22 | #ifndef __WL18XX_IO_H__ |
| 23 | #define __WL18XX_IO_H__ | 23 | #define __WL18XX_IO_H__ |
| 24 | 24 | ||
| 25 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); | 25 | int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); |
| 26 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); | 26 | int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out); |
| 27 | 27 | ||
| 28 | #endif /* __WL18XX_IO_H__ */ | 28 | #endif /* __WL18XX_IO_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 271ff81da922..5e583be8f674 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
| @@ -612,20 +612,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
| 612 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | 612 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; |
| 613 | break; | 613 | break; |
| 614 | case CHIP_ID_185x_PG10: | 614 | case CHIP_ID_185x_PG10: |
| 615 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)", | 615 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", |
| 616 | wl->chip.id); | 616 | wl->chip.id); |
| 617 | wl->sr_fw_name = WL18XX_FW_NAME; | 617 | ret = -ENODEV; |
| 618 | /* wl18xx uses the same firmware for PLT */ | 618 | goto out; |
| 619 | wl->plt_fw_name = WL18XX_FW_NAME; | ||
| 620 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | ||
| 621 | WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | | ||
| 622 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
| 623 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
| 624 | |||
| 625 | /* PG 1.0 has some problems with MCS_13, so disable it */ | ||
| 626 | wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5); | ||
| 627 | 619 | ||
| 628 | break; | ||
| 629 | default: | 620 | default: |
| 630 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 621 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
| 631 | ret = -ENODEV; | 622 | ret = -ENODEV; |
| @@ -636,123 +627,178 @@ out: | |||
| 636 | return ret; | 627 | return ret; |
| 637 | } | 628 | } |
| 638 | 629 | ||
| 639 | static void wl18xx_set_clk(struct wl1271 *wl) | 630 | static int wl18xx_set_clk(struct wl1271 *wl) |
| 640 | { | 631 | { |
| 641 | u32 clk_freq; | 632 | u16 clk_freq; |
| 633 | int ret; | ||
| 642 | 634 | ||
| 643 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 635 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
| 636 | if (ret < 0) | ||
| 637 | goto out; | ||
| 644 | 638 | ||
| 645 | /* TODO: PG2: apparently we need to read the clk type */ | 639 | /* TODO: PG2: apparently we need to read the clk type */ |
| 646 | 640 | ||
| 647 | clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); | 641 | ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq); |
| 642 | if (ret < 0) | ||
| 643 | goto out; | ||
| 644 | |||
| 648 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, | 645 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, |
| 649 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, | 646 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, |
| 650 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, | 647 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, |
| 651 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); | 648 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); |
| 652 | 649 | ||
| 653 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); | 650 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, |
| 654 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); | 651 | wl18xx_clk_table[clk_freq].n); |
| 652 | if (ret < 0) | ||
| 653 | goto out; | ||
| 654 | |||
| 655 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, | ||
| 656 | wl18xx_clk_table[clk_freq].m); | ||
| 657 | if (ret < 0) | ||
| 658 | goto out; | ||
| 655 | 659 | ||
| 656 | if (wl18xx_clk_table[clk_freq].swallow) { | 660 | if (wl18xx_clk_table[clk_freq].swallow) { |
| 657 | /* first the 16 lower bits */ | 661 | /* first the 16 lower bits */ |
| 658 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, | 662 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, |
| 659 | wl18xx_clk_table[clk_freq].q & | 663 | wl18xx_clk_table[clk_freq].q & |
| 660 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); | 664 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); |
| 665 | if (ret < 0) | ||
| 666 | goto out; | ||
| 667 | |||
| 661 | /* then the 16 higher bits, masked out */ | 668 | /* then the 16 higher bits, masked out */ |
| 662 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, | 669 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, |
| 663 | (wl18xx_clk_table[clk_freq].q >> 16) & | 670 | (wl18xx_clk_table[clk_freq].q >> 16) & |
| 664 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); | 671 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); |
| 672 | if (ret < 0) | ||
| 673 | goto out; | ||
| 665 | 674 | ||
| 666 | /* first the 16 lower bits */ | 675 | /* first the 16 lower bits */ |
| 667 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, | 676 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, |
| 668 | wl18xx_clk_table[clk_freq].p & | 677 | wl18xx_clk_table[clk_freq].p & |
| 669 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); | 678 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); |
| 679 | if (ret < 0) | ||
| 680 | goto out; | ||
| 681 | |||
| 670 | /* then the 16 higher bits, masked out */ | 682 | /* then the 16 higher bits, masked out */ |
| 671 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, | 683 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, |
| 672 | (wl18xx_clk_table[clk_freq].p >> 16) & | 684 | (wl18xx_clk_table[clk_freq].p >> 16) & |
| 673 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); | 685 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); |
| 674 | } else { | 686 | } else { |
| 675 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, | 687 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, |
| 676 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); | 688 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); |
| 677 | } | 689 | } |
| 690 | |||
| 691 | out: | ||
| 692 | return ret; | ||
| 678 | } | 693 | } |
| 679 | 694 | ||
| 680 | static void wl18xx_boot_soft_reset(struct wl1271 *wl) | 695 | static int wl18xx_boot_soft_reset(struct wl1271 *wl) |
| 681 | { | 696 | { |
| 697 | int ret; | ||
| 698 | |||
| 682 | /* disable Rx/Tx */ | 699 | /* disable Rx/Tx */ |
| 683 | wl1271_write32(wl, WL18XX_ENABLE, 0x0); | 700 | ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0); |
| 701 | if (ret < 0) | ||
| 702 | goto out; | ||
| 684 | 703 | ||
| 685 | /* disable auto calibration on start*/ | 704 | /* disable auto calibration on start*/ |
| 686 | wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff); | 705 | ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff); |
| 706 | |||
| 707 | out: | ||
| 708 | return ret; | ||
| 687 | } | 709 | } |
| 688 | 710 | ||
| 689 | static int wl18xx_pre_boot(struct wl1271 *wl) | 711 | static int wl18xx_pre_boot(struct wl1271 *wl) |
| 690 | { | 712 | { |
| 691 | wl18xx_set_clk(wl); | 713 | int ret; |
| 714 | |||
| 715 | ret = wl18xx_set_clk(wl); | ||
| 716 | if (ret < 0) | ||
| 717 | goto out; | ||
| 692 | 718 | ||
| 693 | /* Continue the ELP wake up sequence */ | 719 | /* Continue the ELP wake up sequence */ |
| 694 | wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 720 | ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
| 721 | if (ret < 0) | ||
| 722 | goto out; | ||
| 723 | |||
| 695 | udelay(500); | 724 | udelay(500); |
| 696 | 725 | ||
| 697 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 726 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
| 727 | if (ret < 0) | ||
| 728 | goto out; | ||
| 698 | 729 | ||
| 699 | /* Disable interrupts */ | 730 | /* Disable interrupts */ |
| 700 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 731 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
| 732 | if (ret < 0) | ||
| 733 | goto out; | ||
| 701 | 734 | ||
| 702 | wl18xx_boot_soft_reset(wl); | 735 | ret = wl18xx_boot_soft_reset(wl); |
| 703 | 736 | ||
| 704 | return 0; | 737 | out: |
| 738 | return ret; | ||
| 705 | } | 739 | } |
| 706 | 740 | ||
| 707 | static void wl18xx_pre_upload(struct wl1271 *wl) | 741 | static int wl18xx_pre_upload(struct wl1271 *wl) |
| 708 | { | 742 | { |
| 709 | u32 tmp; | 743 | u32 tmp; |
| 744 | int ret; | ||
| 710 | 745 | ||
| 711 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 746 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
| 747 | if (ret < 0) | ||
| 748 | goto out; | ||
| 712 | 749 | ||
| 713 | /* TODO: check if this is all needed */ | 750 | /* TODO: check if this is all needed */ |
| 714 | wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); | 751 | ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); |
| 752 | if (ret < 0) | ||
| 753 | goto out; | ||
| 715 | 754 | ||
| 716 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 755 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
| 756 | if (ret < 0) | ||
| 757 | goto out; | ||
| 717 | 758 | ||
| 718 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 759 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
| 719 | 760 | ||
| 720 | tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); | 761 | ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp); |
| 762 | |||
| 763 | out: | ||
| 764 | return ret; | ||
| 721 | } | 765 | } |
| 722 | 766 | ||
| 723 | static void wl18xx_set_mac_and_phy(struct wl1271 *wl) | 767 | static int wl18xx_set_mac_and_phy(struct wl1271 *wl) |
| 724 | { | 768 | { |
| 725 | struct wl18xx_priv *priv = wl->priv; | 769 | struct wl18xx_priv *priv = wl->priv; |
| 726 | size_t len; | 770 | int ret; |
| 727 | 771 | ||
| 728 | /* the parameters struct is smaller for PG1 */ | 772 | ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); |
| 729 | if (wl->chip.id == CHIP_ID_185x_PG10) | 773 | if (ret < 0) |
| 730 | len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1; | 774 | goto out; |
| 731 | else | ||
| 732 | len = sizeof(struct wl18xx_mac_and_phy_params); | ||
| 733 | 775 | ||
| 734 | wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); | 776 | ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, |
| 735 | wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, | 777 | sizeof(struct wl18xx_mac_and_phy_params), false); |
| 736 | false); | 778 | |
| 779 | out: | ||
| 780 | return ret; | ||
| 737 | } | 781 | } |
| 738 | 782 | ||
| 739 | static void wl18xx_enable_interrupts(struct wl1271 *wl) | 783 | static int wl18xx_enable_interrupts(struct wl1271 *wl) |
| 740 | { | 784 | { |
| 741 | u32 event_mask, intr_mask; | 785 | u32 event_mask, intr_mask; |
| 786 | int ret; | ||
| 742 | 787 | ||
| 743 | if (wl->chip.id == CHIP_ID_185x_PG10) { | 788 | event_mask = WL18XX_ACX_EVENTS_VECTOR; |
| 744 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1; | 789 | intr_mask = WL18XX_INTR_MASK; |
| 745 | intr_mask = WL18XX_INTR_MASK_PG1; | ||
| 746 | } else { | ||
| 747 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2; | ||
| 748 | intr_mask = WL18XX_INTR_MASK_PG2; | ||
| 749 | } | ||
| 750 | 790 | ||
| 751 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); | 791 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); |
| 792 | if (ret < 0) | ||
| 793 | goto out; | ||
| 752 | 794 | ||
| 753 | wlcore_enable_interrupts(wl); | 795 | wlcore_enable_interrupts(wl); |
| 754 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 796 | |
| 755 | WL1271_ACX_INTR_ALL & ~intr_mask); | 797 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
| 798 | WL1271_ACX_INTR_ALL & ~intr_mask); | ||
| 799 | |||
| 800 | out: | ||
| 801 | return ret; | ||
| 756 | } | 802 | } |
| 757 | 803 | ||
| 758 | static int wl18xx_boot(struct wl1271 *wl) | 804 | static int wl18xx_boot(struct wl1271 *wl) |
| @@ -763,25 +809,29 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
| 763 | if (ret < 0) | 809 | if (ret < 0) |
| 764 | goto out; | 810 | goto out; |
| 765 | 811 | ||
| 766 | wl18xx_pre_upload(wl); | 812 | ret = wl18xx_pre_upload(wl); |
| 813 | if (ret < 0) | ||
| 814 | goto out; | ||
| 767 | 815 | ||
| 768 | ret = wlcore_boot_upload_firmware(wl); | 816 | ret = wlcore_boot_upload_firmware(wl); |
| 769 | if (ret < 0) | 817 | if (ret < 0) |
| 770 | goto out; | 818 | goto out; |
| 771 | 819 | ||
| 772 | wl18xx_set_mac_and_phy(wl); | 820 | ret = wl18xx_set_mac_and_phy(wl); |
| 821 | if (ret < 0) | ||
| 822 | goto out; | ||
| 773 | 823 | ||
| 774 | ret = wlcore_boot_run_firmware(wl); | 824 | ret = wlcore_boot_run_firmware(wl); |
| 775 | if (ret < 0) | 825 | if (ret < 0) |
| 776 | goto out; | 826 | goto out; |
| 777 | 827 | ||
| 778 | wl18xx_enable_interrupts(wl); | 828 | ret = wl18xx_enable_interrupts(wl); |
| 779 | 829 | ||
| 780 | out: | 830 | out: |
| 781 | return ret; | 831 | return ret; |
| 782 | } | 832 | } |
| 783 | 833 | ||
| 784 | static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 834 | static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
| 785 | void *buf, size_t len) | 835 | void *buf, size_t len) |
| 786 | { | 836 | { |
| 787 | struct wl18xx_priv *priv = wl->priv; | 837 | struct wl18xx_priv *priv = wl->priv; |
| @@ -789,13 +839,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | |||
| 789 | memcpy(priv->cmd_buf, buf, len); | 839 | memcpy(priv->cmd_buf, buf, len); |
| 790 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); | 840 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); |
| 791 | 841 | ||
| 792 | wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE, | 842 | return wlcore_write(wl, cmd_box_addr, priv->cmd_buf, |
| 793 | false); | 843 | WL18XX_CMD_MAX_SIZE, false); |
| 794 | } | 844 | } |
| 795 | 845 | ||
| 796 | static void wl18xx_ack_event(struct wl1271 *wl) | 846 | static int wl18xx_ack_event(struct wl1271 *wl) |
| 797 | { | 847 | { |
| 798 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK); | 848 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
| 849 | WL18XX_INTR_TRIG_EVENT_ACK); | ||
| 799 | } | 850 | } |
| 800 | 851 | ||
| 801 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 852 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
| @@ -977,34 +1028,32 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
| 977 | } else if (!strcmp(ht_mode_param, "mimo")) { | 1028 | } else if (!strcmp(ht_mode_param, "mimo")) { |
| 978 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); | 1029 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); |
| 979 | 1030 | ||
| 980 | /* | ||
| 981 | * PG 1.0 has some problems with MCS_13, so disable it | ||
| 982 | * | ||
| 983 | * TODO: instead of hacking this in here, we should | ||
| 984 | * make it more general and change a bit in the | ||
| 985 | * wlvif->rate_set instead. | ||
| 986 | */ | ||
| 987 | if (wl->chip.id == CHIP_ID_185x_PG10) | ||
| 988 | return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13; | ||
| 989 | |||
| 990 | return CONF_TX_MIMO_RATES; | 1031 | return CONF_TX_MIMO_RATES; |
| 991 | } else { | 1032 | } else { |
| 992 | return 0; | 1033 | return 0; |
| 993 | } | 1034 | } |
| 994 | } | 1035 | } |
| 995 | 1036 | ||
| 996 | static s8 wl18xx_get_pg_ver(struct wl1271 *wl) | 1037 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
| 997 | { | 1038 | { |
| 998 | u32 fuse; | 1039 | u32 fuse; |
| 1040 | int ret; | ||
| 999 | 1041 | ||
| 1000 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1042 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
| 1043 | if (ret < 0) | ||
| 1044 | goto out; | ||
| 1001 | 1045 | ||
| 1002 | fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); | 1046 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse); |
| 1003 | fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1047 | if (ret < 0) |
| 1048 | goto out; | ||
| 1049 | |||
| 1050 | if (ver) | ||
| 1051 | *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | ||
| 1004 | 1052 | ||
| 1005 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1053 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
| 1006 | 1054 | ||
| 1007 | return (s8)fuse; | 1055 | out: |
| 1056 | return ret; | ||
| 1008 | } | 1057 | } |
| 1009 | 1058 | ||
| 1010 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" | 1059 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" |
| @@ -1070,26 +1119,41 @@ out: | |||
| 1070 | 1119 | ||
| 1071 | static int wl18xx_plt_init(struct wl1271 *wl) | 1120 | static int wl18xx_plt_init(struct wl1271 *wl) |
| 1072 | { | 1121 | { |
| 1073 | wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | 1122 | int ret; |
| 1123 | |||
| 1124 | ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | ||
| 1125 | if (ret < 0) | ||
| 1126 | return ret; | ||
| 1074 | 1127 | ||
| 1075 | return wl->ops->boot(wl); | 1128 | return wl->ops->boot(wl); |
| 1076 | } | 1129 | } |
| 1077 | 1130 | ||
| 1078 | static void wl18xx_get_mac(struct wl1271 *wl) | 1131 | static int wl18xx_get_mac(struct wl1271 *wl) |
| 1079 | { | 1132 | { |
| 1080 | u32 mac1, mac2; | 1133 | u32 mac1, mac2; |
| 1134 | int ret; | ||
| 1081 | 1135 | ||
| 1082 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1136 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
| 1137 | if (ret < 0) | ||
| 1138 | goto out; | ||
| 1083 | 1139 | ||
| 1084 | mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); | 1140 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1); |
| 1085 | mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); | 1141 | if (ret < 0) |
| 1142 | goto out; | ||
| 1143 | |||
| 1144 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2); | ||
| 1145 | if (ret < 0) | ||
| 1146 | goto out; | ||
| 1086 | 1147 | ||
| 1087 | /* these are the two parts of the BD_ADDR */ | 1148 | /* these are the two parts of the BD_ADDR */ |
| 1088 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1149 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
| 1089 | ((mac1 & 0xff000000) >> 24); | 1150 | ((mac1 & 0xff000000) >> 24); |
| 1090 | wl->fuse_nic_addr = (mac1 & 0xffffff); | 1151 | wl->fuse_nic_addr = (mac1 & 0xffffff); |
| 1091 | 1152 | ||
| 1092 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1153 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
| 1154 | |||
| 1155 | out: | ||
| 1156 | return ret; | ||
| 1093 | } | 1157 | } |
| 1094 | 1158 | ||
| 1095 | static int wl18xx_handle_static_data(struct wl1271 *wl, | 1159 | static int wl18xx_handle_static_data(struct wl1271 *wl, |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 0fda500c01c9..8965960b841a 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
| @@ -33,16 +33,22 @@ | |||
| 33 | #include "rx.h" | 33 | #include "rx.h" |
| 34 | #include "hw_ops.h" | 34 | #include "hw_ops.h" |
| 35 | 35 | ||
| 36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | 36 | static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) |
| 37 | { | 37 | { |
| 38 | u32 cpu_ctrl; | 38 | u32 cpu_ctrl; |
| 39 | int ret; | ||
| 39 | 40 | ||
| 40 | /* 10.5.0 run the firmware (I) */ | 41 | /* 10.5.0 run the firmware (I) */ |
| 41 | cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); | 42 | ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl); |
| 43 | if (ret < 0) | ||
| 44 | goto out; | ||
| 42 | 45 | ||
| 43 | /* 10.5.1 run the firmware (II) */ | 46 | /* 10.5.1 run the firmware (II) */ |
| 44 | cpu_ctrl |= flag; | 47 | cpu_ctrl |= flag; |
| 45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); | 48 | ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); |
| 49 | |||
| 50 | out: | ||
| 51 | return ret; | ||
| 46 | } | 52 | } |
| 47 | 53 | ||
| 48 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, | 54 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, |
| @@ -87,7 +93,9 @@ static int wlcore_boot_static_data(struct wl1271 *wl) | |||
| 87 | goto out; | 93 | goto out; |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | wl1271_read(wl, wl->cmd_box_addr, static_data, len, false); | 96 | ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false); |
| 97 | if (ret < 0) | ||
| 98 | goto out_free; | ||
| 91 | 99 | ||
| 92 | ret = wlcore_boot_parse_fw_ver(wl, static_data); | 100 | ret = wlcore_boot_parse_fw_ver(wl, static_data); |
| 93 | if (ret < 0) | 101 | if (ret < 0) |
| @@ -109,6 +117,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
| 109 | struct wlcore_partition_set partition; | 117 | struct wlcore_partition_set partition; |
| 110 | int addr, chunk_num, partition_limit; | 118 | int addr, chunk_num, partition_limit; |
| 111 | u8 *p, *chunk; | 119 | u8 *p, *chunk; |
| 120 | int ret; | ||
| 112 | 121 | ||
| 113 | /* whal_FwCtrl_LoadFwImageSm() */ | 122 | /* whal_FwCtrl_LoadFwImageSm() */ |
| 114 | 123 | ||
| @@ -130,7 +139,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
| 130 | 139 | ||
| 131 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); | 140 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); |
| 132 | partition.mem.start = dest; | 141 | partition.mem.start = dest; |
| 133 | wlcore_set_partition(wl, &partition); | 142 | ret = wlcore_set_partition(wl, &partition); |
| 143 | if (ret < 0) | ||
| 144 | return ret; | ||
| 134 | 145 | ||
| 135 | /* 10.1 set partition limit and chunk num */ | 146 | /* 10.1 set partition limit and chunk num */ |
| 136 | chunk_num = 0; | 147 | chunk_num = 0; |
| @@ -144,7 +155,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
| 144 | partition_limit = chunk_num * CHUNK_SIZE + | 155 | partition_limit = chunk_num * CHUNK_SIZE + |
| 145 | wl->ptable[PART_DOWN].mem.size; | 156 | wl->ptable[PART_DOWN].mem.size; |
| 146 | partition.mem.start = addr; | 157 | partition.mem.start = addr; |
| 147 | wlcore_set_partition(wl, &partition); | 158 | ret = wlcore_set_partition(wl, &partition); |
| 159 | if (ret < 0) | ||
| 160 | return ret; | ||
| 148 | } | 161 | } |
| 149 | 162 | ||
| 150 | /* 10.3 upload the chunk */ | 163 | /* 10.3 upload the chunk */ |
| @@ -153,7 +166,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
| 153 | memcpy(chunk, p, CHUNK_SIZE); | 166 | memcpy(chunk, p, CHUNK_SIZE); |
| 154 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 167 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
| 155 | p, addr); | 168 | p, addr); |
| 156 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); | 169 | ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false); |
| 170 | if (ret < 0) | ||
| 171 | goto out; | ||
| 157 | 172 | ||
| 158 | chunk_num++; | 173 | chunk_num++; |
| 159 | } | 174 | } |
| @@ -164,10 +179,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
| 164 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | 179 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); |
| 165 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 180 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
| 166 | fw_data_len % CHUNK_SIZE, p, addr); | 181 | fw_data_len % CHUNK_SIZE, p, addr); |
| 167 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | 182 | ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
| 168 | 183 | ||
| 184 | out: | ||
| 169 | kfree(chunk); | 185 | kfree(chunk); |
| 170 | return 0; | 186 | return ret; |
| 171 | } | 187 | } |
| 172 | 188 | ||
| 173 | int wlcore_boot_upload_firmware(struct wl1271 *wl) | 189 | int wlcore_boot_upload_firmware(struct wl1271 *wl) |
| @@ -210,6 +226,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
| 210 | int i; | 226 | int i; |
| 211 | u32 dest_addr, val; | 227 | u32 dest_addr, val; |
| 212 | u8 *nvs_ptr, *nvs_aligned; | 228 | u8 *nvs_ptr, *nvs_aligned; |
| 229 | int ret; | ||
| 213 | 230 | ||
| 214 | if (wl->nvs == NULL) { | 231 | if (wl->nvs == NULL) { |
| 215 | wl1271_error("NVS file is needed during boot"); | 232 | wl1271_error("NVS file is needed during boot"); |
| @@ -307,7 +324,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
| 307 | wl1271_debug(DEBUG_BOOT, | 324 | wl1271_debug(DEBUG_BOOT, |
| 308 | "nvs burst write 0x%x: 0x%x", | 325 | "nvs burst write 0x%x: 0x%x", |
| 309 | dest_addr, val); | 326 | dest_addr, val); |
| 310 | wl1271_write32(wl, dest_addr, val); | 327 | ret = wlcore_write32(wl, dest_addr, val); |
| 328 | if (ret < 0) | ||
| 329 | return ret; | ||
| 311 | 330 | ||
| 312 | nvs_ptr += 4; | 331 | nvs_ptr += 4; |
| 313 | dest_addr += 4; | 332 | dest_addr += 4; |
| @@ -333,7 +352,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
| 333 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | 352 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; |
| 334 | 353 | ||
| 335 | /* Now we must set the partition correctly */ | 354 | /* Now we must set the partition correctly */ |
| 336 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 355 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
| 356 | if (ret < 0) | ||
| 357 | return ret; | ||
| 337 | 358 | ||
| 338 | /* Copy the NVS tables to a new block to ensure alignment */ | 359 | /* Copy the NVS tables to a new block to ensure alignment */ |
| 339 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 360 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
| @@ -341,11 +362,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
| 341 | return -ENOMEM; | 362 | return -ENOMEM; |
| 342 | 363 | ||
| 343 | /* And finally we upload the NVS tables */ | 364 | /* And finally we upload the NVS tables */ |
| 344 | wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, | 365 | ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, |
| 345 | nvs_aligned, nvs_len, false); | 366 | false); |
| 346 | 367 | ||
| 347 | kfree(nvs_aligned); | 368 | kfree(nvs_aligned); |
| 348 | return 0; | 369 | return ret; |
| 349 | 370 | ||
| 350 | out_badnvs: | 371 | out_badnvs: |
| 351 | wl1271_error("nvs data is malformed"); | 372 | wl1271_error("nvs data is malformed"); |
| @@ -359,11 +380,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 359 | u32 chip_id, intr; | 380 | u32 chip_id, intr; |
| 360 | 381 | ||
| 361 | /* Make sure we have the boot partition */ | 382 | /* Make sure we have the boot partition */ |
| 362 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 383 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
| 384 | if (ret < 0) | ||
| 385 | return ret; | ||
| 363 | 386 | ||
| 364 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 387 | ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
| 388 | if (ret < 0) | ||
| 389 | return ret; | ||
| 365 | 390 | ||
| 366 | chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 391 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id); |
| 392 | if (ret < 0) | ||
| 393 | return ret; | ||
| 367 | 394 | ||
| 368 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 395 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
| 369 | 396 | ||
| @@ -376,7 +403,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 376 | loop = 0; | 403 | loop = 0; |
| 377 | while (loop++ < INIT_LOOP) { | 404 | while (loop++ < INIT_LOOP) { |
| 378 | udelay(INIT_LOOP_DELAY); | 405 | udelay(INIT_LOOP_DELAY); |
| 379 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 406 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
| 407 | if (ret < 0) | ||
| 408 | return ret; | ||
| 380 | 409 | ||
| 381 | if (intr == 0xffffffff) { | 410 | if (intr == 0xffffffff) { |
| 382 | wl1271_error("error reading hardware complete " | 411 | wl1271_error("error reading hardware complete " |
| @@ -385,8 +414,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 385 | } | 414 | } |
| 386 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 415 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
| 387 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { | 416 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { |
| 388 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, | 417 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
| 389 | WL1271_ACX_INTR_INIT_COMPLETE); | 418 | WL1271_ACX_INTR_INIT_COMPLETE); |
| 419 | if (ret < 0) | ||
| 420 | return ret; | ||
| 390 | break; | 421 | break; |
| 391 | } | 422 | } |
| 392 | } | 423 | } |
| @@ -398,12 +429,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 398 | } | 429 | } |
| 399 | 430 | ||
| 400 | /* get hardware config command mail box */ | 431 | /* get hardware config command mail box */ |
| 401 | wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); | 432 | ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr); |
| 433 | if (ret < 0) | ||
| 434 | return ret; | ||
| 402 | 435 | ||
| 403 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); | 436 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); |
| 404 | 437 | ||
| 405 | /* get hardware config event mail box */ | 438 | /* get hardware config event mail box */ |
| 406 | wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); | 439 | ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]); |
| 440 | if (ret < 0) | ||
| 441 | return ret; | ||
| 442 | |||
| 407 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 443 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
| 408 | 444 | ||
| 409 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | 445 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", |
| @@ -445,9 +481,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
| 445 | } | 481 | } |
| 446 | 482 | ||
| 447 | /* set the working partition to its "running" mode offset */ | 483 | /* set the working partition to its "running" mode offset */ |
| 448 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 484 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
| 449 | 485 | ||
| 450 | /* firmware startup completed */ | 486 | /* firmware startup completed */ |
| 451 | return 0; | 487 | return ret; |
| 452 | } | 488 | } |
| 453 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); | 489 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 885364ca4344..56c7a2342fdf 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
| @@ -65,17 +65,24 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
| 65 | WARN_ON(len % 4 != 0); | 65 | WARN_ON(len % 4 != 0); |
| 66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); | 66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); |
| 67 | 67 | ||
| 68 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); | 68 | ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false); |
| 69 | if (ret < 0) | ||
| 70 | goto fail; | ||
| 69 | 71 | ||
| 70 | /* | 72 | /* |
| 71 | * TODO: we just need this because one bit is in a different | 73 | * TODO: we just need this because one bit is in a different |
| 72 | * place. Is there any better way? | 74 | * place. Is there any better way? |
| 73 | */ | 75 | */ |
| 74 | wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); | 76 | ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); |
| 77 | if (ret < 0) | ||
| 78 | goto fail; | ||
| 75 | 79 | ||
| 76 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
| 77 | 81 | ||
| 78 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 82 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
| 83 | if (ret < 0) | ||
| 84 | goto fail; | ||
| 85 | |||
| 79 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 86 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
| 80 | if (time_after(jiffies, timeout)) { | 87 | if (time_after(jiffies, timeout)) { |
| 81 | wl1271_error("command complete timeout"); | 88 | wl1271_error("command complete timeout"); |
| @@ -89,13 +96,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
| 89 | else | 96 | else |
| 90 | msleep(1); | 97 | msleep(1); |
| 91 | 98 | ||
| 92 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 99 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
| 100 | if (ret < 0) | ||
| 101 | goto fail; | ||
| 93 | } | 102 | } |
| 94 | 103 | ||
| 95 | /* read back the status code of the command */ | 104 | /* read back the status code of the command */ |
| 96 | if (res_len == 0) | 105 | if (res_len == 0) |
| 97 | res_len = sizeof(struct wl1271_cmd_header); | 106 | res_len = sizeof(struct wl1271_cmd_header); |
| 98 | wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 107 | |
| 108 | ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false); | ||
| 109 | if (ret < 0) | ||
| 110 | goto fail; | ||
| 99 | 111 | ||
| 100 | status = le16_to_cpu(cmd->status); | 112 | status = le16_to_cpu(cmd->status); |
| 101 | if (status != CMD_STATUS_SUCCESS) { | 113 | if (status != CMD_STATUS_SUCCESS) { |
| @@ -104,11 +116,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
| 104 | goto fail; | 116 | goto fail; |
| 105 | } | 117 | } |
| 106 | 118 | ||
| 107 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); | 119 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
| 120 | WL1271_ACX_INTR_CMD_COMPLETE); | ||
| 121 | if (ret < 0) | ||
| 122 | goto fail; | ||
| 123 | |||
| 108 | return 0; | 124 | return 0; |
| 109 | 125 | ||
| 110 | fail: | 126 | fail: |
| 111 | WARN_ON(1); | ||
| 112 | wl12xx_queue_recovery_work(wl); | 127 | wl12xx_queue_recovery_work(wl); |
| 113 | return ret; | 128 | return ret; |
| 114 | } | 129 | } |
| @@ -117,35 +132,45 @@ fail: | |||
| 117 | * Poll the mailbox event field until any of the bits in the mask is set or a | 132 | * Poll the mailbox event field until any of the bits in the mask is set or a |
| 118 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 133 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
| 119 | */ | 134 | */ |
| 120 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | 135 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, |
| 136 | u32 mask, bool *timeout) | ||
| 121 | { | 137 | { |
| 122 | u32 *events_vector; | 138 | u32 *events_vector; |
| 123 | u32 event; | 139 | u32 event; |
| 124 | unsigned long timeout; | 140 | unsigned long timeout_time; |
| 125 | int ret = 0; | 141 | int ret = 0; |
| 126 | 142 | ||
| 143 | *timeout = false; | ||
| 144 | |||
| 127 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); | 145 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); |
| 128 | if (!events_vector) | 146 | if (!events_vector) |
| 129 | return -ENOMEM; | 147 | return -ENOMEM; |
| 130 | 148 | ||
| 131 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 149 | timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
| 132 | 150 | ||
| 133 | do { | 151 | do { |
| 134 | if (time_after(jiffies, timeout)) { | 152 | if (time_after(jiffies, timeout_time)) { |
| 135 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", | 153 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", |
| 136 | (int)mask); | 154 | (int)mask); |
| 137 | ret = -ETIMEDOUT; | 155 | *timeout = true; |
| 138 | goto out; | 156 | goto out; |
| 139 | } | 157 | } |
| 140 | 158 | ||
| 141 | msleep(1); | 159 | msleep(1); |
| 142 | 160 | ||
| 143 | /* read from both event fields */ | 161 | /* read from both event fields */ |
| 144 | wl1271_read(wl, wl->mbox_ptr[0], events_vector, | 162 | ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector, |
| 145 | sizeof(*events_vector), false); | 163 | sizeof(*events_vector), false); |
| 164 | if (ret < 0) | ||
| 165 | goto out; | ||
| 166 | |||
| 146 | event = *events_vector & mask; | 167 | event = *events_vector & mask; |
| 147 | wl1271_read(wl, wl->mbox_ptr[1], events_vector, | 168 | |
| 148 | sizeof(*events_vector), false); | 169 | ret = wlcore_read(wl, wl->mbox_ptr[1], events_vector, |
| 170 | sizeof(*events_vector), false); | ||
| 171 | if (ret < 0) | ||
| 172 | goto out; | ||
| 173 | |||
| 149 | event |= *events_vector & mask; | 174 | event |= *events_vector & mask; |
| 150 | } while (!event); | 175 | } while (!event); |
| 151 | 176 | ||
| @@ -157,9 +182,10 @@ out: | |||
| 157 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | 182 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) |
| 158 | { | 183 | { |
| 159 | int ret; | 184 | int ret; |
| 185 | bool timeout = false; | ||
| 160 | 186 | ||
| 161 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); | 187 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout); |
| 162 | if (ret != 0) { | 188 | if (ret != 0 || timeout) { |
| 163 | wl12xx_queue_recovery_work(wl); | 189 | wl12xx_queue_recovery_work(wl); |
| 164 | return ret; | 190 | return ret; |
| 165 | } | 191 | } |
| @@ -1412,6 +1438,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
| 1412 | { | 1438 | { |
| 1413 | struct wl12xx_cmd_remove_peer *cmd; | 1439 | struct wl12xx_cmd_remove_peer *cmd; |
| 1414 | int ret; | 1440 | int ret; |
| 1441 | bool timeout = false; | ||
| 1415 | 1442 | ||
| 1416 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); | 1443 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); |
| 1417 | 1444 | ||
| @@ -1432,12 +1459,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
| 1432 | goto out_free; | 1459 | goto out_free; |
| 1433 | } | 1460 | } |
| 1434 | 1461 | ||
| 1462 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, | ||
| 1463 | PEER_REMOVE_COMPLETE_EVENT_ID, | ||
| 1464 | &timeout); | ||
| 1435 | /* | 1465 | /* |
| 1436 | * We are ok with a timeout here. The event is sometimes not sent | 1466 | * We are ok with a timeout here. The event is sometimes not sent |
| 1437 | * due to a firmware bug. | 1467 | * due to a firmware bug. In case of another error (like SDIO timeout) |
| 1468 | * queue a recovery. | ||
| 1438 | */ | 1469 | */ |
| 1439 | wl1271_cmd_wait_for_event_or_timeout(wl, | 1470 | if (ret) |
| 1440 | PEER_REMOVE_COMPLETE_EVENT_ID); | 1471 | wl12xx_queue_recovery_work(wl); |
| 1441 | 1472 | ||
| 1442 | out_free: | 1473 | out_free: |
| 1443 | kfree(cmd); | 1474 | kfree(cmd); |
| @@ -1754,7 +1785,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
| 1754 | return -EINVAL; | 1785 | return -EINVAL; |
| 1755 | 1786 | ||
| 1756 | /* flush all pending packets */ | 1787 | /* flush all pending packets */ |
| 1757 | wl1271_tx_work_locked(wl); | 1788 | ret = wlcore_tx_work_locked(wl); |
| 1789 | if (ret < 0) | ||
| 1790 | goto out; | ||
| 1758 | 1791 | ||
| 1759 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { | 1792 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { |
| 1760 | ret = wl12xx_croc(wl, wlvif->dev_role_id); | 1793 | ret = wl12xx_croc(wl, wlvif->dev_role_id); |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 1768f37049bd..80dbc5304fac 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | /* ms */ | 38 | /* ms */ |
| 39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
| 40 | 40 | ||
| 41 | #define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE)) | ||
| 42 | |||
| 41 | /* debugfs macros idea from mac80211 */ | 43 | /* debugfs macros idea from mac80211 */ |
| 42 | int wl1271_format_buffer(char __user *userbuf, size_t count, | 44 | int wl1271_format_buffer(char __user *userbuf, size_t count, |
| 43 | loff_t *ppos, char *fmt, ...) | 45 | loff_t *ppos, char *fmt, ...) |
| @@ -1025,6 +1027,195 @@ static const struct file_operations sleep_auth_ops = { | |||
| 1025 | .llseek = default_llseek, | 1027 | .llseek = default_llseek, |
| 1026 | }; | 1028 | }; |
| 1027 | 1029 | ||
| 1030 | static ssize_t dev_mem_read(struct file *file, | ||
| 1031 | char __user *user_buf, size_t count, | ||
| 1032 | loff_t *ppos) | ||
| 1033 | { | ||
| 1034 | struct wl1271 *wl = file->private_data; | ||
| 1035 | struct wlcore_partition_set part, old_part; | ||
| 1036 | size_t bytes = count; | ||
| 1037 | int ret; | ||
| 1038 | char *buf; | ||
| 1039 | |||
| 1040 | /* only requests of dword-aligned size and offset are supported */ | ||
| 1041 | if (bytes % 4) | ||
| 1042 | return -EINVAL; | ||
| 1043 | |||
| 1044 | if (*ppos % 4) | ||
| 1045 | return -EINVAL; | ||
| 1046 | |||
| 1047 | /* function should return in reasonable time */ | ||
| 1048 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
| 1049 | |||
| 1050 | if (bytes == 0) | ||
| 1051 | return -EINVAL; | ||
| 1052 | |||
| 1053 | memset(&part, 0, sizeof(part)); | ||
| 1054 | part.mem.start = file->f_pos; | ||
| 1055 | part.mem.size = bytes; | ||
| 1056 | |||
| 1057 | buf = kmalloc(bytes, GFP_KERNEL); | ||
| 1058 | if (!buf) | ||
| 1059 | return -ENOMEM; | ||
| 1060 | |||
| 1061 | mutex_lock(&wl->mutex); | ||
| 1062 | |||
| 1063 | if (wl->state == WL1271_STATE_OFF) { | ||
| 1064 | ret = -EFAULT; | ||
| 1065 | goto skip_read; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | ret = wl1271_ps_elp_wakeup(wl); | ||
| 1069 | if (ret < 0) | ||
| 1070 | goto skip_read; | ||
| 1071 | |||
| 1072 | /* store current partition and switch partition */ | ||
| 1073 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
| 1074 | ret = wlcore_set_partition(wl, &part); | ||
| 1075 | if (ret < 0) | ||
| 1076 | goto part_err; | ||
| 1077 | |||
| 1078 | ret = wlcore_raw_read(wl, 0, buf, bytes, false); | ||
| 1079 | if (ret < 0) | ||
| 1080 | goto read_err; | ||
| 1081 | |||
| 1082 | read_err: | ||
| 1083 | /* recover partition */ | ||
| 1084 | ret = wlcore_set_partition(wl, &old_part); | ||
| 1085 | if (ret < 0) | ||
| 1086 | goto part_err; | ||
| 1087 | |||
| 1088 | part_err: | ||
| 1089 | wl1271_ps_elp_sleep(wl); | ||
| 1090 | |||
| 1091 | skip_read: | ||
| 1092 | mutex_unlock(&wl->mutex); | ||
| 1093 | |||
| 1094 | if (ret == 0) { | ||
| 1095 | ret = copy_to_user(user_buf, buf, bytes); | ||
| 1096 | if (ret < bytes) { | ||
| 1097 | bytes -= ret; | ||
| 1098 | *ppos += bytes; | ||
| 1099 | ret = 0; | ||
| 1100 | } else { | ||
| 1101 | ret = -EFAULT; | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | kfree(buf); | ||
| 1106 | |||
| 1107 | return ((ret == 0) ? bytes : ret); | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, | ||
| 1111 | size_t count, loff_t *ppos) | ||
| 1112 | { | ||
| 1113 | struct wl1271 *wl = file->private_data; | ||
| 1114 | struct wlcore_partition_set part, old_part; | ||
| 1115 | size_t bytes = count; | ||
| 1116 | int ret; | ||
| 1117 | char *buf; | ||
| 1118 | |||
| 1119 | /* only requests of dword-aligned size and offset are supported */ | ||
| 1120 | if (bytes % 4) | ||
| 1121 | return -EINVAL; | ||
| 1122 | |||
| 1123 | if (*ppos % 4) | ||
| 1124 | return -EINVAL; | ||
| 1125 | |||
| 1126 | /* function should return in reasonable time */ | ||
| 1127 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
| 1128 | |||
| 1129 | if (bytes == 0) | ||
| 1130 | return -EINVAL; | ||
| 1131 | |||
| 1132 | memset(&part, 0, sizeof(part)); | ||
| 1133 | part.mem.start = file->f_pos; | ||
| 1134 | part.mem.size = bytes; | ||
| 1135 | |||
| 1136 | buf = kmalloc(bytes, GFP_KERNEL); | ||
| 1137 | if (!buf) | ||
| 1138 | return -ENOMEM; | ||
| 1139 | |||
| 1140 | ret = copy_from_user(buf, user_buf, bytes); | ||
| 1141 | if (ret) { | ||
| 1142 | ret = -EFAULT; | ||
| 1143 | goto err_out; | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | mutex_lock(&wl->mutex); | ||
| 1147 | |||
| 1148 | if (wl->state == WL1271_STATE_OFF) { | ||
| 1149 | ret = -EFAULT; | ||
| 1150 | goto skip_write; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | ret = wl1271_ps_elp_wakeup(wl); | ||
| 1154 | if (ret < 0) | ||
| 1155 | goto skip_write; | ||
| 1156 | |||
| 1157 | /* store current partition and switch partition */ | ||
| 1158 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
| 1159 | ret = wlcore_set_partition(wl, &part); | ||
| 1160 | if (ret < 0) | ||
| 1161 | goto part_err; | ||
| 1162 | |||
| 1163 | ret = wlcore_raw_write(wl, 0, buf, bytes, false); | ||
| 1164 | if (ret < 0) | ||
| 1165 | goto write_err; | ||
| 1166 | |||
| 1167 | write_err: | ||
| 1168 | /* recover partition */ | ||
| 1169 | ret = wlcore_set_partition(wl, &old_part); | ||
| 1170 | if (ret < 0) | ||
| 1171 | goto part_err; | ||
| 1172 | |||
| 1173 | part_err: | ||
| 1174 | wl1271_ps_elp_sleep(wl); | ||
| 1175 | |||
| 1176 | skip_write: | ||
| 1177 | mutex_unlock(&wl->mutex); | ||
| 1178 | |||
| 1179 | if (ret == 0) | ||
| 1180 | *ppos += bytes; | ||
| 1181 | |||
| 1182 | err_out: | ||
| 1183 | kfree(buf); | ||
| 1184 | |||
| 1185 | return ((ret == 0) ? bytes : ret); | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig) | ||
| 1189 | { | ||
| 1190 | loff_t ret; | ||
| 1191 | |||
| 1192 | /* only requests of dword-aligned size and offset are supported */ | ||
| 1193 | if (offset % 4) | ||
| 1194 | return -EINVAL; | ||
| 1195 | |||
| 1196 | switch (orig) { | ||
| 1197 | case SEEK_SET: | ||
| 1198 | file->f_pos = offset; | ||
| 1199 | ret = file->f_pos; | ||
| 1200 | break; | ||
| 1201 | case SEEK_CUR: | ||
| 1202 | file->f_pos += offset; | ||
| 1203 | ret = file->f_pos; | ||
| 1204 | break; | ||
| 1205 | default: | ||
| 1206 | ret = -EINVAL; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | return ret; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static const struct file_operations dev_mem_ops = { | ||
| 1213 | .open = simple_open, | ||
| 1214 | .read = dev_mem_read, | ||
| 1215 | .write = dev_mem_write, | ||
| 1216 | .llseek = dev_mem_seek, | ||
| 1217 | }; | ||
| 1218 | |||
| 1028 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 1219 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
| 1029 | struct dentry *rootdir) | 1220 | struct dentry *rootdir) |
| 1030 | { | 1221 | { |
| @@ -1059,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
| 1059 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); | 1250 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); |
| 1060 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); | 1251 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); |
| 1061 | 1252 | ||
| 1253 | DEBUGFS_ADD_PREFIX(dev, mem, rootdir); | ||
| 1062 | 1254 | ||
| 1063 | return 0; | 1255 | return 0; |
| 1064 | 1256 | ||
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index c976f0409865..48907054d493 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
| @@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
| 105 | u32 vector; | 105 | u32 vector; |
| 106 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
| 107 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
| 108 | int ret; | ||
| 108 | 109 | ||
| 109 | wl1271_event_mbox_dump(mbox); | 110 | wl1271_event_mbox_dump(mbox); |
| 110 | 111 | ||
| @@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
| 228 | 229 | ||
| 229 | if ((vector & DUMMY_PACKET_EVENT_ID)) { | 230 | if ((vector & DUMMY_PACKET_EVENT_ID)) { |
| 230 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); | 231 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
| 231 | wl1271_tx_dummy_packet(wl); | 232 | ret = wl1271_tx_dummy_packet(wl); |
| 233 | if (ret < 0) | ||
| 234 | return ret; | ||
| 232 | } | 235 | } |
| 233 | 236 | ||
| 234 | /* | 237 | /* |
| @@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
| 301 | return -EINVAL; | 304 | return -EINVAL; |
| 302 | 305 | ||
| 303 | /* first we read the mbox descriptor */ | 306 | /* first we read the mbox descriptor */ |
| 304 | wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, | 307 | ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, |
| 305 | sizeof(*wl->mbox), false); | 308 | sizeof(*wl->mbox), false); |
| 309 | if (ret < 0) | ||
| 310 | return ret; | ||
| 306 | 311 | ||
| 307 | /* process the descriptor */ | 312 | /* process the descriptor */ |
| 308 | ret = wl1271_event_process(wl); | 313 | ret = wl1271_event_process(wl); |
| @@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
| 313 | * TODO: we just need this because one bit is in a different | 318 | * TODO: we just need this because one bit is in a different |
| 314 | * place. Is there any better way? | 319 | * place. Is there any better way? |
| 315 | */ | 320 | */ |
| 316 | wl->ops->ack_event(wl); | 321 | ret = wl->ops->ack_event(wl); |
| 317 | 322 | ||
| 318 | return 0; | 323 | return ret; |
| 319 | } | 324 | } |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 9e7787ba9610..2673d783ec1e 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
| @@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | |||
| 65 | return wl->ops->get_rx_buf_align(wl, rx_desc); | 65 | return wl->ops->get_rx_buf_align(wl, rx_desc); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static inline void | 68 | static inline int |
| 69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
| 70 | { | 70 | { |
| 71 | if (wl->ops->prepare_read) | 71 | if (wl->ops->prepare_read) |
| 72 | wl->ops->prepare_read(wl, rx_desc, len); | 72 | return wl->ops->prepare_read(wl, rx_desc, len); |
| 73 | |||
| 74 | return 0; | ||
| 73 | } | 75 | } |
| 74 | 76 | ||
| 75 | static inline u32 | 77 | static inline u32 |
| @@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len) | |||
| 81 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); | 83 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl) | 86 | static inline int wlcore_hw_tx_delayed_compl(struct wl1271 *wl) |
| 85 | { | 87 | { |
| 86 | if (wl->ops->tx_delayed_compl) | 88 | if (wl->ops->tx_delayed_compl) |
| 87 | wl->ops->tx_delayed_compl(wl); | 89 | return wl->ops->tx_delayed_compl(wl); |
| 90 | |||
| 91 | return 0; | ||
| 88 | } | 92 | } |
| 89 | 93 | ||
| 90 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) | 94 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) |
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index 7cd0081aede5..9976219c4e49 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c | |||
| @@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl) | |||
| 48 | } | 48 | } |
| 49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); | 49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); |
| 50 | 50 | ||
| 51 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl) | ||
| 52 | { | ||
| 53 | disable_irq_nosync(wl->irq); | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync); | ||
| 56 | |||
| 51 | void wlcore_enable_interrupts(struct wl1271 *wl) | 57 | void wlcore_enable_interrupts(struct wl1271 *wl) |
| 52 | { | 58 | { |
| 53 | enable_irq(wl->irq); | 59 | enable_irq(wl->irq); |
| @@ -122,9 +128,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr); | |||
| 122 | * | | | 128 | * | | |
| 123 | * | 129 | * |
| 124 | */ | 130 | */ |
| 125 | void wlcore_set_partition(struct wl1271 *wl, | 131 | int wlcore_set_partition(struct wl1271 *wl, |
| 126 | const struct wlcore_partition_set *p) | 132 | const struct wlcore_partition_set *p) |
| 127 | { | 133 | { |
| 134 | int ret; | ||
| 135 | |||
| 128 | /* copy partition info */ | 136 | /* copy partition info */ |
| 129 | memcpy(&wl->curr_part, p, sizeof(*p)); | 137 | memcpy(&wl->curr_part, p, sizeof(*p)); |
| 130 | 138 | ||
| @@ -137,28 +145,41 @@ void wlcore_set_partition(struct wl1271 *wl, | |||
| 137 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", | 145 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", |
| 138 | p->mem3.start, p->mem3.size); | 146 | p->mem3.start, p->mem3.size); |
| 139 | 147 | ||
| 140 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | 148 | ret = wlcore_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); |
| 141 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | 149 | if (ret < 0) |
| 142 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | 150 | goto out; |
| 143 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | 151 | |
| 144 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | 152 | ret = wlcore_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); |
| 145 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | 153 | if (ret < 0) |
| 154 | goto out; | ||
| 155 | |||
| 156 | ret = wlcore_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
| 157 | if (ret < 0) | ||
| 158 | goto out; | ||
| 159 | |||
| 160 | ret = wlcore_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
| 161 | if (ret < 0) | ||
| 162 | goto out; | ||
| 163 | |||
| 164 | ret = wlcore_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
| 165 | if (ret < 0) | ||
| 166 | goto out; | ||
| 167 | |||
| 168 | ret = wlcore_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
| 169 | if (ret < 0) | ||
| 170 | goto out; | ||
| 171 | |||
| 146 | /* | 172 | /* |
| 147 | * We don't need the size of the last partition, as it is | 173 | * We don't need the size of the last partition, as it is |
| 148 | * automatically calculated based on the total memory size and | 174 | * automatically calculated based on the total memory size and |
| 149 | * the sizes of the previous partitions. | 175 | * the sizes of the previous partitions. |
| 150 | */ | 176 | */ |
| 151 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | 177 | ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); |
| 152 | } | ||
| 153 | EXPORT_SYMBOL_GPL(wlcore_set_partition); | ||
| 154 | 178 | ||
| 155 | void wlcore_select_partition(struct wl1271 *wl, u8 part) | 179 | out: |
| 156 | { | 180 | return ret; |
| 157 | wl1271_debug(DEBUG_IO, "setting partition %d", part); | ||
| 158 | |||
| 159 | wlcore_set_partition(wl, &wl->ptable[part]); | ||
| 160 | } | 181 | } |
| 161 | EXPORT_SYMBOL_GPL(wlcore_select_partition); | 182 | EXPORT_SYMBOL_GPL(wlcore_set_partition); |
| 162 | 183 | ||
| 163 | void wl1271_io_reset(struct wl1271 *wl) | 184 | void wl1271_io_reset(struct wl1271 *wl) |
| 164 | { | 185 | { |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 8942954b56a0..fef80adc8bf5 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | struct wl1271; | 45 | struct wl1271; |
| 46 | 46 | ||
| 47 | void wlcore_disable_interrupts(struct wl1271 *wl); | 47 | void wlcore_disable_interrupts(struct wl1271 *wl); |
| 48 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl); | ||
| 48 | void wlcore_enable_interrupts(struct wl1271 *wl); | 49 | void wlcore_enable_interrupts(struct wl1271 *wl); |
| 49 | 50 | ||
| 50 | void wl1271_io_reset(struct wl1271 *wl); | 51 | void wl1271_io_reset(struct wl1271 *wl); |
| @@ -52,79 +53,113 @@ void wl1271_io_init(struct wl1271 *wl); | |||
| 52 | int wlcore_translate_addr(struct wl1271 *wl, int addr); | 53 | int wlcore_translate_addr(struct wl1271 *wl, int addr); |
| 53 | 54 | ||
| 54 | /* Raw target IO, address is not translated */ | 55 | /* Raw target IO, address is not translated */ |
| 55 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 56 | static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, |
| 56 | size_t len, bool fixed) | 57 | void *buf, size_t len, |
| 58 | bool fixed) | ||
| 57 | { | 59 | { |
| 58 | wl->if_ops->write(wl->dev, addr, buf, len, fixed); | 60 | int ret; |
| 61 | |||
| 62 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
| 63 | return -EIO; | ||
| 64 | |||
| 65 | ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); | ||
| 66 | if (ret) | ||
| 67 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
| 68 | |||
| 69 | return ret; | ||
| 59 | } | 70 | } |
| 60 | 71 | ||
| 61 | static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | 72 | static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, |
| 62 | size_t len, bool fixed) | 73 | void *buf, size_t len, |
| 74 | bool fixed) | ||
| 63 | { | 75 | { |
| 64 | wl->if_ops->read(wl->dev, addr, buf, len, fixed); | 76 | int ret; |
| 77 | |||
| 78 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
| 79 | return -EIO; | ||
| 80 | |||
| 81 | ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); | ||
| 82 | if (ret) | ||
| 83 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
| 84 | |||
| 85 | return ret; | ||
| 65 | } | 86 | } |
| 66 | 87 | ||
| 67 | static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf, | 88 | static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg, |
| 68 | size_t len, bool fixed) | 89 | void *buf, size_t len, |
| 90 | bool fixed) | ||
| 69 | { | 91 | { |
| 70 | wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed); | 92 | return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed); |
| 71 | } | 93 | } |
| 72 | 94 | ||
| 73 | static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf, | 95 | static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg, |
| 74 | size_t len, bool fixed) | 96 | void *buf, size_t len, |
| 97 | bool fixed) | ||
| 75 | { | 98 | { |
| 76 | wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed); | 99 | return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed); |
| 77 | } | 100 | } |
| 78 | 101 | ||
| 79 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 102 | static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr, |
| 103 | u32 *val) | ||
| 80 | { | 104 | { |
| 81 | wl1271_raw_read(wl, addr, &wl->buffer_32, | 105 | int ret; |
| 82 | sizeof(wl->buffer_32), false); | 106 | |
| 107 | ret = wlcore_raw_read(wl, addr, &wl->buffer_32, | ||
| 108 | sizeof(wl->buffer_32), false); | ||
| 109 | if (ret < 0) | ||
| 110 | return ret; | ||
| 111 | |||
| 112 | if (val) | ||
| 113 | *val = le32_to_cpu(wl->buffer_32); | ||
| 83 | 114 | ||
| 84 | return le32_to_cpu(wl->buffer_32); | 115 | return 0; |
| 85 | } | 116 | } |
| 86 | 117 | ||
| 87 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | 118 | static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr, |
| 119 | u32 val) | ||
| 88 | { | 120 | { |
| 89 | wl->buffer_32 = cpu_to_le32(val); | 121 | wl->buffer_32 = cpu_to_le32(val); |
| 90 | wl1271_raw_write(wl, addr, &wl->buffer_32, | 122 | return wlcore_raw_write(wl, addr, &wl->buffer_32, |
| 91 | sizeof(wl->buffer_32), false); | 123 | sizeof(wl->buffer_32), false); |
| 92 | } | 124 | } |
| 93 | 125 | ||
| 94 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | 126 | static inline int __must_check wlcore_read(struct wl1271 *wl, int addr, |
| 95 | size_t len, bool fixed) | 127 | void *buf, size_t len, bool fixed) |
| 96 | { | 128 | { |
| 97 | int physical; | 129 | int physical; |
| 98 | 130 | ||
| 99 | physical = wlcore_translate_addr(wl, addr); | 131 | physical = wlcore_translate_addr(wl, addr); |
| 100 | 132 | ||
| 101 | wl1271_raw_read(wl, physical, buf, len, fixed); | 133 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
| 102 | } | 134 | } |
| 103 | 135 | ||
| 104 | static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | 136 | static inline int __must_check wlcore_write(struct wl1271 *wl, int addr, |
| 105 | size_t len, bool fixed) | 137 | void *buf, size_t len, bool fixed) |
| 106 | { | 138 | { |
| 107 | int physical; | 139 | int physical; |
| 108 | 140 | ||
| 109 | physical = wlcore_translate_addr(wl, addr); | 141 | physical = wlcore_translate_addr(wl, addr); |
| 110 | 142 | ||
| 111 | wl1271_raw_write(wl, physical, buf, len, fixed); | 143 | return wlcore_raw_write(wl, physical, buf, len, fixed); |
| 112 | } | 144 | } |
| 113 | 145 | ||
| 114 | static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf, | 146 | static inline int __must_check wlcore_write_data(struct wl1271 *wl, int reg, |
| 115 | size_t len, bool fixed) | 147 | void *buf, size_t len, |
| 148 | bool fixed) | ||
| 116 | { | 149 | { |
| 117 | wl1271_write(wl, wl->rtable[reg], buf, len, fixed); | 150 | return wlcore_write(wl, wl->rtable[reg], buf, len, fixed); |
| 118 | } | 151 | } |
| 119 | 152 | ||
| 120 | static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf, | 153 | static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg, |
| 121 | size_t len, bool fixed) | 154 | void *buf, size_t len, |
| 155 | bool fixed) | ||
| 122 | { | 156 | { |
| 123 | wl1271_read(wl, wl->rtable[reg], buf, len, fixed); | 157 | return wlcore_read(wl, wl->rtable[reg], buf, len, fixed); |
| 124 | } | 158 | } |
| 125 | 159 | ||
| 126 | static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | 160 | static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, |
| 127 | void *buf, size_t len, bool fixed) | 161 | void *buf, size_t len, |
| 162 | bool fixed) | ||
| 128 | { | 163 | { |
| 129 | int physical; | 164 | int physical; |
| 130 | int addr; | 165 | int addr; |
| @@ -134,34 +169,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
| 134 | 169 | ||
| 135 | physical = wlcore_translate_addr(wl, addr); | 170 | physical = wlcore_translate_addr(wl, addr); |
| 136 | 171 | ||
| 137 | wl1271_raw_read(wl, physical, buf, len, fixed); | 172 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
| 138 | } | 173 | } |
| 139 | 174 | ||
| 140 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | 175 | static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr, |
| 176 | u32 *val) | ||
| 141 | { | 177 | { |
| 142 | return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr)); | 178 | return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val); |
| 143 | } | 179 | } |
| 144 | 180 | ||
| 145 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | 181 | static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr, |
| 182 | u32 val) | ||
| 146 | { | 183 | { |
| 147 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); | 184 | return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val); |
| 148 | } | 185 | } |
| 149 | 186 | ||
| 150 | static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) | 187 | static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg, |
| 188 | u32 *val) | ||
| 151 | { | 189 | { |
| 152 | return wl1271_raw_read32(wl, | 190 | return wlcore_raw_read32(wl, |
| 153 | wlcore_translate_addr(wl, wl->rtable[reg])); | 191 | wlcore_translate_addr(wl, wl->rtable[reg]), |
| 192 | val); | ||
| 154 | } | 193 | } |
| 155 | 194 | ||
| 156 | static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) | 195 | static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg, |
| 196 | u32 val) | ||
| 157 | { | 197 | { |
| 158 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val); | 198 | return wlcore_raw_write32(wl, |
| 199 | wlcore_translate_addr(wl, wl->rtable[reg]), | ||
| 200 | val); | ||
| 159 | } | 201 | } |
| 160 | 202 | ||
| 161 | static inline void wl1271_power_off(struct wl1271 *wl) | 203 | static inline void wl1271_power_off(struct wl1271 *wl) |
| 162 | { | 204 | { |
| 163 | wl->if_ops->power(wl->dev, false); | 205 | int ret; |
| 164 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 206 | |
| 207 | if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags)) | ||
| 208 | return; | ||
| 209 | |||
| 210 | ret = wl->if_ops->power(wl->dev, false); | ||
| 211 | if (!ret) | ||
| 212 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
| 165 | } | 213 | } |
| 166 | 214 | ||
| 167 | static inline int wl1271_power_on(struct wl1271 *wl) | 215 | static inline int wl1271_power_on(struct wl1271 *wl) |
| @@ -173,8 +221,8 @@ static inline int wl1271_power_on(struct wl1271 *wl) | |||
| 173 | return ret; | 221 | return ret; |
| 174 | } | 222 | } |
| 175 | 223 | ||
| 176 | void wlcore_set_partition(struct wl1271 *wl, | 224 | int wlcore_set_partition(struct wl1271 *wl, |
| 177 | const struct wlcore_partition_set *p); | 225 | const struct wlcore_partition_set *p); |
| 178 | 226 | ||
| 179 | bool wl1271_set_block_size(struct wl1271 *wl); | 227 | bool wl1271_set_block_size(struct wl1271 *wl); |
| 180 | 228 | ||
| @@ -182,6 +230,4 @@ bool wl1271_set_block_size(struct wl1271 *wl); | |||
| 182 | 230 | ||
| 183 | int wl1271_tx_dummy_packet(struct wl1271 *wl); | 231 | int wl1271_tx_dummy_packet(struct wl1271 *wl); |
| 184 | 232 | ||
| 185 | void wlcore_select_partition(struct wl1271 *wl, u8 part); | ||
| 186 | |||
| 187 | #endif | 233 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 78edc58da210..2240cca597ac 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
| @@ -378,9 +378,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
| 378 | } | 378 | } |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static void wl12xx_fw_status(struct wl1271 *wl, | 381 | static int wlcore_fw_status(struct wl1271 *wl, |
| 382 | struct wl_fw_status_1 *status_1, | 382 | struct wl_fw_status_1 *status_1, |
| 383 | struct wl_fw_status_2 *status_2) | 383 | struct wl_fw_status_2 *status_2) |
| 384 | { | 384 | { |
| 385 | struct wl12xx_vif *wlvif; | 385 | struct wl12xx_vif *wlvif; |
| 386 | struct timespec ts; | 386 | struct timespec ts; |
| @@ -388,12 +388,15 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
| 388 | int avail, freed_blocks; | 388 | int avail, freed_blocks; |
| 389 | int i; | 389 | int i; |
| 390 | size_t status_len; | 390 | size_t status_len; |
| 391 | int ret; | ||
| 391 | 392 | ||
| 392 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + | 393 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
| 393 | sizeof(*status_2) + wl->fw_status_priv_len; | 394 | sizeof(*status_2) + wl->fw_status_priv_len; |
| 394 | 395 | ||
| 395 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, | 396 | ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, |
| 396 | status_len, false); | 397 | status_len, false); |
| 398 | if (ret < 0) | ||
| 399 | return ret; | ||
| 397 | 400 | ||
| 398 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 401 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
| 399 | "drv_rx_counter = %d, tx_results_counter = %d)", | 402 | "drv_rx_counter = %d, tx_results_counter = %d)", |
| @@ -462,6 +465,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
| 462 | getnstimeofday(&ts); | 465 | getnstimeofday(&ts); |
| 463 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 466 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
| 464 | (s64)le32_to_cpu(status_2->fw_localtime); | 467 | (s64)le32_to_cpu(status_2->fw_localtime); |
| 468 | |||
| 469 | return 0; | ||
| 465 | } | 470 | } |
| 466 | 471 | ||
| 467 | static void wl1271_flush_deferred_work(struct wl1271 *wl) | 472 | static void wl1271_flush_deferred_work(struct wl1271 *wl) |
| @@ -489,20 +494,15 @@ static void wl1271_netstack_work(struct work_struct *work) | |||
| 489 | 494 | ||
| 490 | #define WL1271_IRQ_MAX_LOOPS 256 | 495 | #define WL1271_IRQ_MAX_LOOPS 256 |
| 491 | 496 | ||
| 492 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 497 | static int wlcore_irq_locked(struct wl1271 *wl) |
| 493 | { | 498 | { |
| 494 | int ret; | 499 | int ret = 0; |
| 495 | u32 intr; | 500 | u32 intr; |
| 496 | int loopcount = WL1271_IRQ_MAX_LOOPS; | 501 | int loopcount = WL1271_IRQ_MAX_LOOPS; |
| 497 | struct wl1271 *wl = (struct wl1271 *)cookie; | ||
| 498 | bool done = false; | 502 | bool done = false; |
| 499 | unsigned int defer_count; | 503 | unsigned int defer_count; |
| 500 | unsigned long flags; | 504 | unsigned long flags; |
| 501 | 505 | ||
| 502 | /* TX might be handled here, avoid redundant work */ | ||
| 503 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
| 504 | cancel_work_sync(&wl->tx_work); | ||
| 505 | |||
| 506 | /* | 506 | /* |
| 507 | * In case edge triggered interrupt must be used, we cannot iterate | 507 | * In case edge triggered interrupt must be used, we cannot iterate |
| 508 | * more than once without introducing race conditions with the hardirq. | 508 | * more than once without introducing race conditions with the hardirq. |
| @@ -510,8 +510,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | 510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) |
| 511 | loopcount = 1; | 511 | loopcount = 1; |
| 512 | 512 | ||
| 513 | mutex_lock(&wl->mutex); | ||
| 514 | |||
| 515 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 513 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
| 516 | 514 | ||
| 517 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 515 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
| @@ -530,7 +528,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 530 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | 528 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); |
| 531 | smp_mb__after_clear_bit(); | 529 | smp_mb__after_clear_bit(); |
| 532 | 530 | ||
| 533 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 531 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
| 532 | if (ret < 0) | ||
| 533 | goto out; | ||
| 534 | 534 | ||
| 535 | wlcore_hw_tx_immediate_compl(wl); | 535 | wlcore_hw_tx_immediate_compl(wl); |
| 536 | 536 | ||
| @@ -544,7 +544,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { | 544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { |
| 545 | wl1271_error("HW watchdog interrupt received! starting recovery."); | 545 | wl1271_error("HW watchdog interrupt received! starting recovery."); |
| 546 | wl->watchdog_recovery = true; | 546 | wl->watchdog_recovery = true; |
| 547 | wl12xx_queue_recovery_work(wl); | 547 | ret = -EIO; |
| 548 | 548 | ||
| 549 | /* restarting the chip. ignore any other interrupt. */ | 549 | /* restarting the chip. ignore any other interrupt. */ |
| 550 | goto out; | 550 | goto out; |
| @@ -554,7 +554,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 554 | wl1271_error("SW watchdog interrupt received! " | 554 | wl1271_error("SW watchdog interrupt received! " |
| 555 | "starting recovery."); | 555 | "starting recovery."); |
| 556 | wl->watchdog_recovery = true; | 556 | wl->watchdog_recovery = true; |
| 557 | wl12xx_queue_recovery_work(wl); | 557 | ret = -EIO; |
| 558 | 558 | ||
| 559 | /* restarting the chip. ignore any other interrupt. */ | 559 | /* restarting the chip. ignore any other interrupt. */ |
| 560 | goto out; | 560 | goto out; |
| @@ -563,7 +563,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { | 563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { |
| 564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
| 565 | 565 | ||
| 566 | wl12xx_rx(wl, wl->fw_status_1); | 566 | ret = wlcore_rx(wl, wl->fw_status_1); |
| 567 | if (ret < 0) | ||
| 568 | goto out; | ||
| 567 | 569 | ||
| 568 | /* Check if any tx blocks were freed */ | 570 | /* Check if any tx blocks were freed */ |
| 569 | spin_lock_irqsave(&wl->wl_lock, flags); | 571 | spin_lock_irqsave(&wl->wl_lock, flags); |
| @@ -574,13 +576,17 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 574 | * In order to avoid starvation of the TX path, | 576 | * In order to avoid starvation of the TX path, |
| 575 | * call the work function directly. | 577 | * call the work function directly. |
| 576 | */ | 578 | */ |
| 577 | wl1271_tx_work_locked(wl); | 579 | ret = wlcore_tx_work_locked(wl); |
| 580 | if (ret < 0) | ||
| 581 | goto out; | ||
| 578 | } else { | 582 | } else { |
| 579 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 583 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
| 580 | } | 584 | } |
| 581 | 585 | ||
| 582 | /* check for tx results */ | 586 | /* check for tx results */ |
| 583 | wlcore_hw_tx_delayed_compl(wl); | 587 | ret = wlcore_hw_tx_delayed_compl(wl); |
| 588 | if (ret < 0) | ||
| 589 | goto out; | ||
| 584 | 590 | ||
| 585 | /* Make sure the deferred queues don't get too long */ | 591 | /* Make sure the deferred queues don't get too long */ |
| 586 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + | 592 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + |
| @@ -591,12 +597,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 591 | 597 | ||
| 592 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 598 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
| 593 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 599 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
| 594 | wl1271_event_handle(wl, 0); | 600 | ret = wl1271_event_handle(wl, 0); |
| 601 | if (ret < 0) | ||
| 602 | goto out; | ||
| 595 | } | 603 | } |
| 596 | 604 | ||
| 597 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 605 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
| 598 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 606 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
| 599 | wl1271_event_handle(wl, 1); | 607 | ret = wl1271_event_handle(wl, 1); |
| 608 | if (ret < 0) | ||
| 609 | goto out; | ||
| 600 | } | 610 | } |
| 601 | 611 | ||
| 602 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 612 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
| @@ -610,6 +620,25 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 610 | wl1271_ps_elp_sleep(wl); | 620 | wl1271_ps_elp_sleep(wl); |
| 611 | 621 | ||
| 612 | out: | 622 | out: |
| 623 | return ret; | ||
| 624 | } | ||
| 625 | |||
| 626 | static irqreturn_t wlcore_irq(int irq, void *cookie) | ||
| 627 | { | ||
| 628 | int ret; | ||
| 629 | unsigned long flags; | ||
| 630 | struct wl1271 *wl = cookie; | ||
| 631 | |||
| 632 | /* TX might be handled here, avoid redundant work */ | ||
| 633 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
| 634 | cancel_work_sync(&wl->tx_work); | ||
| 635 | |||
| 636 | mutex_lock(&wl->mutex); | ||
| 637 | |||
| 638 | ret = wlcore_irq_locked(wl); | ||
| 639 | if (ret) | ||
| 640 | wl12xx_queue_recovery_work(wl); | ||
| 641 | |||
| 613 | spin_lock_irqsave(&wl->wl_lock, flags); | 642 | spin_lock_irqsave(&wl->wl_lock, flags); |
| 614 | /* In case TX was not handled here, queue TX work */ | 643 | /* In case TX was not handled here, queue TX work */ |
| 615 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 644 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
| @@ -743,8 +772,13 @@ out: | |||
| 743 | 772 | ||
| 744 | void wl12xx_queue_recovery_work(struct wl1271 *wl) | 773 | void wl12xx_queue_recovery_work(struct wl1271 *wl) |
| 745 | { | 774 | { |
| 746 | if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | 775 | WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
| 776 | |||
| 777 | /* Avoid a recursive recovery */ | ||
| 778 | if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
| 779 | wlcore_disable_interrupts_nosync(wl); | ||
| 747 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 780 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
| 781 | } | ||
| 748 | } | 782 | } |
| 749 | 783 | ||
| 750 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | 784 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) |
| @@ -778,6 +812,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 778 | u32 offset; | 812 | u32 offset; |
| 779 | u32 end_of_log; | 813 | u32 end_of_log; |
| 780 | u8 *block; | 814 | u8 *block; |
| 815 | int ret; | ||
| 781 | 816 | ||
| 782 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || | 817 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || |
| 783 | (wl->conf.fwlog.mem_blocks == 0)) | 818 | (wl->conf.fwlog.mem_blocks == 0)) |
| @@ -799,7 +834,10 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 799 | wl12xx_cmd_stop_fwlog(wl); | 834 | wl12xx_cmd_stop_fwlog(wl); |
| 800 | 835 | ||
| 801 | /* Read the first memory block address */ | 836 | /* Read the first memory block address */ |
| 802 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 837 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
| 838 | if (ret < 0) | ||
| 839 | goto out; | ||
| 840 | |||
| 803 | addr = le32_to_cpu(wl->fw_status_2->log_start_addr); | 841 | addr = le32_to_cpu(wl->fw_status_2->log_start_addr); |
| 804 | if (!addr) | 842 | if (!addr) |
| 805 | goto out; | 843 | goto out; |
| @@ -815,8 +853,10 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 815 | /* Traverse the memory blocks linked list */ | 853 | /* Traverse the memory blocks linked list */ |
| 816 | do { | 854 | do { |
| 817 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); | 855 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); |
| 818 | wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, | 856 | ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, |
| 819 | false); | 857 | false); |
| 858 | if (ret < 0) | ||
| 859 | goto out; | ||
| 820 | 860 | ||
| 821 | /* | 861 | /* |
| 822 | * Memory blocks are linked to one another. The first 4 bytes | 862 | * Memory blocks are linked to one another. The first 4 bytes |
| @@ -836,6 +876,34 @@ out: | |||
| 836 | kfree(block); | 876 | kfree(block); |
| 837 | } | 877 | } |
| 838 | 878 | ||
| 879 | static void wlcore_print_recovery(struct wl1271 *wl) | ||
| 880 | { | ||
| 881 | u32 pc = 0; | ||
| 882 | u32 hint_sts = 0; | ||
| 883 | int ret; | ||
| 884 | |||
| 885 | wl1271_info("Hardware recovery in progress. FW ver: %s", | ||
| 886 | wl->chip.fw_ver_str); | ||
| 887 | |||
| 888 | /* change partitions momentarily so we can read the FW pc */ | ||
| 889 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
| 890 | if (ret < 0) | ||
| 891 | return; | ||
| 892 | |||
| 893 | ret = wlcore_read_reg(wl, REG_PC_ON_RECOVERY, &pc); | ||
| 894 | if (ret < 0) | ||
| 895 | return; | ||
| 896 | |||
| 897 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &hint_sts); | ||
| 898 | if (ret < 0) | ||
| 899 | return; | ||
| 900 | |||
| 901 | wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts); | ||
| 902 | |||
| 903 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
| 904 | } | ||
| 905 | |||
| 906 | |||
| 839 | static void wl1271_recovery_work(struct work_struct *work) | 907 | static void wl1271_recovery_work(struct work_struct *work) |
| 840 | { | 908 | { |
| 841 | struct wl1271 *wl = | 909 | struct wl1271 *wl = |
| @@ -848,19 +916,9 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
| 848 | if (wl->state != WL1271_STATE_ON || wl->plt) | 916 | if (wl->state != WL1271_STATE_ON || wl->plt) |
| 849 | goto out_unlock; | 917 | goto out_unlock; |
| 850 | 918 | ||
| 851 | /* Avoid a recursive recovery */ | ||
| 852 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
| 853 | |||
| 854 | wl12xx_read_fwlog_panic(wl); | 919 | wl12xx_read_fwlog_panic(wl); |
| 855 | 920 | ||
| 856 | /* change partitions momentarily so we can read the FW pc */ | 921 | wlcore_print_recovery(wl); |
| 857 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
| 858 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x " | ||
| 859 | "hint_sts: 0x%08x", | ||
| 860 | wl->chip.fw_ver_str, | ||
| 861 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY), | ||
| 862 | wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR)); | ||
| 863 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
| 864 | 922 | ||
| 865 | BUG_ON(bug_on_recovery && | 923 | BUG_ON(bug_on_recovery && |
| 866 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 924 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
| @@ -902,8 +960,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
| 902 | mutex_unlock(&wl->mutex); | 960 | mutex_unlock(&wl->mutex); |
| 903 | wl1271_op_stop(wl->hw); | 961 | wl1271_op_stop(wl->hw); |
| 904 | 962 | ||
| 905 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
| 906 | |||
| 907 | ieee80211_restart_hw(wl->hw); | 963 | ieee80211_restart_hw(wl->hw); |
| 908 | 964 | ||
| 909 | /* | 965 | /* |
| @@ -917,9 +973,9 @@ out_unlock: | |||
| 917 | mutex_unlock(&wl->mutex); | 973 | mutex_unlock(&wl->mutex); |
| 918 | } | 974 | } |
| 919 | 975 | ||
| 920 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 976 | static int wlcore_fw_wakeup(struct wl1271 *wl) |
| 921 | { | 977 | { |
| 922 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 978 | return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
| 923 | } | 979 | } |
| 924 | 980 | ||
| 925 | static int wl1271_setup(struct wl1271 *wl) | 981 | static int wl1271_setup(struct wl1271 *wl) |
| @@ -955,13 +1011,21 @@ static int wl12xx_set_power_on(struct wl1271 *wl) | |||
| 955 | wl1271_io_reset(wl); | 1011 | wl1271_io_reset(wl); |
| 956 | wl1271_io_init(wl); | 1012 | wl1271_io_init(wl); |
| 957 | 1013 | ||
| 958 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1014 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
| 1015 | if (ret < 0) | ||
| 1016 | goto fail; | ||
| 959 | 1017 | ||
| 960 | /* ELP module wake up */ | 1018 | /* ELP module wake up */ |
| 961 | wl1271_fw_wakeup(wl); | 1019 | ret = wlcore_fw_wakeup(wl); |
| 1020 | if (ret < 0) | ||
| 1021 | goto fail; | ||
| 962 | 1022 | ||
| 963 | out: | 1023 | out: |
| 964 | return ret; | 1024 | return ret; |
| 1025 | |||
| 1026 | fail: | ||
| 1027 | wl1271_power_off(wl); | ||
| 1028 | return ret; | ||
| 965 | } | 1029 | } |
| 966 | 1030 | ||
| 967 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | 1031 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) |
| @@ -1184,7 +1248,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) | |||
| 1184 | 1248 | ||
| 1185 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | 1249 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ |
| 1186 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | 1250 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) |
| 1187 | wl1271_tx_work_locked(wl); | 1251 | return wlcore_tx_work_locked(wl); |
| 1188 | 1252 | ||
| 1189 | /* | 1253 | /* |
| 1190 | * If the FW TX is busy, TX work will be scheduled by the threaded | 1254 | * If the FW TX is busy, TX work will be scheduled by the threaded |
| @@ -1451,8 +1515,15 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
| 1451 | int i, ret; | 1515 | int i, ret; |
| 1452 | 1516 | ||
| 1453 | if (!wow || wow->any || !wow->n_patterns) { | 1517 | if (!wow || wow->any || !wow->n_patterns) { |
| 1454 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1518 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, |
| 1455 | wl1271_rx_filter_clear_all(wl); | 1519 | FILTER_SIGNAL); |
| 1520 | if (ret) | ||
| 1521 | goto out; | ||
| 1522 | |||
| 1523 | ret = wl1271_rx_filter_clear_all(wl); | ||
| 1524 | if (ret) | ||
| 1525 | goto out; | ||
| 1526 | |||
| 1456 | return 0; | 1527 | return 0; |
| 1457 | } | 1528 | } |
| 1458 | 1529 | ||
| @@ -1468,8 +1539,13 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
| 1468 | } | 1539 | } |
| 1469 | } | 1540 | } |
| 1470 | 1541 | ||
| 1471 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1542 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); |
| 1472 | wl1271_rx_filter_clear_all(wl); | 1543 | if (ret) |
| 1544 | goto out; | ||
| 1545 | |||
| 1546 | ret = wl1271_rx_filter_clear_all(wl); | ||
| 1547 | if (ret) | ||
| 1548 | goto out; | ||
| 1473 | 1549 | ||
| 1474 | /* Translate WoWLAN patterns into filters */ | 1550 | /* Translate WoWLAN patterns into filters */ |
| 1475 | for (i = 0; i < wow->n_patterns; i++) { | 1551 | for (i = 0; i < wow->n_patterns; i++) { |
| @@ -1511,7 +1587,10 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
| 1511 | if (ret < 0) | 1587 | if (ret < 0) |
| 1512 | goto out; | 1588 | goto out; |
| 1513 | 1589 | ||
| 1514 | wl1271_configure_wowlan(wl, wow); | 1590 | ret = wl1271_configure_wowlan(wl, wow); |
| 1591 | if (ret < 0) | ||
| 1592 | goto out_sleep; | ||
| 1593 | |||
| 1515 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1594 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
| 1516 | wl->conf.conn.suspend_wake_up_event, | 1595 | wl->conf.conn.suspend_wake_up_event, |
| 1517 | wl->conf.conn.suspend_listen_interval); | 1596 | wl->conf.conn.suspend_listen_interval); |
| @@ -1519,8 +1598,8 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
| 1519 | if (ret < 0) | 1598 | if (ret < 0) |
| 1520 | wl1271_error("suspend: set wake up conditions failed: %d", ret); | 1599 | wl1271_error("suspend: set wake up conditions failed: %d", ret); |
| 1521 | 1600 | ||
| 1601 | out_sleep: | ||
| 1522 | wl1271_ps_elp_sleep(wl); | 1602 | wl1271_ps_elp_sleep(wl); |
| 1523 | |||
| 1524 | out: | 1603 | out: |
| 1525 | return ret; | 1604 | return ret; |
| 1526 | 1605 | ||
| @@ -1599,6 +1678,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
| 1599 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1678 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
| 1600 | WARN_ON(!wow); | 1679 | WARN_ON(!wow); |
| 1601 | 1680 | ||
| 1681 | /* we want to perform the recovery before suspending */ | ||
| 1682 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
| 1683 | wl1271_warning("postponing suspend to perform recovery"); | ||
| 1684 | return -EBUSY; | ||
| 1685 | } | ||
| 1686 | |||
| 1602 | wl1271_tx_flush(wl); | 1687 | wl1271_tx_flush(wl); |
| 1603 | 1688 | ||
| 1604 | mutex_lock(&wl->mutex); | 1689 | mutex_lock(&wl->mutex); |
| @@ -1639,7 +1724,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
| 1639 | struct wl1271 *wl = hw->priv; | 1724 | struct wl1271 *wl = hw->priv; |
| 1640 | struct wl12xx_vif *wlvif; | 1725 | struct wl12xx_vif *wlvif; |
| 1641 | unsigned long flags; | 1726 | unsigned long flags; |
| 1642 | bool run_irq_work = false; | 1727 | bool run_irq_work = false, pending_recovery; |
| 1728 | int ret; | ||
| 1643 | 1729 | ||
| 1644 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | 1730 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", |
| 1645 | wl->wow_enabled); | 1731 | wl->wow_enabled); |
| @@ -1655,17 +1741,37 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
| 1655 | run_irq_work = true; | 1741 | run_irq_work = true; |
| 1656 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1742 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
| 1657 | 1743 | ||
| 1744 | mutex_lock(&wl->mutex); | ||
| 1745 | |||
| 1746 | /* test the recovery flag before calling any SDIO functions */ | ||
| 1747 | pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
| 1748 | &wl->flags); | ||
| 1749 | |||
| 1658 | if (run_irq_work) { | 1750 | if (run_irq_work) { |
| 1659 | wl1271_debug(DEBUG_MAC80211, | 1751 | wl1271_debug(DEBUG_MAC80211, |
| 1660 | "run postponed irq_work directly"); | 1752 | "run postponed irq_work directly"); |
| 1661 | wl1271_irq(0, wl); | 1753 | |
| 1754 | /* don't talk to the HW if recovery is pending */ | ||
| 1755 | if (!pending_recovery) { | ||
| 1756 | ret = wlcore_irq_locked(wl); | ||
| 1757 | if (ret) | ||
| 1758 | wl12xx_queue_recovery_work(wl); | ||
| 1759 | } | ||
| 1760 | |||
| 1662 | wlcore_enable_interrupts(wl); | 1761 | wlcore_enable_interrupts(wl); |
| 1663 | } | 1762 | } |
| 1664 | 1763 | ||
| 1665 | mutex_lock(&wl->mutex); | 1764 | if (pending_recovery) { |
| 1765 | wl1271_warning("queuing forgotten recovery on resume"); | ||
| 1766 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
| 1767 | goto out; | ||
| 1768 | } | ||
| 1769 | |||
| 1666 | wl12xx_for_each_wlvif(wl, wlvif) { | 1770 | wl12xx_for_each_wlvif(wl, wlvif) { |
| 1667 | wl1271_configure_resume(wl, wlvif); | 1771 | wl1271_configure_resume(wl, wlvif); |
| 1668 | } | 1772 | } |
| 1773 | |||
| 1774 | out: | ||
| 1669 | wl->wow_enabled = false; | 1775 | wl->wow_enabled = false; |
| 1670 | mutex_unlock(&wl->mutex); | 1776 | mutex_unlock(&wl->mutex); |
| 1671 | 1777 | ||
| @@ -1706,6 +1812,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
| 1706 | wlcore_disable_interrupts(wl); | 1812 | wlcore_disable_interrupts(wl); |
| 1707 | mutex_lock(&wl->mutex); | 1813 | mutex_lock(&wl->mutex); |
| 1708 | if (wl->state == WL1271_STATE_OFF) { | 1814 | if (wl->state == WL1271_STATE_OFF) { |
| 1815 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
| 1816 | &wl->flags)) | ||
| 1817 | wlcore_enable_interrupts(wl); | ||
| 1818 | |||
| 1709 | mutex_unlock(&wl->mutex); | 1819 | mutex_unlock(&wl->mutex); |
| 1710 | 1820 | ||
| 1711 | /* | 1821 | /* |
| @@ -1737,6 +1847,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
| 1737 | mutex_lock(&wl->mutex); | 1847 | mutex_lock(&wl->mutex); |
| 1738 | 1848 | ||
| 1739 | wl1271_power_off(wl); | 1849 | wl1271_power_off(wl); |
| 1850 | /* | ||
| 1851 | * In case a recovery was scheduled, interrupts were disabled to avoid | ||
| 1852 | * an interrupt storm. Now that the power is down, it is safe to | ||
| 1853 | * re-enable interrupts to balance the disable depth | ||
| 1854 | */ | ||
| 1855 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
| 1856 | wlcore_enable_interrupts(wl); | ||
| 1740 | 1857 | ||
| 1741 | wl->band = IEEE80211_BAND_2GHZ; | 1858 | wl->band = IEEE80211_BAND_2GHZ; |
| 1742 | 1859 | ||
| @@ -2475,7 +2592,10 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 2475 | (wlvif->channel != channel) || | 2592 | (wlvif->channel != channel) || |
| 2476 | (wlvif->channel_type != conf->channel_type))) { | 2593 | (wlvif->channel_type != conf->channel_type))) { |
| 2477 | /* send all pending packets */ | 2594 | /* send all pending packets */ |
| 2478 | wl1271_tx_work_locked(wl); | 2595 | ret = wlcore_tx_work_locked(wl); |
| 2596 | if (ret < 0) | ||
| 2597 | return ret; | ||
| 2598 | |||
| 2479 | wlvif->band = conf->channel->band; | 2599 | wlvif->band = conf->channel->band; |
| 2480 | wlvif->channel = channel; | 2600 | wlvif->channel = channel; |
| 2481 | wlvif->channel_type = conf->channel_type; | 2601 | wlvif->channel_type = conf->channel_type; |
| @@ -4934,18 +5054,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl) | |||
| 4934 | if (ret < 0) | 5054 | if (ret < 0) |
| 4935 | goto out; | 5055 | goto out; |
| 4936 | 5056 | ||
| 4937 | wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 5057 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id); |
| 5058 | if (ret < 0) | ||
| 5059 | goto out; | ||
| 4938 | 5060 | ||
| 4939 | wl->fuse_oui_addr = 0; | 5061 | wl->fuse_oui_addr = 0; |
| 4940 | wl->fuse_nic_addr = 0; | 5062 | wl->fuse_nic_addr = 0; |
| 4941 | 5063 | ||
| 4942 | wl->hw_pg_ver = wl->ops->get_pg_ver(wl); | 5064 | ret = wl->ops->get_pg_ver(wl, &wl->hw_pg_ver); |
| 5065 | if (ret < 0) | ||
| 5066 | goto out; | ||
| 4943 | 5067 | ||
| 4944 | if (wl->ops->get_mac) | 5068 | if (wl->ops->get_mac) |
| 4945 | wl->ops->get_mac(wl); | 5069 | ret = wl->ops->get_mac(wl); |
| 4946 | 5070 | ||
| 4947 | wl1271_power_off(wl); | ||
| 4948 | out: | 5071 | out: |
| 5072 | wl1271_power_off(wl); | ||
| 4949 | return ret; | 5073 | return ret; |
| 4950 | } | 5074 | } |
| 4951 | 5075 | ||
| @@ -5372,7 +5496,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
| 5372 | else | 5496 | else |
| 5373 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 5497 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
| 5374 | 5498 | ||
| 5375 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, | 5499 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, |
| 5376 | irqflags, | 5500 | irqflags, |
| 5377 | pdev->name, wl); | 5501 | pdev->name, wl); |
| 5378 | if (ret < 0) { | 5502 | if (ret < 0) { |
| @@ -5398,12 +5522,12 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
| 5398 | ret = wl12xx_get_hw_info(wl); | 5522 | ret = wl12xx_get_hw_info(wl); |
| 5399 | if (ret < 0) { | 5523 | if (ret < 0) { |
| 5400 | wl1271_error("couldn't get hw info"); | 5524 | wl1271_error("couldn't get hw info"); |
| 5401 | goto out; | 5525 | goto out_irq; |
| 5402 | } | 5526 | } |
| 5403 | 5527 | ||
| 5404 | ret = wl->ops->identify_chip(wl); | 5528 | ret = wl->ops->identify_chip(wl); |
| 5405 | if (ret < 0) | 5529 | if (ret < 0) |
| 5406 | goto out; | 5530 | goto out_irq; |
| 5407 | 5531 | ||
| 5408 | ret = wl1271_init_ieee80211(wl); | 5532 | ret = wl1271_init_ieee80211(wl); |
| 5409 | if (ret) | 5533 | if (ret) |
| @@ -5417,7 +5541,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
| 5417 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); | 5541 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); |
| 5418 | if (ret < 0) { | 5542 | if (ret < 0) { |
| 5419 | wl1271_error("failed to create sysfs file bt_coex_state"); | 5543 | wl1271_error("failed to create sysfs file bt_coex_state"); |
| 5420 | goto out_irq; | 5544 | goto out_unreg; |
| 5421 | } | 5545 | } |
| 5422 | 5546 | ||
| 5423 | /* Create sysfs file to get HW PG version */ | 5547 | /* Create sysfs file to get HW PG version */ |
| @@ -5442,6 +5566,9 @@ out_hw_pg_ver: | |||
| 5442 | out_bt_coex_state: | 5566 | out_bt_coex_state: |
| 5443 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); | 5567 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); |
| 5444 | 5568 | ||
| 5569 | out_unreg: | ||
| 5570 | wl1271_unregister_hw(wl); | ||
| 5571 | |||
| 5445 | out_irq: | 5572 | out_irq: |
| 5446 | free_irq(wl->irq, wl); | 5573 | free_irq(wl->irq, wl); |
| 5447 | 5574 | ||
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 95d8797cfa28..46d36fd30eba 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
| @@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work) | |||
| 35 | struct delayed_work *dwork; | 35 | struct delayed_work *dwork; |
| 36 | struct wl1271 *wl; | 36 | struct wl1271 *wl; |
| 37 | struct wl12xx_vif *wlvif; | 37 | struct wl12xx_vif *wlvif; |
| 38 | int ret; | ||
| 38 | 39 | ||
| 39 | dwork = container_of(work, struct delayed_work, work); | 40 | dwork = container_of(work, struct delayed_work, work); |
| 40 | wl = container_of(dwork, struct wl1271, elp_work); | 41 | wl = container_of(dwork, struct wl1271, elp_work); |
| @@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work) | |||
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 66 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
| 66 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); | 67 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); |
| 68 | if (ret < 0) { | ||
| 69 | wl12xx_queue_recovery_work(wl); | ||
| 70 | goto out; | ||
| 71 | } | ||
| 72 | |||
| 67 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); | 73 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
| 68 | 74 | ||
| 69 | out: | 75 | out: |
| @@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
| 135 | wl->elp_compl = &compl; | 141 | wl->elp_compl = &compl; |
| 136 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 142 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
| 137 | 143 | ||
| 138 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 144 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
| 145 | if (ret < 0) { | ||
| 146 | wl12xx_queue_recovery_work(wl); | ||
| 147 | goto err; | ||
| 148 | } | ||
| 139 | 149 | ||
| 140 | if (!pending) { | 150 | if (!pending) { |
| 141 | ret = wait_for_completion_timeout( | 151 | ret = wait_for_completion_timeout( |
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index a1db4e032409..f55e2f9e7ac5 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
| @@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
| 200 | return is_data; | 200 | return is_data; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | 203 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) |
| 204 | { | 204 | { |
| 205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
| 206 | u32 buf_size; | 206 | u32 buf_size; |
| @@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
| 211 | u32 pkt_offset, des; | 211 | u32 pkt_offset, des; |
| 212 | u8 hlid; | 212 | u8 hlid; |
| 213 | enum wl_rx_buf_align rx_align; | 213 | enum wl_rx_buf_align rx_align; |
| 214 | int ret = 0; | ||
| 214 | 215 | ||
| 215 | while (drv_rx_counter != fw_rx_counter) { | 216 | while (drv_rx_counter != fw_rx_counter) { |
| 216 | buf_size = 0; | 217 | buf_size = 0; |
| @@ -234,9 +235,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
| 234 | 235 | ||
| 235 | /* Read all available packets at once */ | 236 | /* Read all available packets at once */ |
| 236 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); | 237 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); |
| 237 | wlcore_hw_prepare_read(wl, des, buf_size); | 238 | ret = wlcore_hw_prepare_read(wl, des, buf_size); |
| 238 | wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 239 | if (ret < 0) |
| 239 | buf_size, true); | 240 | goto out; |
| 241 | |||
| 242 | ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | ||
| 243 | buf_size, true); | ||
| 244 | if (ret < 0) | ||
| 245 | goto out; | ||
| 240 | 246 | ||
| 241 | /* Split data into separate packets */ | 247 | /* Split data into separate packets */ |
| 242 | pkt_offset = 0; | 248 | pkt_offset = 0; |
| @@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
| 273 | * Write the driver's packet counter to the FW. This is only required | 279 | * Write the driver's packet counter to the FW. This is only required |
| 274 | * for older hardware revisions | 280 | * for older hardware revisions |
| 275 | */ | 281 | */ |
| 276 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 282 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
| 277 | wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, | 283 | ret = wlcore_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, |
| 278 | wl->rx_counter); | 284 | wl->rx_counter); |
| 285 | if (ret < 0) | ||
| 286 | goto out; | ||
| 287 | } | ||
| 279 | 288 | ||
| 280 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 289 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
| 290 | |||
| 291 | out: | ||
| 292 | return ret; | ||
| 281 | } | 293 | } |
| 282 | 294 | ||
| 283 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
| @@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl, | |||
| 306 | return 0; | 318 | return 0; |
| 307 | } | 319 | } |
| 308 | 320 | ||
| 309 | void wl1271_rx_filter_clear_all(struct wl1271 *wl) | 321 | int wl1271_rx_filter_clear_all(struct wl1271 *wl) |
| 310 | { | 322 | { |
| 311 | int i; | 323 | int i, ret = 0; |
| 312 | 324 | ||
| 313 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { | 325 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { |
| 314 | if (!wl->rx_filter_enabled[i]) | 326 | if (!wl->rx_filter_enabled[i]) |
| 315 | continue; | 327 | continue; |
| 316 | wl1271_rx_filter_enable(wl, i, 0, NULL); | 328 | ret = wl1271_rx_filter_enable(wl, i, 0, NULL); |
| 329 | if (ret) | ||
| 330 | goto out; | ||
| 317 | } | 331 | } |
| 332 | |||
| 333 | out: | ||
| 334 | return ret; | ||
| 318 | } | 335 | } |
| 319 | #endif /* CONFIG_PM */ | 336 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 4324a427e835..71eba1899915 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
| @@ -143,11 +143,11 @@ struct wl1271_rx_descriptor { | |||
| 143 | u8 reserved; | 143 | u8 reserved; |
| 144 | } __packed; | 144 | } __packed; |
| 145 | 145 | ||
| 146 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); | 146 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); |
| 147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
| 148 | int wl1271_rx_filter_enable(struct wl1271 *wl, | 148 | int wl1271_rx_filter_enable(struct wl1271 *wl, |
| 149 | int index, bool enable, | 149 | int index, bool enable, |
| 150 | struct wl12xx_rx_filter *filter); | 150 | struct wl12xx_rx_filter *filter); |
| 151 | void wl1271_rx_filter_clear_all(struct wl1271 *wl); | 151 | int wl1271_rx_filter_clear_all(struct wl1271 *wl); |
| 152 | 152 | ||
| 153 | #endif | 153 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index c67ec482e445..204e69fa9327 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
| @@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child, | |||
| 71 | sdio_release_host(func); | 71 | sdio_release_host(func); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | 74 | static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr, |
| 75 | size_t len, bool fixed) | 75 | void *buf, size_t len, bool fixed) |
| 76 | { | 76 | { |
| 77 | int ret; | 77 | int ret; |
| 78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
| @@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
| 103 | 103 | ||
| 104 | sdio_release_host(func); | 104 | sdio_release_host(func); |
| 105 | 105 | ||
| 106 | if (ret) | 106 | if (WARN_ON(ret)) |
| 107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); | 107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); |
| 108 | |||
| 109 | return ret; | ||
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | 112 | static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr, |
| 111 | size_t len, bool fixed) | 113 | void *buf, size_t len, bool fixed) |
| 112 | { | 114 | { |
| 113 | int ret; | 115 | int ret; |
| 114 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 116 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
| @@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
| 139 | 141 | ||
| 140 | sdio_release_host(func); | 142 | sdio_release_host(func); |
| 141 | 143 | ||
| 142 | if (ret) | 144 | if (WARN_ON(ret)) |
| 143 | dev_err(child->parent, "sdio write failed (%d)\n", ret); | 145 | dev_err(child->parent, "sdio write failed (%d)\n", ret); |
| 146 | |||
| 147 | return ret; | ||
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) | 150 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) |
| 147 | { | 151 | { |
| 148 | int ret; | 152 | int ret; |
| 149 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 153 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
| 154 | struct mmc_card *card = func->card; | ||
| 150 | 155 | ||
| 151 | /* If enabled, tell runtime PM not to power off the card */ | 156 | ret = pm_runtime_get_sync(&card->dev); |
| 152 | if (pm_runtime_enabled(&func->dev)) { | 157 | if (ret) { |
| 153 | ret = pm_runtime_get_sync(&func->dev); | 158 | /* |
| 154 | if (ret < 0) | 159 | * Runtime PM might be temporarily disabled, or the device |
| 155 | goto out; | 160 | * might have a positive reference counter. Make sure it is |
| 156 | } else { | 161 | * really powered on. |
| 157 | /* Runtime PM is disabled: power up the card manually */ | 162 | */ |
| 158 | ret = mmc_power_restore_host(func->card->host); | 163 | ret = mmc_power_restore_host(card->host); |
| 159 | if (ret < 0) | 164 | if (ret < 0) { |
| 165 | pm_runtime_put_sync(&card->dev); | ||
| 160 | goto out; | 166 | goto out; |
| 167 | } | ||
| 161 | } | 168 | } |
| 162 | 169 | ||
| 163 | sdio_claim_host(func); | 170 | sdio_claim_host(func); |
| @@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) | |||
| 172 | { | 179 | { |
| 173 | int ret; | 180 | int ret; |
| 174 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 181 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
| 182 | struct mmc_card *card = func->card; | ||
| 175 | 183 | ||
| 176 | sdio_claim_host(func); | 184 | sdio_claim_host(func); |
| 177 | sdio_disable_func(func); | 185 | sdio_disable_func(func); |
| 178 | sdio_release_host(func); | 186 | sdio_release_host(func); |
| 179 | 187 | ||
| 180 | /* Power off the card manually, even if runtime PM is enabled. */ | 188 | /* Power off the card manually in case it wasn't powered off above */ |
| 181 | ret = mmc_power_save_host(func->card->host); | 189 | ret = mmc_power_save_host(card->host); |
| 182 | if (ret < 0) | 190 | if (ret < 0) |
| 183 | return ret; | 191 | goto out; |
| 184 | 192 | ||
| 185 | /* If enabled, let runtime PM know the card is powered off */ | 193 | /* Let runtime PM know the card is powered off */ |
| 186 | if (pm_runtime_enabled(&func->dev)) | 194 | pm_runtime_put_sync(&card->dev); |
| 187 | ret = pm_runtime_put_sync(&func->dev); | ||
| 188 | 195 | ||
| 196 | out: | ||
| 189 | return ret; | 197 | return ret; |
| 190 | } | 198 | } |
| 191 | 199 | ||
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 553cd3cbb98c..6420abae40ee 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
| @@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child) | |||
| 193 | return -ETIMEDOUT; | 193 | return -ETIMEDOUT; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | 196 | static int __must_check wl12xx_spi_raw_read(struct device *child, int addr, |
| 197 | size_t len, bool fixed) | 197 | void *buf, size_t len, bool fixed) |
| 198 | { | 198 | { |
| 199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
| 200 | struct wl1271 *wl = dev_get_drvdata(child); | 200 | struct wl1271 *wl = dev_get_drvdata(child); |
| @@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
| 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
| 239 | wl12xx_spi_read_busy(child)) { | 239 | wl12xx_spi_read_busy(child)) { |
| 240 | memset(buf, 0, chunk_len); | 240 | memset(buf, 0, chunk_len); |
| 241 | return; | 241 | return 0; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | spi_message_init(&m); | 244 | spi_message_init(&m); |
| @@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
| 256 | buf += chunk_len; | 256 | buf += chunk_len; |
| 257 | len -= chunk_len; | 257 | len -= chunk_len; |
| 258 | } | 258 | } |
| 259 | |||
| 260 | return 0; | ||
| 259 | } | 261 | } |
| 260 | 262 | ||
| 261 | static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | 263 | static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, |
| 262 | size_t len, bool fixed) | 264 | void *buf, size_t len, bool fixed) |
| 263 | { | 265 | { |
| 264 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 266 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
| 265 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; | 267 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; |
| @@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | |||
| 304 | } | 306 | } |
| 305 | 307 | ||
| 306 | spi_sync(to_spi_device(glue->dev), &m); | 308 | spi_sync(to_spi_device(glue->dev), &m); |
| 309 | |||
| 310 | return 0; | ||
| 307 | } | 311 | } |
| 308 | 312 | ||
| 309 | static struct wl1271_if_operations spi_ops = { | 313 | static struct wl1271_if_operations spi_ops = { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 8ee82b9f93f4..6a28aeecf004 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
| @@ -352,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 352 | bool is_dummy; | 352 | bool is_dummy; |
| 353 | bool is_gem = false; | 353 | bool is_gem = false; |
| 354 | 354 | ||
| 355 | if (!skb) | 355 | if (!skb) { |
| 356 | wl1271_error("discarding null skb"); | ||
| 356 | return -EINVAL; | 357 | return -EINVAL; |
| 358 | } | ||
| 357 | 359 | ||
| 358 | info = IEEE80211_SKB_CB(skb); | 360 | info = IEEE80211_SKB_CB(skb); |
| 359 | 361 | ||
| @@ -662,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) | |||
| 662 | } | 664 | } |
| 663 | } | 665 | } |
| 664 | 666 | ||
| 665 | void wl1271_tx_work_locked(struct wl1271 *wl) | 667 | /* |
| 668 | * Returns failure values only in case of failed bus ops within this function. | ||
| 669 | * wl1271_prepare_tx_frame retvals won't be returned in order to avoid | ||
| 670 | * triggering recovery by higher layers when not necessary. | ||
| 671 | * In case a FW command fails within wl1271_prepare_tx_frame fails a recovery | ||
| 672 | * will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame | ||
| 673 | * can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING | ||
| 674 | * within prepare_tx_frame code but there's nothing we should do about those | ||
| 675 | * as well. | ||
| 676 | */ | ||
| 677 | int wlcore_tx_work_locked(struct wl1271 *wl) | ||
| 666 | { | 678 | { |
| 667 | struct wl12xx_vif *wlvif; | 679 | struct wl12xx_vif *wlvif; |
| 668 | struct sk_buff *skb; | 680 | struct sk_buff *skb; |
| @@ -670,10 +682,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
| 670 | u32 buf_offset = 0, last_len = 0; | 682 | u32 buf_offset = 0, last_len = 0; |
| 671 | bool sent_packets = false; | 683 | bool sent_packets = false; |
| 672 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 684 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
| 673 | int ret; | 685 | int ret = 0; |
| 686 | int bus_ret = 0; | ||
| 674 | 687 | ||
| 675 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 688 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
| 676 | return; | 689 | return 0; |
| 677 | 690 | ||
| 678 | while ((skb = wl1271_skb_dequeue(wl))) { | 691 | while ((skb = wl1271_skb_dequeue(wl))) { |
| 679 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 692 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| @@ -694,8 +707,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
| 694 | 707 | ||
| 695 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, | 708 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, |
| 696 | last_len); | 709 | last_len); |
| 697 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 710 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, |
| 698 | buf_offset, true); | 711 | wl->aggr_buf, buf_offset, true); |
| 712 | if (bus_ret < 0) | ||
| 713 | goto out; | ||
| 714 | |||
| 699 | sent_packets = true; | 715 | sent_packets = true; |
| 700 | buf_offset = 0; | 716 | buf_offset = 0; |
| 701 | continue; | 717 | continue; |
| @@ -731,8 +747,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
| 731 | out_ack: | 747 | out_ack: |
| 732 | if (buf_offset) { | 748 | if (buf_offset) { |
| 733 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); | 749 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); |
| 734 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 750 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
| 735 | buf_offset, true); | 751 | buf_offset, true); |
| 752 | if (bus_ret < 0) | ||
| 753 | goto out; | ||
| 754 | |||
| 736 | sent_packets = true; | 755 | sent_packets = true; |
| 737 | } | 756 | } |
| 738 | if (sent_packets) { | 757 | if (sent_packets) { |
| @@ -740,13 +759,19 @@ out_ack: | |||
| 740 | * Interrupt the firmware with the new packets. This is only | 759 | * Interrupt the firmware with the new packets. This is only |
| 741 | * required for older hardware revisions | 760 | * required for older hardware revisions |
| 742 | */ | 761 | */ |
| 743 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 762 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
| 744 | wl1271_write32(wl, WL12XX_HOST_WR_ACCESS, | 763 | bus_ret = wlcore_write32(wl, WL12XX_HOST_WR_ACCESS, |
| 745 | wl->tx_packets_count); | 764 | wl->tx_packets_count); |
| 765 | if (bus_ret < 0) | ||
| 766 | goto out; | ||
| 767 | } | ||
| 746 | 768 | ||
| 747 | wl1271_handle_tx_low_watermark(wl); | 769 | wl1271_handle_tx_low_watermark(wl); |
| 748 | } | 770 | } |
| 749 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 771 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
| 772 | |||
| 773 | out: | ||
| 774 | return bus_ret; | ||
| 750 | } | 775 | } |
| 751 | 776 | ||
| 752 | void wl1271_tx_work(struct work_struct *work) | 777 | void wl1271_tx_work(struct work_struct *work) |
| @@ -759,7 +784,11 @@ void wl1271_tx_work(struct work_struct *work) | |||
| 759 | if (ret < 0) | 784 | if (ret < 0) |
| 760 | goto out; | 785 | goto out; |
| 761 | 786 | ||
| 762 | wl1271_tx_work_locked(wl); | 787 | ret = wlcore_tx_work_locked(wl); |
| 788 | if (ret < 0) { | ||
| 789 | wl12xx_queue_recovery_work(wl); | ||
| 790 | goto out; | ||
| 791 | } | ||
| 763 | 792 | ||
| 764 | wl1271_ps_elp_sleep(wl); | 793 | wl1271_ps_elp_sleep(wl); |
| 765 | out: | 794 | out: |
| @@ -881,22 +910,28 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
| 881 | } | 910 | } |
| 882 | 911 | ||
| 883 | /* Called upon reception of a TX complete interrupt */ | 912 | /* Called upon reception of a TX complete interrupt */ |
| 884 | void wl1271_tx_complete(struct wl1271 *wl) | 913 | int wlcore_tx_complete(struct wl1271 *wl) |
| 885 | { | 914 | { |
| 886 | struct wl1271_acx_mem_map *memmap = | 915 | struct wl1271_acx_mem_map *memmap = |
| 887 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 916 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
| 888 | u32 count, fw_counter; | 917 | u32 count, fw_counter; |
| 889 | u32 i; | 918 | u32 i; |
| 919 | int ret; | ||
| 890 | 920 | ||
| 891 | /* read the tx results from the chipset */ | 921 | /* read the tx results from the chipset */ |
| 892 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 922 | ret = wlcore_read(wl, le32_to_cpu(memmap->tx_result), |
| 893 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 923 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
| 924 | if (ret < 0) | ||
| 925 | goto out; | ||
| 926 | |||
| 894 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | 927 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); |
| 895 | 928 | ||
| 896 | /* write host counter to chipset (to ack) */ | 929 | /* write host counter to chipset (to ack) */ |
| 897 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 930 | ret = wlcore_write32(wl, le32_to_cpu(memmap->tx_result) + |
| 898 | offsetof(struct wl1271_tx_hw_res_if, | 931 | offsetof(struct wl1271_tx_hw_res_if, |
| 899 | tx_result_host_counter), fw_counter); | 932 | tx_result_host_counter), fw_counter); |
| 933 | if (ret < 0) | ||
| 934 | goto out; | ||
| 900 | 935 | ||
| 901 | count = fw_counter - wl->tx_results_count; | 936 | count = fw_counter - wl->tx_results_count; |
| 902 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 937 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
| @@ -916,8 +951,11 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
| 916 | 951 | ||
| 917 | wl->tx_results_count++; | 952 | wl->tx_results_count++; |
| 918 | } | 953 | } |
| 954 | |||
| 955 | out: | ||
| 956 | return ret; | ||
| 919 | } | 957 | } |
| 920 | EXPORT_SYMBOL(wl1271_tx_complete); | 958 | EXPORT_SYMBOL(wlcore_tx_complete); |
| 921 | 959 | ||
| 922 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 960 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
| 923 | { | 961 | { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index fa4be1b91135..1e939b016155 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
| @@ -234,8 +234,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) | |||
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | void wl1271_tx_work(struct work_struct *work); | 236 | void wl1271_tx_work(struct work_struct *work); |
| 237 | void wl1271_tx_work_locked(struct wl1271 *wl); | 237 | int wlcore_tx_work_locked(struct wl1271 *wl); |
| 238 | void wl1271_tx_complete(struct wl1271 *wl); | 238 | int wlcore_tx_complete(struct wl1271 *wl); |
| 239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
| 240 | void wl12xx_tx_reset(struct wl1271 *wl); | 240 | void wl12xx_tx_reset(struct wl1271 *wl); |
| 241 | void wl1271_tx_flush(struct wl1271 *wl); | 241 | void wl1271_tx_flush(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 205d8ad2b761..e796974df59b 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
| @@ -41,9 +41,9 @@ struct wlcore_ops { | |||
| 41 | int (*identify_fw)(struct wl1271 *wl); | 41 | int (*identify_fw)(struct wl1271 *wl); |
| 42 | int (*boot)(struct wl1271 *wl); | 42 | int (*boot)(struct wl1271 *wl); |
| 43 | int (*plt_init)(struct wl1271 *wl); | 43 | int (*plt_init)(struct wl1271 *wl); |
| 44 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | 44 | int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, |
| 45 | void *buf, size_t len); | 45 | void *buf, size_t len); |
| 46 | void (*ack_event)(struct wl1271 *wl); | 46 | int (*ack_event)(struct wl1271 *wl); |
| 47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); | 47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); |
| 48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, | 48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, |
| 49 | struct wl1271_tx_hw_descr *desc, | 49 | struct wl1271_tx_hw_descr *desc, |
| @@ -53,17 +53,17 @@ struct wlcore_ops { | |||
| 53 | struct sk_buff *skb); | 53 | struct sk_buff *skb); |
| 54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, | 54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, |
| 55 | u32 rx_desc); | 55 | u32 rx_desc); |
| 56 | void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); | 56 | int (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); |
| 57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, | 57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, |
| 58 | u32 data_len); | 58 | u32 data_len); |
| 59 | void (*tx_delayed_compl)(struct wl1271 *wl); | 59 | int (*tx_delayed_compl)(struct wl1271 *wl); |
| 60 | void (*tx_immediate_compl)(struct wl1271 *wl); | 60 | void (*tx_immediate_compl)(struct wl1271 *wl); |
| 61 | int (*hw_init)(struct wl1271 *wl); | 61 | int (*hw_init)(struct wl1271 *wl); |
| 62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
| 63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, | 63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, |
| 64 | struct wl12xx_vif *wlvif); | 64 | struct wl12xx_vif *wlvif); |
| 65 | s8 (*get_pg_ver)(struct wl1271 *wl); | 65 | int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); |
| 66 | void (*get_mac)(struct wl1271 *wl); | 66 | int (*get_mac)(struct wl1271 *wl); |
| 67 | void (*set_tx_desc_csum)(struct wl1271 *wl, | 67 | void (*set_tx_desc_csum)(struct wl1271 *wl, |
| 68 | struct wl1271_tx_hw_descr *desc, | 68 | struct wl1271_tx_hw_descr *desc, |
| 69 | struct sk_buff *skb); | 69 | struct sk_buff *skb); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 8260b1e9288a..4273a21cdde1 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
| @@ -209,10 +209,10 @@ struct wl1271_scan { | |||
| 209 | }; | 209 | }; |
| 210 | 210 | ||
| 211 | struct wl1271_if_operations { | 211 | struct wl1271_if_operations { |
| 212 | void (*read)(struct device *child, int addr, void *buf, size_t len, | 212 | int __must_check (*read)(struct device *child, int addr, void *buf, |
| 213 | bool fixed); | 213 | size_t len, bool fixed); |
| 214 | void (*write)(struct device *child, int addr, void *buf, size_t len, | 214 | int __must_check (*write)(struct device *child, int addr, void *buf, |
| 215 | bool fixed); | 215 | size_t len, bool fixed); |
| 216 | void (*reset)(struct device *child); | 216 | void (*reset)(struct device *child); |
| 217 | void (*init)(struct device *child); | 217 | void (*init)(struct device *child); |
| 218 | int (*power)(struct device *child, bool enable); | 218 | int (*power)(struct device *child, bool enable); |
| @@ -247,6 +247,7 @@ enum wl12xx_flags { | |||
| 247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, | 247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, |
| 248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, | 248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, |
| 249 | WL1271_FLAG_INTENDED_FW_RECOVERY, | 249 | WL1271_FLAG_INTENDED_FW_RECOVERY, |
| 250 | WL1271_FLAG_SDIO_FAILED, | ||
| 250 | }; | 251 | }; |
| 251 | 252 | ||
| 252 | enum wl12xx_vif_flags { | 253 | enum wl12xx_vif_flags { |
